Simple plugin proof of concept.

This commit is contained in:
Paul 2021-07-11 09:51:34 +01:00
parent 6f6020c474
commit 745ae35c6b
3 changed files with 83 additions and 4 deletions

View file

@ -36,6 +36,7 @@ import { takeError } from "../../../context/revoltjs/util";
import IconButton from "../../ui/IconButton";
import { PluginSingleton } from "../../../plugins";
import AutoComplete, { useAutoComplete } from "../AutoComplete";
import { PermissionTooltip } from "../Tooltip";
import FilePreview from "./bars/FilePreview";
@ -185,8 +186,11 @@ export default function MessageBox({ channel }: Props) {
return;
const content = draft?.trim() ?? "";
if (uploadState.type === "attached") return sendFile(content);
if (content.length === 0) return;
const target = { content };
if (PluginSingleton.emit("Message:Send", target)) return;
if (uploadState.type === "attached") return sendFile(target.content);
if (target.content.length === 0) return;
stopTyping();
setMessage();
@ -203,7 +207,7 @@ export default function MessageBox({ channel }: Props) {
channel: channel._id,
author: client.user!._id,
content,
content: target.content,
replies,
},
});
@ -217,7 +221,7 @@ export default function MessageBox({ channel }: Props) {
try {
await client.channels.sendMessage(channel._id, {
content,
content: target.content,
nonce,
replies,
});

View file

@ -6,6 +6,7 @@ import { render } from "preact";
import { internalEmit } from "./lib/eventEmitter";
import { App } from "./pages/app";
import "./plugins";
export const updateSW = registerSW({
onNeedRefresh() {

74
src/plugins/index.ts Normal file
View file

@ -0,0 +1,74 @@
import { Children } from "../types/Preact";
export interface PluginEvent<T> {
cancel: () => void;
target: T;
}
export interface PluginEvents {
"Message:Send": (
event: PluginEvent<{ content?: string; files?: File[] }>,
) => void;
"Misc:Test": (event: PluginEvent<string>) => void;
}
export interface Plugin {
render?: () => Children;
events?: Partial<PluginEvents>;
}
class Singleton {
listeners: {
[key in keyof PluginEvents]?: PluginEvents[key][];
};
constructor() {
this.listeners = {};
}
private getListenerArray<K extends keyof PluginEvents>(
key: K,
): PluginEvents[K][] {
const arr = this.listeners[key];
if (arr) return arr as PluginEvents[K][];
this.listeners[key] = [];
return this.listeners[key]! as PluginEvents[K][];
}
addListener<K extends keyof PluginEvents>(key: K, fn: PluginEvents[K]) {
this.getListenerArray(key).push(fn);
}
emit<K extends keyof PluginEvents>(
key: K,
target: Parameters<PluginEvents[K]>[0]["target"],
): boolean {
let canceled = false;
const ev: PluginEvent<any> = {
cancel: () => (canceled = true),
target,
};
const arr = this.getListenerArray(key);
for (const listener of arr) {
listener(ev);
if (canceled) break;
}
return canceled;
}
}
export const PluginSingleton = new Singleton();
PluginSingleton.addListener("Message:Send", (event) => {
const { content } = event.target;
if (content?.startsWith(";sus")) {
event.target.content = "baka!";
} else if (content?.startsWith(";amogus")) {
alert("fat");
event.cancel();
}
});