UNPKG

@lilybird/handlers

Version:
135 lines (132 loc) 5.46 kB
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; } }