diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 76f6a0dc..ab8bd1ba 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -289,7 +289,7 @@ router.post(
edited_timestamp: undefined,
timestamp: new Date(),
});
-
+ if (message.id == "0") return res.json(message); // Don't handle cancelled messages.
channel.last_message_id = message.id;
if (channel.isDm()) {
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 42325681..24e67fcc 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -40,12 +40,14 @@ import {
Config,
Sticker,
MessageCreateSchema,
- EmbedCache,
+ EmbedCache, MessageOptions,
} from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { In } from "typeorm";
import { EmbedHandlers } from "@fosscord/api";
import * as Sentry from "@sentry/node";
+import { MessageInterceptResult } from "@fosscord/util/message_interceptors/IMessageInterceptor";
+import { PluralCommandInterceptor } from "../../../util/message_interceptors/plural_tooling/PluralCommandInterceptor";
const allow_empty = false;
// TODO: check webhook, application, system author, stickers
// TODO: embed gifs/videos/images
@@ -53,6 +55,26 @@ const allow_empty = false;
const LINK_REGEX =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g;
+const interceptors = [new PluralCommandInterceptor()];
+
+async function runMessageInterceptors(ctx: { message: Message, opts: MessageOptions }): Promise<MessageInterceptResult> {
+ const result = new MessageInterceptResult();
+ result.cancel = false;
+ result.message = ctx.message;
+ for (const interceptorsKey in interceptors) {
+ const interceptor = interceptors[interceptorsKey];
+ const interceptorResult = await interceptor.execute(ctx);
+
+ result.message = interceptorResult.message;
+ if (interceptorResult.cancel) {
+ result.cancel = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
export async function handleMessage(opts: MessageOptions): Promise<Message> {
const channel = await Channel.findOneOrFail({
where: { id: opts.channel_id },
@@ -192,11 +214,22 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
// TODO: check and put it all in the body
+ // root@Rory - 2023-02-18 - Add message interceptors, for use in dev/plurality, might be useful for plugins too.
+ let interceptMessageResult: MessageInterceptResult = await runMessageInterceptors({
+ opts,
+ message,
+ });
+ if(interceptMessageResult.cancel) {
+ message.id = "0"; //identify as cancelled message, as to prevent it from being distributed
+ return message;
+ }
+
return message;
}
// TODO: cache link result in db
export async function postHandleMessage(message: Message) {
+ if (message.id == "0") return; // don't handle cancelled messages
const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
let links = content?.match(LINK_REGEX);
if (!links) return;
@@ -268,7 +301,7 @@ export async function postHandleMessage(message: Message) {
export async function sendMessage(opts: MessageOptions) {
const message = await handleMessage({ ...opts, timestamp: new Date() });
-
+ if (message.id == "0") return; // don't handle cancelled messages
await Promise.all([
Message.insert(message),
emitEvent({
@@ -285,17 +318,3 @@ export async function sendMessage(opts: MessageOptions) {
return message;
}
-
-interface MessageOptions extends MessageCreateSchema {
- id?: string;
- type?: MessageType;
- pinned?: boolean;
- author_id?: string;
- webhook_id?: string;
- application_id?: string;
- embeds?: Embed[];
- channel_id?: string;
- attachments?: Attachment[];
- edited_timestamp?: Date;
- timestamp?: Date;
-}
diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index fc8c011c..998513f8 100644
--- a/src/util/entities/Message.ts
+++ b/src/util/entities/Message.ts
@@ -217,6 +217,8 @@ export class Message extends BaseClass {
@Column({ type: "simple-json", nullable: true })
components?: MessageComponent[];
+
+ ephemeral?: boolean;
}
export interface MessageComponent {
diff --git a/src/util/index.ts b/src/util/index.ts
index a3495a0c..08abacaa 100644
--- a/src/util/index.ts
+++ b/src/util/index.ts
@@ -25,3 +25,4 @@ export * from "./dtos/index";
export * from "./schemas";
export * from "./imports";
export * from "./config";
+export * from "./message_interceptors";
diff --git a/src/util/interfaces/MessageOptions.ts b/src/util/interfaces/MessageOptions.ts
new file mode 100644
index 00000000..3705e668
--- /dev/null
+++ b/src/util/interfaces/MessageOptions.ts
@@ -0,0 +1,15 @@
+import { Attachment, Embed, MessageCreateSchema, MessageType } from "@fosscord/util*";
+
+export interface MessageOptions extends MessageCreateSchema {
+ id?: string;
+ type?: MessageType;
+ pinned?: boolean;
+ author_id?: string;
+ webhook_id?: string;
+ application_id?: string;
+ embeds?: Embed[];
+ channel_id?: string;
+ attachments?: Attachment[];
+ edited_timestamp?: Date;
+ timestamp?: Date;
+}
\ No newline at end of file
diff --git a/src/util/interfaces/index.ts b/src/util/interfaces/index.ts
index fa259ce1..96a0e9c2 100644
--- a/src/util/interfaces/index.ts
+++ b/src/util/interfaces/index.ts
@@ -21,3 +21,4 @@ export * from "./Presence";
export * from "./Interaction";
export * from "./Event";
export * from "./Status";
+export * from "./MessageOptions";
\ No newline at end of file
diff --git a/src/util/message_interceptors/IMessageInterceptor.ts b/src/util/message_interceptors/IMessageInterceptor.ts
new file mode 100644
index 00000000..35b9dd12
--- /dev/null
+++ b/src/util/message_interceptors/IMessageInterceptor.ts
@@ -0,0 +1,15 @@
+import { Message, MessageOptions } from "@fosscord/util";
+
+export interface IMessageInterceptor {
+ execute(ctx: MessageInterceptorContext): Promise<MessageInterceptResult>;
+}
+
+export class MessageInterceptResult {
+ cancel: boolean;
+ message: Message;
+}
+
+export class MessageInterceptorContext {
+ message: Message;
+ opts: MessageOptions;
+}
\ No newline at end of file
diff --git a/src/util/message_interceptors/index.ts b/src/util/message_interceptors/index.ts
new file mode 100644
index 00000000..db64e5b3
--- /dev/null
+++ b/src/util/message_interceptors/index.ts
@@ -0,0 +1 @@
+export * from "./IMessageInterceptor";
\ No newline at end of file
diff --git a/src/util/message_interceptors/plural_tooling/PluralCommandInterceptor.ts b/src/util/message_interceptors/plural_tooling/PluralCommandInterceptor.ts
new file mode 100644
index 00000000..ac6bb153
--- /dev/null
+++ b/src/util/message_interceptors/plural_tooling/PluralCommandInterceptor.ts
@@ -0,0 +1,46 @@
+import {
+ emitEvent,
+ IMessageInterceptor, Message,
+ MessageCreateEvent, MessageDeleteEvent, MessageFlags,
+ MessageInterceptorContext,
+ MessageInterceptResult, MessageTypes
+} from "@fosscord/util";
+
+export class PluralCommandInterceptor implements IMessageInterceptor {
+ async execute(ctx: MessageInterceptorContext): Promise<MessageInterceptResult> {
+ let result = new MessageInterceptResult();
+ result.cancel = false;
+ result.message = ctx.message;
+
+ if(ctx.message.content?.toLowerCase().startsWith("p;")) {
+ console.log("[PluralCommandInterceptor] Plural command prefix detected, cancelling message send. Content: ", ctx.message.content)
+ result.cancel = true;
+ }
+
+
+ if(result.cancel) {
+ /*await emitEvent({
+ event: "MESSAGE_DELETE",
+ channel_id: ctx.message.channel_id,
+ data: {
+ id: ctx.message.id,
+ channel_id: ctx.message.channel_id,
+ guild_id: ctx.message.guild_id
+ },
+ } as MessageDeleteEvent);*/
+ //result.message.flags = String((BigInt(ctx.message.flags ?? "0")) | MessageTypes.);
+ // @ts-ignore
+ result.message.ephemeral = true;
+ result.message.content += ' (ephemeral?)';
+ /*await emitEvent({
+ event: "MESSAGE_CREATE",
+ //channel_id: ctx.opts.channel_id,
+ user_id: ctx.opts.author_id,
+ data: ctx.message.toJSON(),
+ } as MessageCreateEvent);*/
+ }
+
+ return result;
+ }
+
+}
\ No newline at end of file
|