@lilybird/handlers
Version:
Command handlers and more for lilybird
135 lines (132 loc) • 5.46 kB
JavaScript
import { makeTransformersObject } from "@lilybird/transformers";
const defaultTransformers = makeTransformersObject();
export class MessageComponentStore {
#stacks = new Map();
#store = new Map();
#emit;
#attachDynamicComponentListener = false;
constructor(handlerListener, attachDynamicComponentListener) {
this.#emit = handlerListener;
if (attachDynamicComponentListener)
this.#attachDynamicComponentListener = attachDynamicComponentListener;
}
addDynamicComponent(component) {
if (!this.#attachDynamicComponentListener)
throw new Error("Dynamic Components are disabled, please enable them before using this feature.");
this.#store.set(Date.now(), component);
}
storeComponent(component) {
const { type, id, customMatcher, handle } = component;
const fnName = `component_${id.replace("-", "_")}`;
const componentStack = this.#stacks.get(type);
const obj = {
body: `if (custom_id === "${id}") { return ${fnName}(t_int) }`,
handler: [fnName, handle],
matcher: undefined
};
if (typeof customMatcher === "function") {
const matchFnName = `match_id_${id}`;
obj.body = `if (${matchFnName}(t_int)) { return ${fnName}(t_int) }`;
obj.matcher = [matchFnName, customMatcher];
}
else if (typeof customMatcher === "string")
obj.body = `if (${customMatcher}) { return ${fnName}(t_int) }`;
if (typeof componentStack === "undefined") {
this.#stacks.set(type, new Map([[id, obj]]));
return;
}
obj.body = `else ${obj.body}`;
componentStack.set(id, obj);
}
getCompilationStack() {
if (this.#stacks.size === 0)
return null;
const functions = new Map();
const stackEntries = [...this.#stacks.entries()];
const componentStack = [
"const custom_id = interaction.data.custom_id;",
`if (interaction.type === ${3}) {`,
"const t_int = transformer(client, interaction);"
];
const modalStack = [`else if (interaction.type === "${5}") {`];
for (let i = 0, { length } = stackEntries; i < length; i++) {
const [stringType, stack] = stackEntries[i];
const stackValues = [...stack.values()];
const stackBody = [];
for (let j = 0, len = stackValues.length; j < len; j++) {
const component = stackValues[j];
const [n, h] = component.handler;
functions.set(n, h);
if (typeof component.matcher !== "undefined") {
const [nn, hh] = component.matcher;
functions.set(nn, hh);
}
stackBody.push(component.body);
}
if (+stringType === 4)
modalStack.push(stackBody.join(""));
else
componentStack.push(stackBody.join(""));
}
const arr = [];
if (componentStack.length > 1)
arr.push(componentStack.join(""), "}");
if (modalStack.length > 1) {
if (arr.length === 0)
modalStack[0] = modalStack[0].slice(5);
arr.push(modalStack.join(""), "}");
}
if (arr.length === 0)
return null;
const fNames = functions.keys();
const fHandlers = functions.values();
const compiledListener = arr.join("");
return {
functionNames: fNames,
handlers: fHandlers,
stack: compiledListener
};
}
compile() {
const compiledResult = this.getCompilationStack();
if (compiledResult === null)
return null;
const { stack, functionNames, handlers } = compiledResult;
let extendedStack = stack;
if (this.#attachDynamicComponentListener) {
extendedStack += `\nfor (let i = 0, entries = [..._store.entries()], { length } = entries; i < length; i++) {
const [date, data] = entries[i];
const { timeout, filter, handle } = data;
if (typeof timeout === "number" && Date.now() - date <= timeout) {
this.#store.delete(date);
continue;
}
const _int = transformer(client, interaction);
if (!filter(_int)) continue;
await handle(int);
}`;
}
this.#emit?.(7, extendedStack);
const init = this.#attachDynamicComponentListener ? ["_store", "transformers"] : ["transformers"];
const initArgs = this.#attachDynamicComponentListener ? [this.#store, defaultTransformers.interactionCreate.handler] : [defaultTransformers.interactionCreate.handler];
return new Function(...init, ...functionNames, `return async (client, interaction) => { ${extendedStack} }`)(...initArgs, ...handlers);
}
getStoredComponents() {
const mainEntries = [...this.#stacks.entries()];
const obj = {};
for (let i = 0, { length } = mainEntries; i < length; i++) {
const [key, value] = mainEntries[i];
obj[key] = [...value.values()];
}
return obj;
}
clear() {
this.#stacks.clear();
}
set attachDynamicComponentListener(bool) {
this.#attachDynamicComponentListener = bool;
}
get attachDynamicComponentListener() {
return this.#attachDynamicComponentListener;
}
}