1
0
mirror of https://github.com/spacebarchat/server.git synced 2024-11-22 02:12:40 +01:00

Add basic message interceptor framework

Signed-off-by: TheArcaneBrony <myrainbowdash949@gmail.com>
This commit is contained in:
TheArcaneBrony 2023-02-19 19:55:28 +01:00
parent 01a05a1787
commit 506954f3df
No known key found for this signature in database
GPG Key ID: 32FC5AAADAD75A22
10 changed files with 5112 additions and 17 deletions

4995
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -289,7 +289,7 @@ router.post(
edited_timestamp: undefined, edited_timestamp: undefined,
timestamp: new Date(), timestamp: new Date(),
}); });
if (message.id == "0") return res.json(message); // Don't handle cancelled messages.
channel.last_message_id = message.id; channel.last_message_id = message.id;
if (channel.isDm()) { if (channel.isDm()) {

View File

@ -40,12 +40,14 @@ import {
Config, Config,
Sticker, Sticker,
MessageCreateSchema, MessageCreateSchema,
EmbedCache, EmbedCache, MessageOptions,
} from "@fosscord/util"; } from "@fosscord/util";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { In } from "typeorm"; import { In } from "typeorm";
import { EmbedHandlers } from "@fosscord/api"; import { EmbedHandlers } from "@fosscord/api";
import * as Sentry from "@sentry/node"; 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; const allow_empty = false;
// TODO: check webhook, application, system author, stickers // TODO: check webhook, application, system author, stickers
// TODO: embed gifs/videos/images // TODO: embed gifs/videos/images
@ -53,6 +55,26 @@ const allow_empty = false;
const LINK_REGEX = const LINK_REGEX =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g; /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> { export async function handleMessage(opts: MessageOptions): Promise<Message> {
const channel = await Channel.findOneOrFail({ const channel = await Channel.findOneOrFail({
where: { id: opts.channel_id }, 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 // 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; return message;
} }
// TODO: cache link result in db // TODO: cache link result in db
export async function postHandleMessage(message: Message) { export async function postHandleMessage(message: Message) {
if (message.id == "0") return; // don't handle cancelled messages
const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
let links = content?.match(LINK_REGEX); let links = content?.match(LINK_REGEX);
if (!links) return; if (!links) return;
@ -268,7 +301,7 @@ export async function postHandleMessage(message: Message) {
export async function sendMessage(opts: MessageOptions) { export async function sendMessage(opts: MessageOptions) {
const message = await handleMessage({ ...opts, timestamp: new Date() }); const message = await handleMessage({ ...opts, timestamp: new Date() });
if (message.id == "0") return; // don't handle cancelled messages
await Promise.all([ await Promise.all([
Message.insert(message), Message.insert(message),
emitEvent({ emitEvent({
@ -285,17 +318,3 @@ export async function sendMessage(opts: MessageOptions) {
return message; 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;
}

View File

@ -217,6 +217,8 @@ export class Message extends BaseClass {
@Column({ type: "simple-json", nullable: true }) @Column({ type: "simple-json", nullable: true })
components?: MessageComponent[]; components?: MessageComponent[];
ephemeral?: boolean;
} }
export interface MessageComponent { export interface MessageComponent {

View File

@ -25,3 +25,4 @@ export * from "./dtos/index";
export * from "./schemas"; export * from "./schemas";
export * from "./imports"; export * from "./imports";
export * from "./config"; export * from "./config";
export * from "./message_interceptors";

View File

@ -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;
}

View File

@ -21,3 +21,4 @@ export * from "./Presence";
export * from "./Interaction"; export * from "./Interaction";
export * from "./Event"; export * from "./Event";
export * from "./Status"; export * from "./Status";
export * from "./MessageOptions";

View File

@ -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;
}

View File

@ -0,0 +1 @@
export * from "./IMessageInterceptor";

View File

@ -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;
}
}