utilitas 1990.1.28 → 1990.1.31
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/.github/workflows/npm-publish.yml +46 -0
- package/README.md +2 -0
- package/lib/bot.mjs +38 -22
- package/lib/manifest.mjs +2 -2
- package/lib/network.mjs +3 -1
- package/lib/shot.mjs +2 -2
- package/lib/storage.mjs +17 -32
- package/lib/tape.mjs +3 -3
- package/lib/utilitas.mjs +12 -6
- package/package.json +3 -3
- package/dist/utilitas.lite.mjs +0 -3
- package/dist/utilitas.lite.mjs.LICENSE.txt +0 -41
- package/dist/utilitas.lite.mjs.map +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
3
|
+
|
|
4
|
+
name: Node.js Package
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [ master ]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [ master ]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
version:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
if: "!startsWith(github.event.head_commit.message, '[RELEASE]')"
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v3
|
|
18
|
+
with:
|
|
19
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
20
|
+
- run: git config --global user.name 'Leask Wong'
|
|
21
|
+
- run: git config --global user.email 'i@leaskh.com'
|
|
22
|
+
- run: npm version patch -m "[RELEASE] %s"
|
|
23
|
+
- run: git push
|
|
24
|
+
|
|
25
|
+
build:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
needs: version
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v3
|
|
30
|
+
- uses: actions/setup-node@v3
|
|
31
|
+
with:
|
|
32
|
+
node-version: 16
|
|
33
|
+
- run: npm test
|
|
34
|
+
|
|
35
|
+
publish-npm:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v3
|
|
40
|
+
- uses: actions/setup-node@v3
|
|
41
|
+
with:
|
|
42
|
+
node-version: 16
|
|
43
|
+
registry-url: https://registry.npmjs.org/
|
|
44
|
+
- run: npm publish
|
|
45
|
+
env:
|
|
46
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/README.md
CHANGED
package/lib/bot.mjs
CHANGED
|
@@ -4,9 +4,10 @@ import { ensureArray, insensitiveCompare, log as _log } from './utilitas.mjs';
|
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { readdirSync } from 'fs';
|
|
6
6
|
import { Telegraf } from 'telegraf';
|
|
7
|
+
import cluster from 'cluster';
|
|
7
8
|
|
|
8
9
|
const signals = ['SIGINT', 'SIGTERM'];
|
|
9
|
-
const provider = 'TELEGRAM';
|
|
10
|
+
const [BOT_SEND, provider, MESSAGE] = ['BOT_SEND', 'TELEGRAM', 'message'];
|
|
10
11
|
const iCmp = (strA, strB) => ~~insensitiveCompare(strA, strB, { w: true });
|
|
11
12
|
const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
12
13
|
const end = async (options) => bot && bot.stop(options?.signal);
|
|
@@ -56,34 +57,49 @@ const init = async (options) => {
|
|
|
56
57
|
insensitiveCompare(options?.provider, provider),
|
|
57
58
|
'Invalid bot provider.', 501
|
|
58
59
|
);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
60
|
+
if (cluster.isPrimary) {
|
|
61
|
+
bot = new Telegraf(options?.botToken);
|
|
62
|
+
const [mods, pmsTrain] = [[{
|
|
63
|
+
...subconscious, run: !options?.silent
|
|
64
|
+
}, ...ensureArray(options?.skill)], []];
|
|
65
|
+
for (let skillPath of ensureArray(options?.skillPath)) {
|
|
66
|
+
log(`SKILLS: ${skillPath}`);
|
|
67
|
+
const files = (readdirSync(skillPath) || []).filter(
|
|
68
|
+
file => /\.mjs$/i.test(file) && !file.startsWith('.')
|
|
69
|
+
);
|
|
70
|
+
for (let f of files) {
|
|
71
|
+
const m = await import(join(skillPath, f));
|
|
72
|
+
mods.push({ ...m, name: m.name || f.replace(/^(.*)\.mjs$/i, '$1') });
|
|
73
|
+
}
|
|
71
74
|
}
|
|
75
|
+
mods.map(mod => { mod.run && pmsTrain.push(load(bot, mod, options)) });
|
|
76
|
+
assert(pmsTrain.length, 'Invalid skill set.', 501);
|
|
77
|
+
await Promise.all(pmsTrain);
|
|
78
|
+
bot.launch();
|
|
79
|
+
cluster.on(MESSAGE, (worker, msg) => eventHandler(msg));
|
|
80
|
+
// Graceful stop
|
|
81
|
+
signals.map(signal => process.once(signal, () => bot.stop(signal)));
|
|
82
|
+
} else {
|
|
83
|
+
bot = {
|
|
84
|
+
telegram: {
|
|
85
|
+
sendMessage: (...args) =>
|
|
86
|
+
process.send({ action: BOT_SEND, data: args })
|
|
87
|
+
}
|
|
88
|
+
};
|
|
72
89
|
}
|
|
73
|
-
mods.map(mod => { mod.run && pmsTrain.push(load(bot, mod, options)) });
|
|
74
|
-
assert(pmsTrain.length, 'Invalid skill set.', 501);
|
|
75
|
-
await Promise.all(pmsTrain);
|
|
76
|
-
bot.launch();
|
|
77
|
-
// Graceful stop
|
|
78
|
-
signals.map(signal => process.once(signal, () => bot.stop(signal)));
|
|
79
90
|
}
|
|
80
91
|
assert(bot, 'Bot have not been initialized.', 501);
|
|
81
92
|
return bot;
|
|
82
93
|
};
|
|
83
94
|
|
|
84
|
-
const send = async (chatId, content, options) =>
|
|
85
|
-
await init()
|
|
86
|
-
|
|
95
|
+
const send = async (chatId, content, options) =>
|
|
96
|
+
(await init()).telegram.sendMessage(chatId, content);
|
|
97
|
+
|
|
98
|
+
const eventHandler = async (msg) => {
|
|
99
|
+
switch (msg?.action) {
|
|
100
|
+
case BOT_SEND: return await send(...msg?.data || []);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
87
103
|
|
|
88
104
|
export default init;
|
|
89
105
|
export {
|
package/lib/manifest.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const manifest = {
|
|
2
2
|
"name": "utilitas",
|
|
3
3
|
"description": "Just another common utility for JavaScript.",
|
|
4
|
-
"version": "1990.1.
|
|
4
|
+
"version": "1990.1.29",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/utilitas",
|
|
7
7
|
"main": "index.mjs",
|
|
@@ -16,7 +16,7 @@ const manifest = {
|
|
|
16
16
|
"url": "https://github.com/Leask/utilitas.git"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@sentry/node": "^6.19.
|
|
19
|
+
"@sentry/node": "^6.19.7",
|
|
20
20
|
"base64url": "^3.0.1",
|
|
21
21
|
"buffer": "^6.0.3",
|
|
22
22
|
"fast-geoip": "^1.1.68",
|
package/lib/network.mjs
CHANGED
|
@@ -4,7 +4,8 @@ import { ensureArray, log as _log, throwError } from './utilitas.mjs';
|
|
|
4
4
|
import { getCurrentIp } from './shot.mjs';
|
|
5
5
|
import { lookup } from 'fast-geoip';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const isLocalhost = host => ['127.0.0.1', '::1', 'localhost'].includes(host);
|
|
8
|
+
const log = content => _log(content, import.meta.url);
|
|
8
9
|
|
|
9
10
|
const ping = async (host, options = { timeout: 3, min_reply: 3 }) => {
|
|
10
11
|
await assertExist('ping');
|
|
@@ -94,6 +95,7 @@ const getCurrentPosition = async () => {
|
|
|
94
95
|
export {
|
|
95
96
|
getCurrentPosition,
|
|
96
97
|
httping,
|
|
98
|
+
isLocalhost,
|
|
97
99
|
pickFastestHost,
|
|
98
100
|
pickFastestHttpServer,
|
|
99
101
|
ping,
|
package/lib/shot.mjs
CHANGED
|
@@ -63,7 +63,7 @@ const get = async (url, options) => {
|
|
|
63
63
|
) : [];
|
|
64
64
|
const meta = options?.refresh || !base ? null : await readJson(cacheMeta);
|
|
65
65
|
const cache = options?.refresh || !base ? null : await ignoreErrFunc(
|
|
66
|
-
|
|
66
|
+
() => fs.readFile(cacheCont)
|
|
67
67
|
);
|
|
68
68
|
const headers = meta?.responseHeaders && cache ? {
|
|
69
69
|
'cache-control': 'max-age=0',
|
|
@@ -75,7 +75,7 @@ const get = async (url, options) => {
|
|
|
75
75
|
if (options.timeout) {
|
|
76
76
|
const controller = new AbortController();
|
|
77
77
|
fetchOptions.signal = controller.signal;
|
|
78
|
-
timer = setTimeout(() =>
|
|
78
|
+
timer = setTimeout(() => controller.abort(), options.timeout);
|
|
79
79
|
}
|
|
80
80
|
try { r = await fetch(url, fetchOptions); } catch (e) {
|
|
81
81
|
throwError(e.message.includes('aborted') ? 'Timed out.' : e.message, 500);
|
package/lib/storage.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { constants, promises as fs, readSync } from 'fs';
|
|
1
|
+
import { constants as consts, promises as fs, readSync } from 'fs';
|
|
2
2
|
import { ensureString, mergeAtoB, throwError, trim, which } from './utilitas.mjs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { parse as iniParse, stringify as iniStringify } from 'ini';
|
|
@@ -45,42 +45,27 @@ const writeTempFile = async (data, options) => {
|
|
|
45
45
|
return filepath;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const assertPath = async (path, type, mode,
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
|
|
52
|
-
}
|
|
48
|
+
const assertPath = async (path, type, mode, msg, code, options) => {
|
|
49
|
+
var [code, b, E, s, err] = [code || 500, 'Path is not', m => err = msg || m];
|
|
50
|
+
try { s = await fs.stat(path); }
|
|
51
|
+
catch (e) { throwError(msg || e.message, code, options); }
|
|
53
52
|
switch (String(type || '').toUpperCase()) {
|
|
54
|
-
case '*': case '':
|
|
55
|
-
|
|
56
|
-
case '
|
|
57
|
-
|
|
58
|
-
? null : (message || `Path is not a file: '${path}'.`);
|
|
59
|
-
break;
|
|
60
|
-
case 'D':
|
|
61
|
-
typeErr = stat.isDirectory()
|
|
62
|
-
? null : (message || `Path is not a directory: '${path}'.`);
|
|
63
|
-
break;
|
|
64
|
-
default:
|
|
65
|
-
typeErr = message || `Unsupported path type: '${type}'.`;
|
|
53
|
+
case '*': case '': break;
|
|
54
|
+
case 'F': s.isFile() || E(`${b} a file: '${path}'.`); break;
|
|
55
|
+
case 'D': s.isDirectory() || E(`${b} a directory: '${path}'.`); break;
|
|
56
|
+
default: E(`Unsupported path type: '${type}'.`);
|
|
66
57
|
}
|
|
67
|
-
assert(!
|
|
58
|
+
assert(!err, err, code, options);
|
|
68
59
|
try {
|
|
69
60
|
switch (String(mode || '').toUpperCase()) {
|
|
70
|
-
case '*': case '':
|
|
71
|
-
|
|
72
|
-
case '
|
|
73
|
-
|
|
74
|
-
break;
|
|
75
|
-
case 'W':
|
|
76
|
-
await fs.access(path, constants.R_OK | constants.W_OK);
|
|
77
|
-
break;
|
|
78
|
-
default:
|
|
79
|
-
modeErr = message || `Unsupported access mode: '${mode}'.`;
|
|
61
|
+
case '*': case '': break;
|
|
62
|
+
case 'R': await fs.access(path, consts.R_OK); break;
|
|
63
|
+
case 'W': await fs.access(path, consts.R_OK | consts.W_OK); break;
|
|
64
|
+
default: E(`Unsupported access mode: '${mode}'.`);
|
|
80
65
|
};
|
|
81
|
-
} catch (
|
|
82
|
-
assert(!
|
|
83
|
-
return
|
|
66
|
+
} catch (e) { E(e.message); }
|
|
67
|
+
assert(!err, err, code, options);
|
|
68
|
+
return s;
|
|
84
69
|
};
|
|
85
70
|
|
|
86
71
|
const isTextFile = async (filename, options) => {
|
package/lib/tape.mjs
CHANGED
|
@@ -10,10 +10,10 @@ const consoleMap = ['log', 'info', 'debug', 'warn', 'error'];
|
|
|
10
10
|
const trace = { trace: true };
|
|
11
11
|
const [TAPE, BOT] = ['TAPE', 'BOT'];
|
|
12
12
|
const [maxLength, defBufCycle, maxBufCycle] = [4096, 10, 100];
|
|
13
|
-
const stdout =
|
|
13
|
+
const stdout = message => process.stdout.write(`${message}\n`);
|
|
14
14
|
const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
15
|
-
const getSendTxt =
|
|
16
|
-
const getSndSize =
|
|
15
|
+
const getSendTxt = arr => arr.map(x => x[1]).join('\n');
|
|
16
|
+
const getSndSize = arr => getSendTxt(arr).length;
|
|
17
17
|
const getBufSize = () => maxLength * bufferCycle;
|
|
18
18
|
const nextLen = () => botBuffer?.[0]?.[1].length || (maxLength + 1);
|
|
19
19
|
const stringify = any => ensureString(any, trace);
|
package/lib/utilitas.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { assertPath, readJson, } from './storage.mjs';
|
|
2
|
+
import { basename as _basename, dirname, join, sep } from 'path';
|
|
3
3
|
import { validate as verifyUuid } from 'uuid';
|
|
4
4
|
import color from './color.mjs';
|
|
5
5
|
|
|
@@ -292,15 +292,21 @@ const log = (content, filename, options) => {
|
|
|
292
292
|
|
|
293
293
|
const which = async (any) => {
|
|
294
294
|
if (!Object.isObject(any)) {
|
|
295
|
-
any = any ||
|
|
295
|
+
any = any || import.meta.url;
|
|
296
296
|
any = any.startsWith('file://') ? fileURLToPath(any) : any;
|
|
297
297
|
if (!any?.endsWith?.('.json')) {
|
|
298
|
-
any =
|
|
299
|
-
|
|
298
|
+
any = ['/', ...any.split(sep).slice(1)];
|
|
299
|
+
const arrPath = [];
|
|
300
|
+
for (let sub of any) {
|
|
301
|
+
arrPath.push(sub);
|
|
302
|
+
const curPath = join(...arrPath, 'package.json');
|
|
303
|
+
try { await assertPath(curPath, 'F', 'R'); any = curPath; break; }
|
|
304
|
+
catch (e) { }
|
|
305
|
+
}
|
|
300
306
|
}
|
|
301
307
|
any = await readJson(any);
|
|
302
308
|
}
|
|
303
|
-
any.name = any.name ||
|
|
309
|
+
any.name = any.name || '';
|
|
304
310
|
any.versionNormalized = parseVersion(any.version = any.version || '');
|
|
305
311
|
any.title = `${any.name}${any.version ? (' v' + any.version) : ''}`;
|
|
306
312
|
any.userAgent = `${any.name}${any.version ? `/${any.version}` : ''}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "utilitas",
|
|
3
3
|
"description": "Just another common utility for JavaScript.",
|
|
4
|
-
"version": "1990.1.
|
|
4
|
+
"version": "1990.1.31",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/utilitas",
|
|
7
7
|
"main": "index.mjs",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gitsync": "( git commit -am \"Released @ `date`\" || true ) && git pull && git push",
|
|
18
18
|
"pack": "./node_modules/.bin/webpack-cli --config webpack.config.mjs",
|
|
19
19
|
"build": "npm run updep && ( git commit -am 'update dependencies' || true ) && npm version patch && node build.mjs && npm run pack",
|
|
20
|
-
"
|
|
20
|
+
"xprepublishOnly": "npm run build && npm run gitsync",
|
|
21
21
|
"beta": "npm publish --tag beta"
|
|
22
22
|
},
|
|
23
23
|
"author": "Leask Wong <i@leaskh.com>",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"url": "https://github.com/Leask/utilitas.git"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@sentry/node": "^6.19.
|
|
30
|
+
"@sentry/node": "^6.19.7",
|
|
31
31
|
"base64url": "^3.0.1",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
33
33
|
"fast-geoip": "^1.1.68",
|