fix(matrix): fix sending being broken by normalizing thread ID normalization in message sending functions; improve matrix types
This commit is contained in:
committed by
Peter Steinberger
parent
30c945fe92
commit
c49b6cc241
@@ -7,15 +7,17 @@
|
|||||||
* - m.poll.end - Closes a poll
|
* - m.poll.end - Closes a poll
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { TimelineEvents } from "matrix-js-sdk/lib/@types/event.js";
|
||||||
|
import type { ExtensibleAnyMessageEventContent } from "matrix-js-sdk/lib/@types/extensible_events.js";
|
||||||
import type { PollInput } from "../../../../src/polls.js";
|
import type { PollInput } from "../../../../src/polls.js";
|
||||||
|
|
||||||
export const M_POLL_START = "m.poll.start";
|
export const M_POLL_START = "m.poll.start" as const;
|
||||||
export const M_POLL_RESPONSE = "m.poll.response";
|
export const M_POLL_RESPONSE = "m.poll.response" as const;
|
||||||
export const M_POLL_END = "m.poll.end";
|
export const M_POLL_END = "m.poll.end" as const;
|
||||||
|
|
||||||
export const ORG_POLL_START = "org.matrix.msc3381.poll.start";
|
export const ORG_POLL_START = "org.matrix.msc3381.poll.start" as const;
|
||||||
export const ORG_POLL_RESPONSE = "org.matrix.msc3381.poll.response";
|
export const ORG_POLL_RESPONSE = "org.matrix.msc3381.poll.response" as const;
|
||||||
export const ORG_POLL_END = "org.matrix.msc3381.poll.end";
|
export const ORG_POLL_END = "org.matrix.msc3381.poll.end" as const;
|
||||||
|
|
||||||
export const POLL_EVENT_TYPES = [
|
export const POLL_EVENT_TYPES = [
|
||||||
M_POLL_START,
|
M_POLL_START,
|
||||||
@@ -32,9 +34,7 @@ export const POLL_END_TYPES = [M_POLL_END, ORG_POLL_END];
|
|||||||
|
|
||||||
export type PollKind = "m.poll.disclosed" | "m.poll.undisclosed";
|
export type PollKind = "m.poll.disclosed" | "m.poll.undisclosed";
|
||||||
|
|
||||||
export type TextContent = {
|
export type TextContent = ExtensibleAnyMessageEventContent & {
|
||||||
"m.text"?: string;
|
|
||||||
"org.matrix.msc1767.text"?: string;
|
|
||||||
body?: string;
|
body?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,24 +42,7 @@ export type PollAnswer = {
|
|||||||
id: string;
|
id: string;
|
||||||
} & TextContent;
|
} & TextContent;
|
||||||
|
|
||||||
export type PollStartContent = {
|
export type PollStartContent = TimelineEvents[typeof M_POLL_START];
|
||||||
"m.poll"?: {
|
|
||||||
question: TextContent;
|
|
||||||
kind?: PollKind;
|
|
||||||
max_selections?: number;
|
|
||||||
answers: PollAnswer[];
|
|
||||||
};
|
|
||||||
"org.matrix.msc3381.poll.start"?: {
|
|
||||||
question: TextContent;
|
|
||||||
kind?: PollKind;
|
|
||||||
max_selections?: number;
|
|
||||||
answers: PollAnswer[];
|
|
||||||
};
|
|
||||||
"m.relates_to"?: {
|
|
||||||
rel_type: "m.reference";
|
|
||||||
event_id: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PollSummary = {
|
export type PollSummary = {
|
||||||
eventId: string;
|
eventId: string;
|
||||||
@@ -82,7 +65,7 @@ export function getTextContent(text?: TextContent): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parsePollStartContent(content: PollStartContent): PollSummary | null {
|
export function parsePollStartContent(content: PollStartContent): PollSummary | null {
|
||||||
const poll = content["m.poll"] ?? content["org.matrix.msc3381.poll.start"];
|
const poll = content[M_POLL_START] ?? content[ORG_POLL_START];
|
||||||
if (!poll) return null;
|
if (!poll) return null;
|
||||||
|
|
||||||
const question = getTextContent(poll.question);
|
const question = getTextContent(poll.question);
|
||||||
@@ -121,6 +104,11 @@ function buildTextContent(body: string): TextContent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildPollFallbackText(question: string, answers: string[]): string {
|
||||||
|
if (answers.length === 0) return question;
|
||||||
|
return `${question}\n${answers.map((answer, idx) => `${idx + 1}. ${answer}`).join("\n")}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildPollStartContent(poll: PollInput): PollStartContent {
|
export function buildPollStartContent(poll: PollInput): PollStartContent {
|
||||||
const question = poll.question.trim();
|
const question = poll.question.trim();
|
||||||
const answers = poll.options
|
const answers = poll.options
|
||||||
@@ -132,13 +120,19 @@ export function buildPollStartContent(poll: PollInput): PollStartContent {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const maxSelections = poll.multiple ? Math.max(1, answers.length) : 1;
|
const maxSelections = poll.multiple ? Math.max(1, answers.length) : 1;
|
||||||
|
const fallbackText = buildPollFallbackText(
|
||||||
|
question,
|
||||||
|
answers.map((answer) => getTextContent(answer)),
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"m.poll": {
|
[M_POLL_START]: {
|
||||||
question: buildTextContent(question),
|
question: buildTextContent(question),
|
||||||
kind: poll.multiple ? "m.poll.undisclosed" : "m.poll.disclosed",
|
kind: poll.multiple ? "m.poll.undisclosed" : "m.poll.disclosed",
|
||||||
max_selections: maxSelections,
|
max_selections: maxSelections,
|
||||||
answers,
|
answers,
|
||||||
},
|
},
|
||||||
|
"m.text": fallbackText,
|
||||||
|
"org.matrix.msc1767.text": fallbackText,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ function normalizeTarget(raw: string): string {
|
|||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeThreadId(raw?: string | number | null): string | null {
|
||||||
|
if (raw === undefined || raw === null) return null;
|
||||||
|
const trimmed = String(raw).trim();
|
||||||
|
return trimmed ? trimmed : null;
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveDirectRoomId(client: MatrixClient, userId: string): Promise<string> {
|
async function resolveDirectRoomId(client: MatrixClient, userId: string): Promise<string> {
|
||||||
const trimmed = userId.trim();
|
const trimmed = userId.trim();
|
||||||
if (!trimmed.startsWith("@")) {
|
if (!trimmed.startsWith("@")) {
|
||||||
@@ -238,14 +244,10 @@ export async function sendMessageMatrix(
|
|||||||
const textLimit = resolveTextChunkLimit(cfg, "matrix");
|
const textLimit = resolveTextChunkLimit(cfg, "matrix");
|
||||||
const chunkLimit = Math.min(textLimit, MATRIX_TEXT_LIMIT);
|
const chunkLimit = Math.min(textLimit, MATRIX_TEXT_LIMIT);
|
||||||
const chunks = chunkMarkdownText(trimmedMessage, chunkLimit);
|
const chunks = chunkMarkdownText(trimmedMessage, chunkLimit);
|
||||||
const rawThreadId = opts.threadId;
|
const threadId = normalizeThreadId(opts.threadId);
|
||||||
const threadId =
|
|
||||||
rawThreadId !== undefined && rawThreadId !== null
|
|
||||||
? String(rawThreadId).trim()
|
|
||||||
: null;
|
|
||||||
const relation = threadId ? undefined : buildReplyRelation(opts.replyToId);
|
const relation = threadId ? undefined : buildReplyRelation(opts.replyToId);
|
||||||
const sendContent = (content: RoomMessageEventContent) =>
|
const sendContent = (content: RoomMessageEventContent) =>
|
||||||
client.sendMessage(roomId, threadId ?? undefined, content);
|
threadId ? client.sendMessage(roomId, threadId, content) : client.sendMessage(roomId, content);
|
||||||
|
|
||||||
let lastMessageId = "";
|
let lastMessageId = "";
|
||||||
if (opts.mediaUrl) {
|
if (opts.mediaUrl) {
|
||||||
@@ -316,17 +318,19 @@ export async function sendPollMatrix(
|
|||||||
try {
|
try {
|
||||||
const roomId = await resolveMatrixRoomId(client, to);
|
const roomId = await resolveMatrixRoomId(client, to);
|
||||||
const pollContent = buildPollStartContent(poll);
|
const pollContent = buildPollStartContent(poll);
|
||||||
const rawThreadId = opts.threadId;
|
const threadId = normalizeThreadId(opts.threadId);
|
||||||
const threadId =
|
const response = threadId
|
||||||
rawThreadId !== undefined && rawThreadId !== null
|
? await client.sendEvent(
|
||||||
? String(rawThreadId).trim()
|
roomId,
|
||||||
: null;
|
threadId,
|
||||||
const response = await client.sendEvent(
|
M_POLL_START,
|
||||||
roomId,
|
pollContent,
|
||||||
threadId ?? undefined,
|
)
|
||||||
M_POLL_START as EventType.RoomMessage,
|
: await client.sendEvent(
|
||||||
pollContent as unknown as RoomMessageEventContent,
|
roomId,
|
||||||
);
|
M_POLL_START,
|
||||||
|
pollContent,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
eventId: response.event_id ?? "unknown",
|
eventId: response.event_id ?? "unknown",
|
||||||
|
|||||||
Reference in New Issue
Block a user