import { logger } from '@squeebot/core/lib/core'; import { IRepository } from '@squeebot/core/lib/plugin/repository'; import { ReadLine } from 'readline'; import { Squeebot } from './core'; export class SqueebotCLI { constructor(private bot: Squeebot) {} private async checkUpdate(repo: IRepository): Promise { const updatable = await this.bot.repositoryManager.checkForUpdates(repo); if (updatable.length) { logger.log('[%s] The following plugins can be updated:', repo.name, updatable.map((u) => u.name).join(', ')); } else { logger.log('[%s] All plugins are up-to-date!', repo.name); } } private async repositoryCommand(...args: any[]): Promise { const help = 'repository add | update | remove '; if (!args[0] || args[0] === 'help') { logger.log(help); return; } switch (args[0]) { case 'a': case 'i': case 'add': case 'install': if (!args[1]) { logger.error('URL is required'); return; } for (const urlp of args.slice(1)) { const repo = await this.bot.repositoryManager.installRepository(urlp); logger.log('Installed repository %s!', repo.name); } break; case 'r': case 'rem': case 'remove': case 'uninstall': if (!args[1]) { logger.error('Name is required'); return; } for (const namep of args.slice(1)) { await this.bot.repositoryManager.uninstallRepository(namep); logger.log('Installed repository %s.', namep); } break; case 'u': case 'upd': case 'update': if (!args[1]) { const repos = this.bot.repositoryManager.getAll(); for (const repo of repos) { await this.checkUpdate(repo); } return; } for (const namep of args.slice(1)) { const repo = this.bot.repositoryManager.getRepoByName(namep); if (!repo) { logger.error('No such repository "%s" found.', namep); return; } await this.checkUpdate(repo); } break; default: logger.log(help); } } private async pluginCommand(...args: any[]): Promise { const help = 'plugin install | update | uninstall | enable | disable | start | stop | list | running []'; if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list' && args[0] !== 'running')) { logger.log(help); return; } switch (args[0]) { case 'i': case 'u': case 'install': case 'update': for (const name of args.slice(1)) { const mf = await this.bot.repositoryManager.installPlugin(name); logger.log('Installed plugin %s version %s!', mf.name, mf.version); } break; case 'uninst': case 'remove': case 'uninstall': for (const name of args.slice(1)) { await this.bot.repositoryManager.uninstallPlugin(name); logger.log('Uninstalled plugin %s.', name); } break; case 'list': logger.log('Installed plugins:', this.bot.pluginManager.availablePlugins.map((mf) => mf.name).join(', ')); break; case 'running': logger.log('Currently running plugins:', this.bot.pluginManager.getLoaded().map((p) => p.manifest.name).join(', ')); break; case 's': case 'run': case 'load': case 'start': for (const name of args.slice(1)) { const plugin = this.bot.pluginManager.getAvailableByName(name); if (!plugin) { logger.error('"%s" is not available. Maybe try installing it? plugin install', name, name); return; } await this.bot.pluginManager.load(plugin); logger.log('Started plugin "%s" successfully.', name); } break; case 'stop': case 'kill': for (const name of args.slice(1)) { if (!this.bot.pluginManager.getAvailableByName(name)) { logger.error('No such plugin is available.'); return; } logger.log('Stopping plugin', name); this.bot.stream.emitTo(name, 'pluginUnload', name); } break; case 'enable': for (const name of args.slice(1)) { if (!this.bot.pluginManager.getAvailableByName(name)) { logger.error('No such plugin "%s" is available.', name); return; } logger.log('Enabling plugin', name); if (!this.bot.config.config.enabled) { this.bot.config.config.enabled = [name]; return; } if (this.bot.config.config.enabled.indexOf(name) === -1) { this.bot.config.config.enabled.push(name); } } await this.bot.config.save(); break; case 'disable': for (const name of args.slice(1)) { if (!this.bot.pluginManager.getAvailableByName(name)) { logger.error('No such plugin "%s" is available.', name); return; } logger.log('Disabling plugin', name); if (!this.bot.config.config.enabled) { return; } const indx = this.bot.config.config.enabled.indexOf(name); if (indx > -1) { this.bot.config.config.enabled.splice(indx, 1); } } await this.bot.config.save(); break; default: logger.log(help); } } private async channelCommand(...args: any[]): Promise { const help = 'channel new | del | list | addplugin | delplugin [] []'; if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list')) { logger.log(help); return; } switch (args[0]) { case 'new': if (this.bot.channelManager.getChannelByName(args[1])) { logger.error('A channel by that name already exists!'); break; } this.bot.channelManager.addChannel({ name: args[1], plugins: [], enabled: true, }); logger.log('Channel added!'); break; case 'del': case 'delete': case 'remove': for (const name of args.slice(1)) { const chan = this.bot.channelManager.getChannelByName(name); if (!chan) { logger.error('No such channel "%s" exists!', name); return; } this.bot.channelManager.removeChannel(chan); logger.log('Channel "%s" removed!', name); } break; case 'addp': case 'addplugin': const chan1 = this.bot.channelManager.getChannelByName(args[1]); if (!chan1) { logger.error('No such channel exists!'); return; } if (!args[2]) { logger.error('A plugin name is required.'); return; } for (const name of args.slice(2)) { if (chan1.plugins.indexOf(name) === -1) { chan1.plugins.push(name); } logger.log('Plugin "%s" added to channel!', name); } break; case 'list': logger.log('Channels:\n', this.bot.channelManager.getAll().map((chan) => { return ` => ${chan.name}: ${chan.plugins.join(', ')} (${chan.enabled ? 'enabled' : 'disabled'})`; }).join('\n')); break; case 'remp': case 'delp': case 'remplugin': case 'delplugin': const chan2 = this.bot.channelManager.getChannelByName(args[1]); if (!chan2) { logger.error('No such channel exists!'); return; } if (!args[2]) { logger.error('A plugin name is required.'); return; } for (const name of args.slice(2)) { const idx = chan2.plugins.indexOf(args[2]); if (idx !== -1) { chan2.plugins.splice(idx, 1); } logger.log('Plugin "%s" added to channel!', name); } break; case 'enable': for (const name of args.slice(1)) { const chan = this.bot.channelManager.getChannelByName(name); if (!chan) { logger.error('No such channel "%s" exists!', name); return; } chan.enabled = true; logger.log('Channel "%s" enabled!', name); } break; case 'disable': for (const name of args.slice(1)) { const chan = this.bot.channelManager.getChannelByName(name); if (!chan) { logger.error('No such channel "%s" exists!', name); return; } chan.enabled = false; logger.log('Channel "%s" disabled!', name); } break; } this.bot.config.config.channels = this.bot.channelManager.getAll(); await this.bot.config.save(); } public attach(rl: ReadLine): void { rl.on('line', (line: string) => { const split = line.split(' '); if (!split[0]) { return; } switch (split[0]) { case 'r': case 'repo': case 'repository': this.repositoryCommand(...split.slice(1)).catch( e => logger.error(e.message)); break; case 'p': case 'pl': case 'plugin': this.pluginCommand(...split.slice(1)).catch( e => logger.error(e.message)); break; case 'c': case 'chan': case 'channel': this.channelCommand(...split.slice(1)).catch( e => logger.error(e.message)); break; case 'stop': case 'exit': case 'quit': case 'shutdown': this.bot.shutdown(); break; } }); } }