init
This commit is contained in:
58
node_modules/matrix-js-sdk/src/extensible_events_v1/ExtensibleEvent.ts
generated
vendored
Normal file
58
node_modules/matrix-js-sdk/src/extensible_events_v1/ExtensibleEvent.ts
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2021 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { type ExtensibleEventType, type IPartialEvent } from "../@types/extensible_events.ts";
|
||||
|
||||
/**
|
||||
* Represents an Extensible Event in Matrix.
|
||||
*/
|
||||
export abstract class ExtensibleEvent<TContent extends object = object> {
|
||||
protected constructor(public readonly wireFormat: IPartialEvent<TContent>) {}
|
||||
|
||||
/**
|
||||
* Shortcut to wireFormat.content
|
||||
*/
|
||||
public get wireContent(): TContent {
|
||||
return this.wireFormat.content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the event into a format which can be used to send the
|
||||
* event to the room.
|
||||
* @returns The serialized event.
|
||||
*/
|
||||
public abstract serialize(): IPartialEvent<object>;
|
||||
|
||||
/**
|
||||
* Determines if this event is equivalent to the provided event type.
|
||||
* This is recommended over `instanceof` checks due to issues in the JS
|
||||
* runtime (and layering of dependencies in some projects).
|
||||
*
|
||||
* Implementations should pass this check off to their super classes
|
||||
* if their own checks fail. Some primary implementations do not extend
|
||||
* fallback classes given they support the primary type first. Thus,
|
||||
* those classes may return false if asked about their fallback
|
||||
* representation.
|
||||
*
|
||||
* Note that this only checks primary event types: legacy events, like
|
||||
* m.room.message, should/will fail this check.
|
||||
* @param primaryEventType - The (potentially namespaced) event
|
||||
* type.
|
||||
* @returns True if this event *could* be represented as the
|
||||
* given type.
|
||||
*/
|
||||
public abstract isEquivalentTo(primaryEventType: ExtensibleEventType): boolean;
|
||||
}
|
||||
24
node_modules/matrix-js-sdk/src/extensible_events_v1/InvalidEventError.ts
generated
vendored
Normal file
24
node_modules/matrix-js-sdk/src/extensible_events_v1/InvalidEventError.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2022 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Thrown when an event is unforgivably unparsable.
|
||||
*/
|
||||
export class InvalidEventError extends Error {
|
||||
public constructor(message: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
143
node_modules/matrix-js-sdk/src/extensible_events_v1/MessageEvent.ts
generated
vendored
Normal file
143
node_modules/matrix-js-sdk/src/extensible_events_v1/MessageEvent.ts
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2022 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { ExtensibleEvent } from "./ExtensibleEvent.ts";
|
||||
import {
|
||||
type ExtensibleEventType,
|
||||
type IMessageRendering,
|
||||
type IPartialEvent,
|
||||
isEventTypeSame,
|
||||
M_HTML,
|
||||
M_MESSAGE,
|
||||
type ExtensibleAnyMessageEventContent,
|
||||
M_TEXT,
|
||||
} from "../@types/extensible_events.ts";
|
||||
import { isOptionalAString, isProvided } from "./utilities.ts";
|
||||
import { InvalidEventError } from "./InvalidEventError.ts";
|
||||
|
||||
/**
|
||||
* Represents a message event. Message events are the simplest form of event with
|
||||
* just text (optionally of different mimetypes, like HTML).
|
||||
*
|
||||
* Message events can additionally be an Emote or Notice, though typically those
|
||||
* are represented as EmoteEvent and NoticeEvent respectively.
|
||||
*/
|
||||
export class MessageEvent extends ExtensibleEvent<ExtensibleAnyMessageEventContent> {
|
||||
/**
|
||||
* The default text for the event.
|
||||
*/
|
||||
public readonly text: string;
|
||||
|
||||
/**
|
||||
* The default HTML for the event, if provided.
|
||||
*/
|
||||
public readonly html?: string;
|
||||
|
||||
/**
|
||||
* All the different renderings of the message. Note that this is the same
|
||||
* format as an m.message body but may contain elements not found directly
|
||||
* in the event content: this is because this is interpreted based off the
|
||||
* other information available in the event.
|
||||
*/
|
||||
public readonly renderings: IMessageRendering[];
|
||||
|
||||
/**
|
||||
* Creates a new MessageEvent from a pure format. Note that the event is
|
||||
* *not* parsed here: it will be treated as a literal m.message primary
|
||||
* typed event.
|
||||
* @param wireFormat - The event.
|
||||
*/
|
||||
public constructor(wireFormat: IPartialEvent<ExtensibleAnyMessageEventContent>) {
|
||||
super(wireFormat);
|
||||
|
||||
const mmessage = M_MESSAGE.findIn(this.wireContent);
|
||||
const mtext = M_TEXT.findIn<string>(this.wireContent);
|
||||
const mhtml = M_HTML.findIn<string>(this.wireContent);
|
||||
if (isProvided(mmessage)) {
|
||||
if (!Array.isArray(mmessage)) {
|
||||
throw new InvalidEventError("m.message contents must be an array");
|
||||
}
|
||||
const text = mmessage.find((r) => !isProvided(r.mimetype) || r.mimetype === "text/plain");
|
||||
const html = mmessage.find((r) => r.mimetype === "text/html");
|
||||
|
||||
if (!text) throw new InvalidEventError("m.message is missing a plain text representation");
|
||||
|
||||
this.text = text.body;
|
||||
this.html = html?.body;
|
||||
this.renderings = mmessage;
|
||||
} else if (isOptionalAString(mtext)) {
|
||||
this.text = mtext;
|
||||
this.html = mhtml ?? undefined;
|
||||
this.renderings = [{ body: mtext, mimetype: "text/plain" }];
|
||||
if (this.html) {
|
||||
this.renderings.push({ body: this.html, mimetype: "text/html" });
|
||||
}
|
||||
} else {
|
||||
throw new InvalidEventError("Missing textual representation for event");
|
||||
}
|
||||
}
|
||||
|
||||
public isEquivalentTo(primaryEventType: ExtensibleEventType): boolean {
|
||||
return isEventTypeSame(primaryEventType, M_MESSAGE);
|
||||
}
|
||||
|
||||
protected serializeMMessageOnly(): ExtensibleAnyMessageEventContent {
|
||||
let messageRendering: ExtensibleAnyMessageEventContent = {
|
||||
[M_MESSAGE.name]: this.renderings,
|
||||
};
|
||||
|
||||
// Use the shorthand if it's just a simple text event
|
||||
if (this.renderings.length === 1) {
|
||||
const mime = this.renderings[0].mimetype;
|
||||
if (mime === undefined || mime === "text/plain") {
|
||||
messageRendering = {
|
||||
[M_TEXT.name]: this.renderings[0].body,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return messageRendering;
|
||||
}
|
||||
|
||||
public serialize(): IPartialEvent<object> {
|
||||
return {
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
...this.serializeMMessageOnly(),
|
||||
body: this.text,
|
||||
msgtype: "m.text",
|
||||
format: this.html ? "org.matrix.custom.html" : undefined,
|
||||
formatted_body: this.html ?? undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MessageEvent from text and HTML.
|
||||
* @param text - The text.
|
||||
* @param html - Optional HTML.
|
||||
* @returns The representative message event.
|
||||
*/
|
||||
public static from(text: string, html?: string): MessageEvent {
|
||||
return new MessageEvent({
|
||||
type: M_MESSAGE.name,
|
||||
content: {
|
||||
[M_TEXT.name]: text,
|
||||
[M_HTML.name]: html,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
97
node_modules/matrix-js-sdk/src/extensible_events_v1/PollEndEvent.ts
generated
vendored
Normal file
97
node_modules/matrix-js-sdk/src/extensible_events_v1/PollEndEvent.ts
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2022 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
type ExtensibleEventType,
|
||||
type IPartialEvent,
|
||||
isEventTypeSame,
|
||||
M_TEXT,
|
||||
REFERENCE_RELATION,
|
||||
} from "../@types/extensible_events.ts";
|
||||
import { M_POLL_END, type PollEndEventContent } from "../@types/polls.ts";
|
||||
import { ExtensibleEvent } from "./ExtensibleEvent.ts";
|
||||
import { InvalidEventError } from "./InvalidEventError.ts";
|
||||
import { MessageEvent } from "./MessageEvent.ts";
|
||||
|
||||
/**
|
||||
* Represents a poll end/closure event.
|
||||
*/
|
||||
export class PollEndEvent extends ExtensibleEvent<PollEndEventContent> {
|
||||
/**
|
||||
* The poll start event ID referenced by the response.
|
||||
*/
|
||||
public readonly pollEventId: string;
|
||||
|
||||
/**
|
||||
* The closing message for the event.
|
||||
*/
|
||||
public readonly closingMessage: MessageEvent;
|
||||
|
||||
/**
|
||||
* Creates a new PollEndEvent from a pure format. Note that the event is *not*
|
||||
* parsed here: it will be treated as a literal m.poll.response primary typed event.
|
||||
* @param wireFormat - The event.
|
||||
*/
|
||||
public constructor(wireFormat: IPartialEvent<PollEndEventContent>) {
|
||||
super(wireFormat);
|
||||
|
||||
const rel = this.wireContent["m.relates_to"];
|
||||
if (!REFERENCE_RELATION.matches(rel?.rel_type) || typeof rel?.event_id !== "string") {
|
||||
throw new InvalidEventError("Relationship must be a reference to an event");
|
||||
}
|
||||
|
||||
this.pollEventId = rel.event_id;
|
||||
this.closingMessage = new MessageEvent(this.wireFormat);
|
||||
}
|
||||
|
||||
public isEquivalentTo(primaryEventType: ExtensibleEventType): boolean {
|
||||
return isEventTypeSame(primaryEventType, M_POLL_END);
|
||||
}
|
||||
|
||||
public serialize(): IPartialEvent<object> {
|
||||
return {
|
||||
type: M_POLL_END.name,
|
||||
content: {
|
||||
"m.relates_to": {
|
||||
rel_type: REFERENCE_RELATION.name,
|
||||
event_id: this.pollEventId,
|
||||
},
|
||||
[M_POLL_END.name]: {},
|
||||
...this.closingMessage.serialize().content,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PollEndEvent from a poll event ID.
|
||||
* @param pollEventId - The poll start event ID.
|
||||
* @param message - A closing message, typically revealing the top answer.
|
||||
* @returns The representative poll closure event.
|
||||
*/
|
||||
public static from(pollEventId: string, message: string): PollEndEvent {
|
||||
return new PollEndEvent({
|
||||
type: M_POLL_END.name,
|
||||
content: {
|
||||
"m.relates_to": {
|
||||
rel_type: REFERENCE_RELATION.name,
|
||||
event_id: pollEventId,
|
||||
},
|
||||
[M_POLL_END.name]: {},
|
||||
[M_TEXT.name]: message,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
148
node_modules/matrix-js-sdk/src/extensible_events_v1/PollResponseEvent.ts
generated
vendored
Normal file
148
node_modules/matrix-js-sdk/src/extensible_events_v1/PollResponseEvent.ts
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright 2022 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { ExtensibleEvent } from "./ExtensibleEvent.ts";
|
||||
import { M_POLL_RESPONSE, type PollResponseEventContent, type PollResponseSubtype } from "../@types/polls.ts";
|
||||
import {
|
||||
type ExtensibleEventType,
|
||||
type IPartialEvent,
|
||||
isEventTypeSame,
|
||||
REFERENCE_RELATION,
|
||||
} from "../@types/extensible_events.ts";
|
||||
import { InvalidEventError } from "./InvalidEventError.ts";
|
||||
import { type PollStartEvent } from "./PollStartEvent.ts";
|
||||
|
||||
/**
|
||||
* Represents a poll response event.
|
||||
*/
|
||||
export class PollResponseEvent extends ExtensibleEvent<PollResponseEventContent> {
|
||||
private internalAnswerIds: string[] = [];
|
||||
private internalSpoiled = false;
|
||||
|
||||
/**
|
||||
* The provided answers for the poll. Note that this may be falsy/unpredictable if
|
||||
* the `spoiled` property is true.
|
||||
*/
|
||||
public get answerIds(): string[] {
|
||||
return this.internalAnswerIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* The poll start event ID referenced by the response.
|
||||
*/
|
||||
public readonly pollEventId: string;
|
||||
|
||||
/**
|
||||
* Whether the vote is spoiled.
|
||||
*/
|
||||
public get spoiled(): boolean {
|
||||
return this.internalSpoiled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PollResponseEvent from a pure format. Note that the event is *not*
|
||||
* parsed here: it will be treated as a literal m.poll.response primary typed event.
|
||||
*
|
||||
* To validate the response against a poll, call `validateAgainst` after creation.
|
||||
* @param wireFormat - The event.
|
||||
*/
|
||||
public constructor(wireFormat: IPartialEvent<PollResponseEventContent>) {
|
||||
super(wireFormat);
|
||||
|
||||
const rel = this.wireContent["m.relates_to"];
|
||||
if (!REFERENCE_RELATION.matches(rel?.rel_type) || typeof rel?.event_id !== "string") {
|
||||
throw new InvalidEventError("Relationship must be a reference to an event");
|
||||
}
|
||||
|
||||
this.pollEventId = rel.event_id;
|
||||
this.validateAgainst(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the poll response using the poll start event as a frame of reference. This
|
||||
* is used to determine if the vote is spoiled, whether the answers are valid, etc.
|
||||
* @param poll - The poll start event.
|
||||
*/
|
||||
public validateAgainst(poll: PollStartEvent | null): void {
|
||||
const response = M_POLL_RESPONSE.findIn<PollResponseSubtype>(this.wireContent);
|
||||
if (!Array.isArray(response?.answers)) {
|
||||
this.internalSpoiled = true;
|
||||
this.internalAnswerIds = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let answers = response?.answers ?? [];
|
||||
if (answers.some((a) => typeof a !== "string") || answers.length === 0) {
|
||||
this.internalSpoiled = true;
|
||||
this.internalAnswerIds = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (poll) {
|
||||
if (answers.some((a) => !poll.answers.some((pa) => pa.id === a))) {
|
||||
this.internalSpoiled = true;
|
||||
this.internalAnswerIds = [];
|
||||
return;
|
||||
}
|
||||
|
||||
answers = answers.slice(0, poll.maxSelections);
|
||||
}
|
||||
|
||||
this.internalAnswerIds = answers;
|
||||
this.internalSpoiled = false;
|
||||
}
|
||||
|
||||
public isEquivalentTo(primaryEventType: ExtensibleEventType): boolean {
|
||||
return isEventTypeSame(primaryEventType, M_POLL_RESPONSE);
|
||||
}
|
||||
|
||||
public serialize(): IPartialEvent<object> {
|
||||
return {
|
||||
type: M_POLL_RESPONSE.name,
|
||||
content: {
|
||||
"m.relates_to": {
|
||||
rel_type: REFERENCE_RELATION.name,
|
||||
event_id: this.pollEventId,
|
||||
},
|
||||
[M_POLL_RESPONSE.name]: {
|
||||
answers: this.spoiled ? undefined : this.answerIds,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PollResponseEvent from a set of answers. To spoil the vote, pass an empty
|
||||
* answers array.
|
||||
* @param answers - The user's answers. Should be valid from a poll's answer IDs.
|
||||
* @param pollEventId - The poll start event ID.
|
||||
* @returns The representative poll response event.
|
||||
*/
|
||||
public static from(answers: string[], pollEventId: string): PollResponseEvent {
|
||||
return new PollResponseEvent({
|
||||
type: M_POLL_RESPONSE.name,
|
||||
content: {
|
||||
"m.relates_to": {
|
||||
rel_type: REFERENCE_RELATION.name,
|
||||
event_id: pollEventId,
|
||||
},
|
||||
[M_POLL_RESPONSE.name]: {
|
||||
answers: answers,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
207
node_modules/matrix-js-sdk/src/extensible_events_v1/PollStartEvent.ts
generated
vendored
Normal file
207
node_modules/matrix-js-sdk/src/extensible_events_v1/PollStartEvent.ts
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Copyright 2022 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { NamespacedValue } from "matrix-events-sdk";
|
||||
|
||||
import { MessageEvent } from "./MessageEvent.ts";
|
||||
import { type ExtensibleEventType, type IPartialEvent, isEventTypeSame, M_TEXT } from "../@types/extensible_events.ts";
|
||||
import {
|
||||
type KnownPollKind,
|
||||
M_POLL_KIND_DISCLOSED,
|
||||
M_POLL_KIND_UNDISCLOSED,
|
||||
M_POLL_START,
|
||||
type PollStartEventContent,
|
||||
type PollStartSubtype,
|
||||
type PollAnswer,
|
||||
} from "../@types/polls.ts";
|
||||
import { InvalidEventError } from "./InvalidEventError.ts";
|
||||
import { ExtensibleEvent } from "./ExtensibleEvent.ts";
|
||||
|
||||
/**
|
||||
* Represents a poll answer. Note that this is represented as a subtype and is
|
||||
* not registered as a parsable event - it is implied for usage exclusively
|
||||
* within the PollStartEvent parsing.
|
||||
*/
|
||||
export class PollAnswerSubevent extends MessageEvent {
|
||||
/**
|
||||
* The answer ID.
|
||||
*/
|
||||
public readonly id: string;
|
||||
|
||||
public constructor(wireFormat: IPartialEvent<PollAnswer>) {
|
||||
super(wireFormat);
|
||||
|
||||
const id = wireFormat.content.id;
|
||||
if (!id || typeof id !== "string") {
|
||||
throw new InvalidEventError("Answer ID must be a non-empty string");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public serialize(): IPartialEvent<object> {
|
||||
return {
|
||||
type: "org.matrix.sdk.poll.answer",
|
||||
content: {
|
||||
id: this.id,
|
||||
...this.serializeMMessageOnly(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PollAnswerSubevent from ID and text.
|
||||
* @param id - The answer ID (unique within the poll).
|
||||
* @param text - The text.
|
||||
* @returns The representative answer.
|
||||
*/
|
||||
public static from(id: string, text: string): PollAnswerSubevent {
|
||||
return new PollAnswerSubevent({
|
||||
type: "org.matrix.sdk.poll.answer",
|
||||
content: {
|
||||
id: id,
|
||||
[M_TEXT.name]: text,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a poll start event.
|
||||
*/
|
||||
export class PollStartEvent extends ExtensibleEvent<PollStartEventContent> {
|
||||
/**
|
||||
* The question being asked, as a MessageEvent node.
|
||||
*/
|
||||
public readonly question: MessageEvent;
|
||||
|
||||
/**
|
||||
* The interpreted kind of poll. Note that this will infer a value that is known to the
|
||||
* SDK rather than verbatim - this means unknown types will be represented as undisclosed
|
||||
* polls.
|
||||
*
|
||||
* To get the raw kind, use rawKind.
|
||||
*/
|
||||
public readonly kind: KnownPollKind;
|
||||
|
||||
/**
|
||||
* The true kind as provided by the event sender. Might not be valid.
|
||||
*/
|
||||
public readonly rawKind: string;
|
||||
|
||||
/**
|
||||
* The maximum number of selections a user is allowed to make.
|
||||
*/
|
||||
public readonly maxSelections: number;
|
||||
|
||||
/**
|
||||
* The possible answers for the poll.
|
||||
*/
|
||||
public readonly answers: PollAnswerSubevent[];
|
||||
|
||||
/**
|
||||
* Creates a new PollStartEvent from a pure format. Note that the event is *not*
|
||||
* parsed here: it will be treated as a literal m.poll.start primary typed event.
|
||||
* @param wireFormat - The event.
|
||||
*/
|
||||
public constructor(wireFormat: IPartialEvent<PollStartEventContent>) {
|
||||
super(wireFormat);
|
||||
|
||||
const poll = M_POLL_START.findIn<PollStartSubtype>(this.wireContent);
|
||||
|
||||
if (!poll?.question) {
|
||||
throw new InvalidEventError("A question is required");
|
||||
}
|
||||
|
||||
this.question = new MessageEvent({ type: "org.matrix.sdk.poll.question", content: poll.question });
|
||||
|
||||
this.rawKind = poll.kind;
|
||||
if (M_POLL_KIND_DISCLOSED.matches(this.rawKind)) {
|
||||
this.kind = M_POLL_KIND_DISCLOSED;
|
||||
} else {
|
||||
this.kind = M_POLL_KIND_UNDISCLOSED; // default & assumed value
|
||||
}
|
||||
|
||||
this.maxSelections =
|
||||
Number.isFinite(poll.max_selections) && poll.max_selections! > 0 ? poll.max_selections! : 1;
|
||||
|
||||
if (!Array.isArray(poll.answers)) {
|
||||
throw new InvalidEventError("Poll answers must be an array");
|
||||
}
|
||||
const answers = poll.answers.slice(0, 20).map(
|
||||
(a) =>
|
||||
new PollAnswerSubevent({
|
||||
type: "org.matrix.sdk.poll.answer",
|
||||
content: a,
|
||||
}),
|
||||
);
|
||||
if (answers.length <= 0) {
|
||||
throw new InvalidEventError("No answers available");
|
||||
}
|
||||
this.answers = answers;
|
||||
}
|
||||
|
||||
public isEquivalentTo(primaryEventType: ExtensibleEventType): boolean {
|
||||
return isEventTypeSame(primaryEventType, M_POLL_START);
|
||||
}
|
||||
|
||||
public serialize(): IPartialEvent<object> {
|
||||
return {
|
||||
type: M_POLL_START.name,
|
||||
content: {
|
||||
[M_POLL_START.name]: {
|
||||
question: this.question.serialize().content,
|
||||
kind: this.rawKind,
|
||||
max_selections: this.maxSelections,
|
||||
answers: this.answers.map((a) => a.serialize().content),
|
||||
},
|
||||
[M_TEXT.name]: `${this.question.text}\n${this.answers.map((a, i) => `${i + 1}. ${a.text}`).join("\n")}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PollStartEvent from question, answers, and metadata.
|
||||
* @param question - The question to ask.
|
||||
* @param answers - The answers. Should be unique within each other.
|
||||
* @param kind - The kind of poll.
|
||||
* @param maxSelections - The maximum number of selections. Must be 1 or higher.
|
||||
* @returns The representative poll start event.
|
||||
*/
|
||||
public static from(
|
||||
question: string,
|
||||
answers: string[],
|
||||
kind: KnownPollKind | string,
|
||||
maxSelections = 1,
|
||||
): PollStartEvent {
|
||||
return new PollStartEvent({
|
||||
type: M_POLL_START.name,
|
||||
content: {
|
||||
[M_TEXT.name]: question, // unused by parsing
|
||||
[M_POLL_START.name]: {
|
||||
question: { [M_TEXT.name]: question },
|
||||
kind: kind instanceof NamespacedValue ? kind.name : kind,
|
||||
max_selections: maxSelections,
|
||||
answers: answers.map((a) => ({ id: makeId(), [M_TEXT.name]: a })),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
function makeId(): string {
|
||||
return [...Array(16)].map(() => LETTERS.charAt(Math.floor(Math.random() * LETTERS.length))).join("");
|
||||
}
|
||||
35
node_modules/matrix-js-sdk/src/extensible_events_v1/utilities.ts
generated
vendored
Normal file
35
node_modules/matrix-js-sdk/src/extensible_events_v1/utilities.ts
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2021 - 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { type Optional } from "matrix-events-sdk";
|
||||
|
||||
/**
|
||||
* Determines if the given optional was provided a value.
|
||||
* @param s - The optional to test.
|
||||
* @returns True if the value is defined.
|
||||
*/
|
||||
export function isProvided<T>(s: Optional<T>): s is T {
|
||||
return s !== null && s !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given optional string is a defined string.
|
||||
* @param s - The input string.
|
||||
* @returns True if the input is a defined string.
|
||||
*/
|
||||
export function isOptionalAString(s: Optional<string>): s is string {
|
||||
return isProvided(s) && typeof s === "string";
|
||||
}
|
||||
Reference in New Issue
Block a user