control plugin loads schemas
This commit is contained in:
parent
ab57ca89f6
commit
49b0660f95
@ -3,7 +3,7 @@
|
|||||||
"name": "control",
|
"name": "control",
|
||||||
"description": "Squeebot Plugin Management API and sockets",
|
"description": "Squeebot Plugin Management API and sockets",
|
||||||
"tags": ["api", "control", "management"],
|
"tags": ["api", "control", "management"],
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"npmDependencies": []
|
"npmDependencies": []
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ interface ControlCommand {
|
|||||||
|
|
||||||
let controlCommands: ControlCommand[] = [
|
let controlCommands: ControlCommand[] = [
|
||||||
{
|
{
|
||||||
name: 'execute',
|
name: 'loadPlugin',
|
||||||
plugin: 'control',
|
plugin: 'control',
|
||||||
execute: async (p: ControlPlugin, plugin: string): Promise<void> => {
|
execute: async (p: ControlPlugin, plugin: string): Promise<void> => {
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
@ -325,11 +325,7 @@ let controlCommands: ControlCommand[] = [
|
|||||||
if (!name) {
|
if (!name) {
|
||||||
throw new Error('This function takes 1 argument.');
|
throw new Error('This function takes 1 argument.');
|
||||||
}
|
}
|
||||||
const plugin = p.plugins.get(name);
|
return p.getPluginSchema(name);
|
||||||
if (!plugin) {
|
|
||||||
throw new Error('This plugin has not registered a schema in control.');
|
|
||||||
}
|
|
||||||
return plugin;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -405,6 +401,126 @@ class ControlPlugin extends Plugin {
|
|||||||
this.addEventListener('core', (core: ISqueebotCore) => this.core = core);
|
this.addEventListener('core', (core: ISqueebotCore) => this.core = core);
|
||||||
this.emitTo('core', 'request-core', this.name);
|
this.emitTo('core', 'request-core', this.name);
|
||||||
this.createSocket();
|
this.createSocket();
|
||||||
|
this.getPluginSchema(this.name).catch(
|
||||||
|
() => logger.error('[control] How embarrasing! control could not load it\'s own schema!')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a plugin schema from it's schema file, if it exists.
|
||||||
|
* @param name Plugin name
|
||||||
|
* @returns Plugin schema
|
||||||
|
*/
|
||||||
|
public async loadPluginSchema(name: string): Promise<any> {
|
||||||
|
if (!this.core) {
|
||||||
|
throw new Error('control could not access the core.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { pluginsPath } = this.core.environment;
|
||||||
|
const schemaPath = path.join(pluginsPath, name, 'schema.json');
|
||||||
|
let schema: any;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fileRead = await fs.readFile(schemaPath, { encoding: 'utf8' });
|
||||||
|
schema = JSON.parse(fileRead);
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error('No schema file found, it is not accessible or is not valid JSON.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!schema.type) {
|
||||||
|
throw new Error('Schema does not specify what type of object it is referencing.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugins.set(name, schema);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a plugin's configuration schema directly instead of reading from file.
|
||||||
|
* @param name Plugin name
|
||||||
|
* @param confspec Static schema
|
||||||
|
*/
|
||||||
|
public registerPluginConfigSchema(name: string, confspec?: any): void {
|
||||||
|
this.plugins.set(name, confspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a plugin's configuration schema from memory or from file.
|
||||||
|
* @param name Plugin name
|
||||||
|
* @returns Schema
|
||||||
|
* @throws Error if schema is not found or is invalid
|
||||||
|
*/
|
||||||
|
public async getPluginSchema(name: string): Promise<any> {
|
||||||
|
if (this.plugins.has(name)) {
|
||||||
|
return this.plugins.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.loadPluginSchema(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a registered control command.
|
||||||
|
* @param command Control command
|
||||||
|
* @param args Control command arguments
|
||||||
|
* @returns Control command response
|
||||||
|
*/
|
||||||
|
public async executeControlCommand(command: string, args: string[]): Promise<any> {
|
||||||
|
if (!this.core) {
|
||||||
|
throw new Error('The control plugin cannot control the bot right now.');
|
||||||
|
}
|
||||||
|
const cmdobj = controlCommands.find(k => k.name === command);
|
||||||
|
if (!cmdobj || !cmdobj.execute) {
|
||||||
|
throw new Error('No such command');
|
||||||
|
}
|
||||||
|
return cmdobj.execute.call(this, this, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new custom control command.
|
||||||
|
* @param obj ControlCommand object
|
||||||
|
*/
|
||||||
|
public registerControlCommand(obj: ControlCommand): void {
|
||||||
|
if (!obj.execute || !obj.name || !obj.plugin) {
|
||||||
|
throw new Error('Invalid command object.');
|
||||||
|
}
|
||||||
|
const exists = controlCommands.find(k => k.name === obj.name);
|
||||||
|
if (exists) {
|
||||||
|
throw new Error('Control commands should not be overwritten.');
|
||||||
|
}
|
||||||
|
controlCommands.push(obj);
|
||||||
|
logger.log('[%s] registered control command', this.name, obj.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public listControlCommands(): string[] {
|
||||||
|
return controlCommands.map((command) => command.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener('pluginUnload')
|
||||||
|
public unloadEventHandler(plugin: string | Plugin): void {
|
||||||
|
if (plugin === this.name || plugin === this) {
|
||||||
|
logger.debug('[%s]', this.name, 'shutting down..');
|
||||||
|
|
||||||
|
if (this.server) {
|
||||||
|
logger.log('[%s] Stopping socket server..', this.name);
|
||||||
|
this.server.close();
|
||||||
|
for (const sock of this.sockets) {
|
||||||
|
sock.destroy();
|
||||||
|
}
|
||||||
|
this.sockets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugins.clear();
|
||||||
|
this.emit('pluginUnloaded', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener('pluginUnloaded')
|
||||||
|
public unloadedEventHandler(plugin: string | Plugin): void {
|
||||||
|
if (typeof plugin !== 'string') {
|
||||||
|
plugin = plugin.manifest.name;
|
||||||
|
}
|
||||||
|
this.plugins.delete(plugin);
|
||||||
|
controlCommands = controlCommands.filter(k => k.plugin !== plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private errorToClient(socket: TLSSocket | Socket, error: Error): void {
|
private errorToClient(socket: TLSSocket | Socket, error: Error): void {
|
||||||
@ -551,62 +667,6 @@ class ControlPlugin extends Plugin {
|
|||||||
this.name, c.bind.toString());
|
this.name, c.bind.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerPluginConfigSchema(name: string, confspec?: any): void {
|
|
||||||
this.plugins.set(name, confspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async executeControlCommand(command: string, args: string[]): Promise<any> {
|
|
||||||
if (!this.core) {
|
|
||||||
throw new Error('The control plugin cannot control the bot right now.');
|
|
||||||
}
|
|
||||||
const cmdobj = controlCommands.find(k => k.name === command);
|
|
||||||
if (!cmdobj || !cmdobj.execute) {
|
|
||||||
throw new Error('No such command');
|
|
||||||
}
|
|
||||||
return cmdobj.execute.call(this, this, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public registerControlCommand(obj: ControlCommand): void {
|
|
||||||
if (!obj.execute || !obj.name || !obj.plugin) {
|
|
||||||
throw new Error('Invalid command object.');
|
|
||||||
}
|
|
||||||
const exists = controlCommands.find(k => k.name === obj.name);
|
|
||||||
if (exists) {
|
|
||||||
throw new Error('Control commands should not be overwritten.');
|
|
||||||
}
|
|
||||||
controlCommands.push(obj);
|
|
||||||
logger.log('[%s] registered control command', this.name, obj.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener('pluginUnload')
|
|
||||||
public unloadEventHandler(plugin: string | Plugin): void {
|
|
||||||
if (plugin === this.name || plugin === this) {
|
|
||||||
logger.debug('[%s]', this.name, 'shutting down..');
|
|
||||||
|
|
||||||
if (this.server) {
|
|
||||||
logger.log('[%s] Stopping socket server..', this.name);
|
|
||||||
this.server.close();
|
|
||||||
for (const sock of this.sockets) {
|
|
||||||
sock.destroy();
|
|
||||||
}
|
|
||||||
this.sockets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugins.clear();
|
|
||||||
this.config.save().then(() =>
|
|
||||||
this.emit('pluginUnloaded', this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener('pluginUnloaded')
|
|
||||||
public unloadedEventHandler(plugin: string | Plugin): void {
|
|
||||||
if (typeof plugin !== 'string') {
|
|
||||||
plugin = plugin.manifest.name;
|
|
||||||
}
|
|
||||||
this.plugins.delete(plugin);
|
|
||||||
controlCommands = controlCommands.filter(k => k.plugin !== plugin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ControlPlugin;
|
module.exports = ControlPlugin;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "control",
|
"name": "control",
|
||||||
"version": "0.1.2"
|
"version": "0.1.3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cron",
|
"name": "cron",
|
||||||
|
Loading…
Reference in New Issue
Block a user