diff --git a/server/client.ts b/server/client.ts index d5ffe84e..35483513 100644 --- a/server/client.ts +++ b/server/client.ts @@ -479,38 +479,9 @@ class Client { const cmd = args?.shift()?.toLowerCase() || ""; const irc = target.network.irc; - let connected = irc && irc.connection && irc.connection.connected; + const connected = irc?.connected; - if (inputs.userInputs.has(cmd)) { - const plugin = inputs.userInputs.get(cmd); - - if (!plugin) { - // should be a no-op - throw new Error(`Plugin ${cmd} not found`); - } - - if (typeof plugin.input === "function" && (connected || plugin.allowDisconnected)) { - connected = true; - plugin.input.apply(client, [target.network, target.chan, cmd, args]); - } - } else if (inputs.pluginCommands.has(cmd)) { - const plugin = inputs.pluginCommands.get(cmd); - - if (typeof plugin.input === "function" && (connected || plugin.allowDisconnected)) { - connected = true; - plugin.input( - new PublicClient(client, plugin.packageInfo), - {network: target.network, chan: target.chan}, - cmd, - args - ); - } - } else if (connected) { - // TODO: fix - irc!.raw(text); - } - - if (!connected) { + const emitFailureDisconnected = () => { target.chan.pushMessage( this, new Msg({ @@ -518,7 +489,44 @@ class Client { text: "You are not connected to the IRC network, unable to send your command.", }) ); + }; + + const plugin = inputs.userInputs.get(cmd); + + if (plugin) { + if (!connected && !plugin.allowDisconnected) { + emitFailureDisconnected(); + return; + } + + plugin.input.apply(client, [target.network, target.chan, cmd, args]); + return; } + + const extPlugin = inputs.pluginCommands.get(cmd); + + if (extPlugin) { + if (!connected && !extPlugin.allowDisconnected) { + emitFailureDisconnected(); + return; + } + + extPlugin.input( + new PublicClient(client, extPlugin.packageInfo), + {network: target.network, chan: target.chan}, + cmd, + args + ); + return; + } + + if (!connected) { + emitFailureDisconnected(); + return; + } + + // TODO: fix + irc!.raw(text); } compileCustomHighlights() { diff --git a/server/plugins/inputs/index.ts b/server/plugins/inputs/index.ts index e3390361..95141b5f 100644 --- a/server/plugins/inputs/index.ts +++ b/server/plugins/inputs/index.ts @@ -3,6 +3,7 @@ import log from "../../log"; import Chan, {Channel} from "../../models/chan"; import Network, {NetworkWithIrcFramework} from "../../models/network"; import {PackageInfo} from "../packages"; +import PublicClient from "../packages/publicClient"; export type PluginInputHandler = ( this: Client, @@ -15,7 +16,18 @@ export type PluginInputHandler = ( type Plugin = { commands: string[]; input: (network: Network, chan: Chan, cmd: string, args: string[]) => void; - allowDisconnected?: boolean | undefined; + allowDisconnected?: boolean; +}; + +type ExternalPluginCommand = { + packageInfo: PackageInfo; + input: ( + pub: PublicClient, + netChan: {network: Network; chan: Chan}, + cmd: string, + args: string[] + ) => void; + allowDisconnected?: boolean; }; const clientSideCommands = ["/collapse", "/expand", "/search"]; @@ -79,7 +91,7 @@ for (const input of builtInInputs) { }); } -const pluginCommands = new Map(); +const pluginCommands = new Map(); const getCommands = () => Array.from(userInputs.keys()) @@ -89,9 +101,22 @@ const getCommands = () => .concat(passThroughCommands) .sort(); -const addPluginCommand = (packageInfo: PackageInfo, command, func) => { - func.packageInfo = packageInfo; - pluginCommands.set(command, func); +const addPluginCommand = (packageInfo: PackageInfo, command: any, obj: any) => { + if (typeof command !== "string") { + log.error(`plugin {packageInfo.packageName} tried to register a bad command`); + return; + } else if (!obj || typeof obj.input !== "function") { + log.error( + `plugin ${packageInfo.packageName} tried to register command "${command} without a callback"` + ); + return; + } + + pluginCommands.set(command, { + packageInfo: packageInfo, + input: obj.input, + allowDisconnected: obj.allowDisconnected, + }); }; export default {