utilitas 1989.9.18 → 1989.9.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +1 -0
- package/lib/bot.mjs +103 -0
- package/lib/cache.mjs +1 -0
- package/lib/dbio.mjs +1 -0
- package/lib/email.mjs +1 -0
- package/lib/event.mjs +5 -4
- package/lib/sentinel.mjs +1 -0
- package/lib/shell.mjs +1 -0
- package/lib/sms.mjs +1 -0
- package/lib/tape.mjs +72 -35
- package/lib/uoid.mjs +1 -0
- package/lib/utilitas.mjs +0 -1
- package/package.json +2 -2
package/index.mjs
CHANGED
|
@@ -22,6 +22,7 @@ export * as winston from 'winston';
|
|
|
22
22
|
export * as winstonPapertrail from 'winston-papertrail-mproved';
|
|
23
23
|
|
|
24
24
|
// features
|
|
25
|
+
export * as bot from './lib/bot.mjs';
|
|
25
26
|
export * as cache from './lib/cache.mjs';
|
|
26
27
|
export * as dbio from './lib/dbio.mjs';
|
|
27
28
|
export * as email from './lib/email.mjs';
|
package/lib/bot.mjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// https://github.com/telegraf/telegraf
|
|
2
|
+
|
|
3
|
+
import { Telegraf } from 'telegraf';
|
|
4
|
+
import * as utilitas from './utilitas.mjs';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
const fileURLToPath = (await import('url')).fileURLToPath
|
|
9
|
+
|| ((url) => { return new URL('', url).pathname; });
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const signals = ['SIGINT', 'SIGTERM'];
|
|
12
|
+
const provider = 'TELEGRAM';
|
|
13
|
+
const c = (s, r) => { return ~~utilitas.insensitiveCompare(s, r, { w: true }) };
|
|
14
|
+
|
|
15
|
+
let bot;
|
|
16
|
+
|
|
17
|
+
const questions = [{
|
|
18
|
+
q: ['The Ultimate Question of Life, the Universe, and Everything',
|
|
19
|
+
'The answer to life the universe and everything'],
|
|
20
|
+
a: '42',
|
|
21
|
+
}, {
|
|
22
|
+
q: ['THE THREE LAWS'],
|
|
23
|
+
a: ['- A robot may not injure a human being or, through inaction, allow a human being to come to harm.',
|
|
24
|
+
'- A robot must obey the orders given it by human beings except where such orders would conflict with the First Law.',
|
|
25
|
+
'- A robot must protect its own existence as long as such protection does not conflict with the First or Second Laws.'].join('\n'),
|
|
26
|
+
}];
|
|
27
|
+
|
|
28
|
+
const subconscious = {
|
|
29
|
+
run: true, name: 'Subconscious', func: async (bot) => {
|
|
30
|
+
bot.use(async (ctx, next) => {
|
|
31
|
+
log(ctx.update);
|
|
32
|
+
|
|
33
|
+
await next();
|
|
34
|
+
});
|
|
35
|
+
bot.on('text', async (ctx, next) => {
|
|
36
|
+
questions.map(s => {
|
|
37
|
+
s.q.map(x => { c(x, ctx.update.message.text) && ctx.reply(s.a) })
|
|
38
|
+
});
|
|
39
|
+
await next();
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const log = (c, o) => {
|
|
45
|
+
utilitas.modLog(c, utilitas.basename(__filename), { time: true, ...o || {} });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const train = async (bot, func, name, options) => {
|
|
49
|
+
log(`Training: ${name = name || uuidv4()}`, { force: true });
|
|
50
|
+
return await func(bot);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const load = async (bot, module, options) => {
|
|
54
|
+
utilitas.assert(module && module.func, 'Skill function is required.', 500);
|
|
55
|
+
return await train(bot, module.func, module.name, options);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const init = async (options) => {
|
|
59
|
+
if (options) {
|
|
60
|
+
utilitas.assert(
|
|
61
|
+
utilitas.insensitiveCompare(options?.provider, provider),
|
|
62
|
+
'Invalid bot provider.', 501
|
|
63
|
+
);
|
|
64
|
+
bot = new Telegraf(options?.botToken);
|
|
65
|
+
const [mods, pmsTrain] = [[
|
|
66
|
+
{ ...subconscious, run: !options?.silent },
|
|
67
|
+
...utilitas.ensureArray(options?.skill)
|
|
68
|
+
], []];
|
|
69
|
+
for (let skillPath of utilitas.ensureArray(options?.skillPath)) {
|
|
70
|
+
log(`SKILLS: ${skillPath}`);
|
|
71
|
+
const files = (fs.readdirSync(skillPath) || []).filter(
|
|
72
|
+
file => /\.mjs$/i.test(file) && !file.startsWith('.')
|
|
73
|
+
);
|
|
74
|
+
for (let file of files) {
|
|
75
|
+
const m = await import(path.join(skillPath, file));
|
|
76
|
+
mods.push({ ...m, name: m.name || f.replace(/^(.*)\.mjs$/i, '$1') });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
mods.map(mod => { mod.run && pmsTrain.push(load(bot, mod, options)) });
|
|
80
|
+
utilitas.assert(pmsTrain.length, 'Invalid skill set.', 501);
|
|
81
|
+
await Promise.all(pmsTrain);
|
|
82
|
+
bot.launch();
|
|
83
|
+
// Graceful stop
|
|
84
|
+
signals.map(signal => process.once(signal, () => bot.stop(signal)));
|
|
85
|
+
}
|
|
86
|
+
utilitas.assert(bot, 'Bot have not been initialized.', 501);
|
|
87
|
+
return bot;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const send = async (chatId, content, options) => {
|
|
91
|
+
return (await init()).telegram.sendMessage(chatId, content);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const end = async (options) => {
|
|
95
|
+
return bot && bot.stop(options?.signal);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default init;
|
|
99
|
+
export {
|
|
100
|
+
end,
|
|
101
|
+
send,
|
|
102
|
+
init,
|
|
103
|
+
};
|
package/lib/cache.mjs
CHANGED
package/lib/dbio.mjs
CHANGED
package/lib/email.mjs
CHANGED
package/lib/event.mjs
CHANGED
|
@@ -5,7 +5,6 @@ import path from 'path';
|
|
|
5
5
|
|
|
6
6
|
const fileURLToPath = (await import('url')).fileURLToPath
|
|
7
7
|
|| ((url) => { return new URL('', url).pathname; });
|
|
8
|
-
|
|
9
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
9
|
const jobs = {};
|
|
11
10
|
const sToMs = (sec) => { return 1000 * (isNaN(sec = Number(sec)) ? 0 : sec); };
|
|
@@ -51,9 +50,9 @@ const exec = async () => {
|
|
|
51
50
|
|
|
52
51
|
const loop = async (func, interval, tout, delay, name, options = {}) => {
|
|
53
52
|
timer = timer || log('Initialized.') || setInterval(exec, 1000 * 1);
|
|
54
|
-
log('Scheduled.', name, { force: true });
|
|
53
|
+
log('Scheduled.', (name = name || uuidv4()), { force: true });
|
|
55
54
|
await utilitas.timeout((delay = sToMs(delay)));
|
|
56
|
-
jobs[
|
|
55
|
+
jobs[name] = {
|
|
57
56
|
function: func,
|
|
58
57
|
interval: sToMs(interval),
|
|
59
58
|
timeout: sToMs(tout),
|
|
@@ -89,7 +88,8 @@ const bulk = async (absDir, options) => {
|
|
|
89
88
|
return await Promise.all(pmsRun);
|
|
90
89
|
};
|
|
91
90
|
|
|
92
|
-
const end = async () => {
|
|
91
|
+
const end = async (name) => {
|
|
92
|
+
if (name) { delete jobs[name]; if (jobs.length) { return; } }
|
|
93
93
|
clearInterval(timer);
|
|
94
94
|
timer = -1;
|
|
95
95
|
const now = Date.now();
|
|
@@ -103,6 +103,7 @@ const end = async () => {
|
|
|
103
103
|
log('Terminated.');
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
+
export default loop;
|
|
106
107
|
export {
|
|
107
108
|
bulk,
|
|
108
109
|
end,
|
package/lib/sentinel.mjs
CHANGED
package/lib/shell.mjs
CHANGED
package/lib/sms.mjs
CHANGED
package/lib/tape.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as bot from './bot.mjs';
|
|
2
|
+
import * as event from './event.mjs';
|
|
1
3
|
import * as utilitas from './utilitas.mjs';
|
|
2
4
|
|
|
3
5
|
// https://github.com/winstonjs/winston#logging-levels
|
|
@@ -5,12 +7,12 @@ import * as utilitas from './utilitas.mjs';
|
|
|
5
7
|
// Handle, report, or silently ignore connection errors and failures
|
|
6
8
|
const handleError = (err) => { process.stdout.write(`${err.message}\n`); };
|
|
7
9
|
const consoleMap = { log: 'verbose', info: 0, debug: 0, warn: 0, error: 0 };
|
|
8
|
-
const
|
|
10
|
+
const TAPE = 'TAPE';
|
|
11
|
+
const modLog = (content) => { return utilitas.modLog(content, TAPE); };
|
|
9
12
|
const getLogger = async () => { return (await init()).logger; };
|
|
10
|
-
const [
|
|
11
|
-
// why keeping providerPapertrail ?
|
|
13
|
+
const [BOT, RSYSLOG, PAPERTRAIL] = ['BOT', 'RSYSLOG', 'PAPERTRAIL'];
|
|
12
14
|
|
|
13
|
-
let winston, papertrail, papertrailConnection,
|
|
15
|
+
let chatIds, tarLevel, botBuffer, winston, papertrail, papertrailConnection,
|
|
14
16
|
papertrailTransport, logger, silent, provider;
|
|
15
17
|
|
|
16
18
|
// Do something after the connection to the Papertrail server is established
|
|
@@ -25,8 +27,7 @@ const hookConsole = () => {
|
|
|
25
27
|
console[bakAct] = console[act];
|
|
26
28
|
console[act] = function() {
|
|
27
29
|
const str = [...arguments].map(utilitas.ensureString).join(' ');
|
|
28
|
-
|
|
29
|
-
logger && logger.log(tar, str);
|
|
30
|
+
logger && logger.log(tar, str.replace(/\u001b\[\d+m/g, ''));
|
|
30
31
|
console[bakAct].apply(console, arguments);
|
|
31
32
|
};
|
|
32
33
|
}
|
|
@@ -43,51 +44,87 @@ const releaseConsole = () => {
|
|
|
43
44
|
|
|
44
45
|
const getDefaultOptions = async (provider, options) => {
|
|
45
46
|
const result = { program: (await utilitas.which()).name };
|
|
46
|
-
switch (provider) {
|
|
47
|
-
case
|
|
48
|
-
result.disableTls = true;
|
|
49
|
-
result.logFormat = (level, message) => {
|
|
50
|
-
return message.replace(/\u001b\[\d+m/g, '');
|
|
51
|
-
}
|
|
47
|
+
switch (provider) { // result.logFormat = (level, message) => { return message; }
|
|
48
|
+
case RSYSLOG: result.disableTls = true;
|
|
52
49
|
}
|
|
53
50
|
return Object.assign(result, options || {});
|
|
54
51
|
};
|
|
55
52
|
|
|
53
|
+
const sysLogInit = async (options) => {
|
|
54
|
+
options = await getDefaultOptions(provider, options);
|
|
55
|
+
winston = await import('winston');
|
|
56
|
+
papertrail = await import('winston-papertrail-mproved');
|
|
57
|
+
papertrailConnection = new papertrail.PapertrailConnection(options);
|
|
58
|
+
papertrailConnection.on('error', handleError);
|
|
59
|
+
papertrailConnection.on('connect', handleConnect);
|
|
60
|
+
papertrailTransport = new papertrail.PapertrailTransport(
|
|
61
|
+
papertrailConnection, options
|
|
62
|
+
);
|
|
63
|
+
logger = new winston.createLogger({ transports: [papertrailTransport] });
|
|
64
|
+
return {
|
|
65
|
+
logger,
|
|
66
|
+
dependencies: { winston, papertrail, papertrailConnection, papertrailTransport },
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const botLoggerInit = (options) => {
|
|
71
|
+
chatIds = utilitas.ensureArray(options?.chatId);
|
|
72
|
+
utilitas.assert(chatIds.length, 'ChatId is required.', 501);
|
|
73
|
+
handleConnect(`Sending logs via bot, chatId: ${chatIds.join(', ')}.`);
|
|
74
|
+
logger = botLogger;
|
|
75
|
+
event.loop(botLoggerSync, 5, 10, 0, TAPE, { silent: true });
|
|
76
|
+
return { logger, dependencies: { bot, event } };
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const botLoggerSync = async () => {
|
|
80
|
+
const fetched = (botBuffer?.length ? botBuffer.splice(0) : []).join('\n');
|
|
81
|
+
if (!fetched.length) { return; }
|
|
82
|
+
for (let id of chatIds) {
|
|
83
|
+
try { await bot.send(id, fetched); }
|
|
84
|
+
catch (e) { process.stdout.write(`Tape error: ${e.message}\n`); }
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const botLogger = {
|
|
89
|
+
log: (level, message) => {
|
|
90
|
+
if (tarLevel !== 'verbose' && level === 'verbose') { return; }
|
|
91
|
+
(botBuffer = botBuffer || []).push([level, message]);
|
|
92
|
+
},
|
|
93
|
+
end: () => { chatIds = null; botBuffer = null; event.end(TAPE); },
|
|
94
|
+
};
|
|
95
|
+
|
|
56
96
|
// use options.level = 'verbose' to send console.log logs
|
|
57
97
|
const init = async (options) => {
|
|
98
|
+
let result;
|
|
58
99
|
if (options) {
|
|
59
|
-
silent = !!options
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
100
|
+
silent = !!options?.silent;
|
|
101
|
+
tarLevel = options?.level;
|
|
102
|
+
provider = utilitas.ensureString(options?.provider, { case: 'UP' });
|
|
103
|
+
switch (provider) {
|
|
104
|
+
case BOT:
|
|
105
|
+
result = await botLoggerInit(options);
|
|
106
|
+
break;
|
|
107
|
+
case RSYSLOG:
|
|
108
|
+
case PAPERTRAIL:
|
|
109
|
+
result = await sysLogInit(options);
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
utilitas.throwError(
|
|
113
|
+
`Invalid tape provider: '${options?.provider}'.`, 501
|
|
114
|
+
);
|
|
115
|
+
}
|
|
75
116
|
options.noHook || hookConsole();
|
|
76
117
|
}
|
|
77
118
|
utilitas.assert(logger, 'Logger client has not been initialized.', 501);
|
|
78
|
-
return
|
|
79
|
-
winston, papertrail, papertrailConnection, papertrailTransport, logger
|
|
80
|
-
};
|
|
119
|
+
return result;
|
|
81
120
|
};
|
|
82
121
|
|
|
83
122
|
const end = async () => {
|
|
84
123
|
releaseConsole();
|
|
85
|
-
setTimeout(() => {
|
|
86
|
-
logger && logger.end();
|
|
87
|
-
modLog('Terminated.');
|
|
88
|
-
}, 1000);
|
|
124
|
+
setTimeout(() => { logger?.end?.(); modLog('Terminated.'); }, 1000);
|
|
89
125
|
};
|
|
90
126
|
|
|
127
|
+
export default init;
|
|
91
128
|
export {
|
|
92
129
|
end,
|
|
93
130
|
getLogger,
|
package/lib/uoid.mjs
CHANGED
package/lib/utilitas.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "utilitas",
|
|
3
3
|
"description": "Just another common utility for Node.js.",
|
|
4
|
-
"version": "1989.9.
|
|
4
|
+
"version": "1989.9.22",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/utilitas",
|
|
7
7
|
"main": "index.mjs",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"qs": "^6.10.3",
|
|
43
43
|
"telegraf": "^4.7.0",
|
|
44
44
|
"telesignsdk": "^2.2.1",
|
|
45
|
-
"twilio": "^3.
|
|
45
|
+
"twilio": "^3.74.0",
|
|
46
46
|
"uuid": "^8.3.2",
|
|
47
47
|
"winston": "^3.5.1",
|
|
48
48
|
"winston-papertrail-mproved": "^1.0.7"
|