implement new sendTo method
This commit is contained in:
parent
bac88841b0
commit
2483a67088
9
cron/plugin.json
Normal file
9
cron/plugin.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"main": "plugin.js",
|
||||||
|
"name": "cron",
|
||||||
|
"description": "API for plugin-scoped cron tasks",
|
||||||
|
"tags": ["timers", "cron", "scheduler", "api"],
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": ["control?"],
|
||||||
|
"npmDependencies": ["node-cron@3.0.0"]
|
||||||
|
}
|
166
cron/plugin.ts
Normal file
166
cron/plugin.ts
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import { logger } from '@squeebot/core/lib/core';
|
||||||
|
import {
|
||||||
|
Plugin,
|
||||||
|
Configurable,
|
||||||
|
EventListener,
|
||||||
|
IPlugin,
|
||||||
|
} from '@squeebot/core/lib/plugin';
|
||||||
|
|
||||||
|
import nodeCron, { ScheduledTask } from 'node-cron';
|
||||||
|
|
||||||
|
type ExecutorFn = (...args: any[]) => void;
|
||||||
|
|
||||||
|
class CronWrapper {
|
||||||
|
private cronTask: ScheduledTask | null = null;
|
||||||
|
public id = Math.random().toString(36).slice(2);
|
||||||
|
public stopped = true;
|
||||||
|
public destroyed = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public expression: string,
|
||||||
|
public taskFn: ExecutorFn,
|
||||||
|
public origin: IPlugin,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
assert(): void {
|
||||||
|
if (!nodeCron.validate(this.expression)) {
|
||||||
|
throw new Error('Invalid cron pattern!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start(): void {
|
||||||
|
if (this.destroyed) {
|
||||||
|
logger.warn('[cron] Someone tried to start a destroyed task! This could indicate a memory leak!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.cronTask) {
|
||||||
|
this.assert();
|
||||||
|
this.cronTask = nodeCron.schedule(this.expression, this.execute, {
|
||||||
|
scheduled: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cronTask.start();
|
||||||
|
this.stopped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop(): void {
|
||||||
|
if (!this.cronTask) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cronTask.stop();
|
||||||
|
this.stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
this.destroyed = true;
|
||||||
|
|
||||||
|
if (!this.cronTask) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cronTask.destroy();
|
||||||
|
this.cronTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(): void {
|
||||||
|
this.taskFn.call(this.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
belongsTo(plugin: IPlugin | string): boolean {
|
||||||
|
if (typeof plugin === 'string') {
|
||||||
|
return this.origin.manifest.name === plugin;
|
||||||
|
}
|
||||||
|
return plugin === this.origin ||
|
||||||
|
plugin.manifest.name === this.origin.manifest.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Configurable({})
|
||||||
|
class CronPlugin extends Plugin {
|
||||||
|
private timers: CronWrapper[] = [];
|
||||||
|
|
||||||
|
@EventListener('pluginUnload')
|
||||||
|
public unloadEventHandler(plugin: string | Plugin): void {
|
||||||
|
if (plugin === this.name || plugin === this) {
|
||||||
|
this.timers.forEach((timer) => timer.destroy());
|
||||||
|
this.timers = [];
|
||||||
|
this.emit('pluginUnloaded', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener('pluginUnloaded')
|
||||||
|
public unloadedEventHandler(plugin: string | Plugin): void {
|
||||||
|
this.timers.forEach((timer) => {
|
||||||
|
if (timer.belongsTo(plugin)) {
|
||||||
|
timer.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns A list of tasks including id, cron expression and origin plugin.
|
||||||
|
*/
|
||||||
|
public getList(): string[][] {
|
||||||
|
return this.timers.map((timer) => ([
|
||||||
|
timer.id,
|
||||||
|
timer.expression,
|
||||||
|
timer.origin.manifest.name,
|
||||||
|
timer.destroyed || timer.stopped ? 'stopped' : 'running',
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new cron task
|
||||||
|
* @param plugin Plugin registering this task
|
||||||
|
* @param expression Cron expression
|
||||||
|
* @param taskFn Function to execute
|
||||||
|
* @param autostart Start the scheduler on add
|
||||||
|
* @returns The task
|
||||||
|
*/
|
||||||
|
public registerTimer(
|
||||||
|
plugin: IPlugin,
|
||||||
|
expression: string,
|
||||||
|
taskFn: ExecutorFn,
|
||||||
|
autostart = true,
|
||||||
|
): CronWrapper {
|
||||||
|
const newTimer = new CronWrapper(expression, taskFn, plugin);
|
||||||
|
|
||||||
|
newTimer.assert();
|
||||||
|
if (autostart) {
|
||||||
|
newTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a scheduled timer by ID or by the object itself.
|
||||||
|
* Always use this to ensure that memory is properly cleared.
|
||||||
|
* @param timer Timer or timer ID
|
||||||
|
*/
|
||||||
|
public removeTimer(timer: string | CronWrapper): void {
|
||||||
|
if (typeof timer === 'string') {
|
||||||
|
const find = this.timers.find((item) => item.id === timer);
|
||||||
|
if (find) {
|
||||||
|
find.destroy();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timer.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove destroyed timers from the cache
|
||||||
|
*/
|
||||||
|
private cleanUp(): void {
|
||||||
|
this.timers = this.timers.filter((timer) => !timer.destroyed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CronPlugin;
|
85
package-lock.json
generated
85
package-lock.json
generated
@ -10,10 +10,12 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@squeebot/core": "^3.3.1",
|
"@squeebot/core": "^3.3.1",
|
||||||
|
"node-cron": "^3.0.0",
|
||||||
"typescript": "^4.4.2"
|
"typescript": "^4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.7.10"
|
"@types/node": "^16.7.10",
|
||||||
|
"@types/node-cron": "^2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../core": {
|
"../core": {
|
||||||
@ -54,6 +56,21 @@
|
|||||||
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node-cron": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-vXzgDRWCZpuut5wJVZtluEnkNhzGojYlyMch2c4kMj7H74L8xTLytVlgQzj+/17wfcjs49aJDFBDglFSGt7GeA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tz-offset": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/tz-offset": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tz-offset/-/tz-offset-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/at-least-node": {
|
"node_modules/at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@ -164,6 +181,36 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.29.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
|
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/moment-timezone": {
|
||||||
|
"version": "0.5.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz",
|
||||||
|
"integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"moment": ">= 2.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-cron": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==",
|
||||||
|
"dependencies": {
|
||||||
|
"moment-timezone": "^0.5.31"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||||
@ -238,6 +285,21 @@
|
|||||||
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/node-cron": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-vXzgDRWCZpuut5wJVZtluEnkNhzGojYlyMch2c4kMj7H74L8xTLytVlgQzj+/17wfcjs49aJDFBDglFSGt7GeA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/tz-offset": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/tz-offset": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tz-offset/-/tz-offset-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"at-least-node": {
|
"at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@ -316,6 +378,27 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.29.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
|
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||||
|
},
|
||||||
|
"moment-timezone": {
|
||||||
|
"version": "0.5.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz",
|
||||||
|
"integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==",
|
||||||
|
"requires": {
|
||||||
|
"moment": ">= 2.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-cron": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==",
|
||||||
|
"requires": {
|
||||||
|
"moment-timezone": "^0.5.31"
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@squeebot/core": "^3.3.1",
|
"@squeebot/core": "^3.3.1",
|
||||||
|
"node-cron": "^3.0.0",
|
||||||
"typescript": "^4.4.2"
|
"typescript": "^4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.7.10"
|
"@types/node": "^16.7.10",
|
||||||
|
"@types/node-cron": "^2.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
"name": "control",
|
"name": "control",
|
||||||
"version": "0.1.1"
|
"version": "0.1.1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "cron",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "permissions",
|
"name": "permissions",
|
||||||
"version": "0.1.0"
|
"version": "0.1.0"
|
||||||
@ -12,6 +16,10 @@
|
|||||||
{
|
{
|
||||||
"name": "simplecommands",
|
"name": "simplecommands",
|
||||||
"version": "1.1.1"
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xprotocol",
|
||||||
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"typescript": true
|
"typescript": true
|
||||||
|
9
xprotocol/plugin.json
Normal file
9
xprotocol/plugin.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"main": "plugin.js",
|
||||||
|
"name": "xprotocol",
|
||||||
|
"description": "API for sending messages to other protocols",
|
||||||
|
"tags": ["messages", "relaying", "api"],
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": ["control?"],
|
||||||
|
"npmDependencies": []
|
||||||
|
}
|
55
xprotocol/plugin.ts
Normal file
55
xprotocol/plugin.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { ISqueebotCore, logger } from '@squeebot/core/lib/core';
|
||||||
|
import {
|
||||||
|
Plugin,
|
||||||
|
EventListener,
|
||||||
|
} from '@squeebot/core/lib/plugin';
|
||||||
|
|
||||||
|
class XProtocolPlugin extends Plugin {
|
||||||
|
private core: ISqueebotCore | null = null;
|
||||||
|
|
||||||
|
@EventListener('pluginUnload')
|
||||||
|
public unloadEventHandler(plugin: string | Plugin): void {
|
||||||
|
if (plugin === this.name || plugin === this) {
|
||||||
|
this.core = null;
|
||||||
|
this.emit('pluginUnloaded', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async sendTo(target: string, ...data: any[]): Promise<boolean> {
|
||||||
|
if (!this.core) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find target plugin
|
||||||
|
const rxSplit = target.split('/');
|
||||||
|
const plugin = this.core.pluginManager.getLoadedByName(rxSplit[0]);
|
||||||
|
if (!plugin || !plugin.service) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find target protocol
|
||||||
|
const protocol = plugin.service.getProtocolByName(rxSplit[1]);
|
||||||
|
if (!protocol || !protocol.running) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return protocol.sendTo(target, ...data);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize(): void {
|
||||||
|
this.on('core', (core: ISqueebotCore) => {
|
||||||
|
this.core = core;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.emitTo('core', 'request-core', this.name);
|
||||||
|
|
||||||
|
this.on('send', (data: any[]) => {
|
||||||
|
const target = data[0];
|
||||||
|
this.sendTo(target, ...data.slice(1)).catch((error: Error) => {
|
||||||
|
logger.error(`[sendto] Sending to protocol from event failed:`, error.message ?? error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = XProtocolPlugin;
|
Loading…
Reference in New Issue
Block a user