utilitas 1993.3.21 → 1993.3.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/README.md +9 -0
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/index.mjs +2 -1
- package/lib/bot.mjs +35 -8
- package/lib/encryption.mjs +12 -0
- package/lib/manifest.mjs +2 -1
- package/lib/speech.mjs +1 -10
- package/lib/vision.mjs +42 -0
- package/package.json +2 -1
package/index.mjs
CHANGED
|
@@ -26,6 +26,7 @@ import * as storage from './lib/storage.mjs';
|
|
|
26
26
|
import * as tape from './lib/tape.mjs';
|
|
27
27
|
import * as uoid from './lib/uoid.mjs';
|
|
28
28
|
import * as utilitas from './lib/utilitas.mjs';
|
|
29
|
+
import * as vision from './lib/vision.mjs';
|
|
29
30
|
import * as web from './lib/web.mjs';
|
|
30
31
|
import color from './lib/color.mjs';
|
|
31
32
|
import manifest from './lib/manifest.mjs';
|
|
@@ -38,7 +39,7 @@ export {
|
|
|
38
39
|
// features
|
|
39
40
|
bot, boxes, cache, callosum, color, dbio, email, encryption, event, hal,
|
|
40
41
|
manifest, memory, network, sentinel, shekel, shell, shot, sms, speech, ssl,
|
|
41
|
-
storage, tape, uoid, utilitas, web
|
|
42
|
+
storage, tape, uoid, utilitas, vision, web
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
if (utilitas.inBrowser() && !globalThis.utilitas) {
|
package/lib/bot.mjs
CHANGED
|
@@ -42,6 +42,8 @@ const [ // https://limits.tginfo.me/en
|
|
|
42
42
|
256, 'bot_command', '🗣️', '👀', '🤖',
|
|
43
43
|
];
|
|
44
44
|
|
|
45
|
+
const [BUFFER_ENCODE] = [{ encode: BUFFER }];
|
|
46
|
+
|
|
45
47
|
const KNOWN_UPDATE_TYPES = [
|
|
46
48
|
'message', 'callback_query', 'channel_post', 'edited_message',
|
|
47
49
|
'my_chat_member'
|
|
@@ -230,8 +232,10 @@ const subconscious = [{
|
|
|
230
232
|
}
|
|
231
233
|
return target === ctx.botInfo.username;
|
|
232
234
|
})) { ctx.chatType = MENTION; }
|
|
233
|
-
if ((ctx.text || ctx.msg.voice || ctx.msg.poll || ctx.msg.data
|
|
234
|
-
&& ctx.messageId) {
|
|
235
|
+
if ((ctx.text || ctx.msg.voice || ctx.msg.poll || ctx.msg.data
|
|
236
|
+
|| ctx.msg.document || ctx.msg.photo) && ctx.messageId) {
|
|
237
|
+
await next();
|
|
238
|
+
}
|
|
235
239
|
await sessionSet(ctx.chatId);
|
|
236
240
|
},
|
|
237
241
|
}, {
|
|
@@ -281,9 +285,7 @@ const subconscious = [{
|
|
|
281
285
|
if (ctx._.speech?.stt && ctx.msg.voice?.mime_type === 'audio/ogg') {
|
|
282
286
|
await ctx.ok(EMOJI_SPEECH);
|
|
283
287
|
try {
|
|
284
|
-
const file = await getFile(
|
|
285
|
-
ctx.msg.voice.file_id, { encode: BUFFER }
|
|
286
|
-
);
|
|
288
|
+
const file = await getFile(ctx.msg.voice.file_id, BUFFER_ENCODE);
|
|
287
289
|
const resp = await ignoreErrFunc(
|
|
288
290
|
async () => await ctx._.speech?.stt(
|
|
289
291
|
file, { config: sampleRateHertz }
|
|
@@ -334,7 +336,31 @@ const subconscious = [{
|
|
|
334
336
|
await next();
|
|
335
337
|
},
|
|
336
338
|
}, {
|
|
337
|
-
run: true, priority: -8880, name: '
|
|
339
|
+
run: true, priority: -8880, name: 'ocr', func: async (ctx, next) => {
|
|
340
|
+
if (!ctx._.vision?.ocrImage) { return await next(); }
|
|
341
|
+
let fileId;
|
|
342
|
+
if (/^image\/.*$/ig.test(ctx.msg?.document?.mime_type)) {
|
|
343
|
+
fileId = ctx.msg.document.file_id;
|
|
344
|
+
} else if (ctx.msg?.photo) {
|
|
345
|
+
fileId = ctx.msg.photo[ctx.msg.photo.length - 1]?.file_id;
|
|
346
|
+
}
|
|
347
|
+
if (fileId) {
|
|
348
|
+
await ctx.ok(EMOJI_LOOK);
|
|
349
|
+
try {
|
|
350
|
+
const file = await getFile(fileId, BUFFER_ENCODE);
|
|
351
|
+
const content = await ignoreErrFunc(
|
|
352
|
+
async () => await ctx._.vision?.ocrImage(
|
|
353
|
+
file, BUFFER_ENCODE
|
|
354
|
+
), { log: true }
|
|
355
|
+
);
|
|
356
|
+
console.log(content);
|
|
357
|
+
ctx.collect(content, 'OCR');
|
|
358
|
+
} catch (err) { return await ctx.er(err); }
|
|
359
|
+
}
|
|
360
|
+
await next();
|
|
361
|
+
},
|
|
362
|
+
}, {
|
|
363
|
+
run: true, priority: -8870, name: 'commands', func: async (ctx, next) => {
|
|
338
364
|
for (let ent of ctx.msg?.entities || []) {
|
|
339
365
|
if (ent.type !== bot_command) { continue; }
|
|
340
366
|
const rawCmd = ctx.text.substr(ent.offset, ent.length);
|
|
@@ -349,7 +375,7 @@ const subconscious = [{
|
|
|
349
375
|
await next();
|
|
350
376
|
},
|
|
351
377
|
}, {
|
|
352
|
-
run: true, priority: -
|
|
378
|
+
run: true, priority: -8860, name: 'help', func: async (ctx, next) => {
|
|
353
379
|
const help = ctx._.info ? [ctx._.info] : [];
|
|
354
380
|
for (let i in ctx._.skills) {
|
|
355
381
|
const _help = [];
|
|
@@ -387,7 +413,7 @@ const subconscious = [{
|
|
|
387
413
|
echo: 'Show debug message.',
|
|
388
414
|
},
|
|
389
415
|
}, {
|
|
390
|
-
run: true, priority: -
|
|
416
|
+
run: true, priority: -8850, name: 'configuration', func: async (ctx, next) => {
|
|
391
417
|
switch (ctx.cmd.cmd) {
|
|
392
418
|
case 'set':
|
|
393
419
|
try {
|
|
@@ -506,6 +532,7 @@ const init = async (options) => {
|
|
|
506
532
|
private: options?.private && new Set(options.private),
|
|
507
533
|
session: { get: options?.session?.get, set: options?.session?.set },
|
|
508
534
|
speech: options?.speech,
|
|
535
|
+
vision: options?.vision,
|
|
509
536
|
skills: { ...options?.skills || {} },
|
|
510
537
|
};
|
|
511
538
|
(!options?.session?.get || !options?.session?.set)
|
package/lib/encryption.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes as random } from 'crypto';
|
|
2
2
|
import { createReadStream } from 'fs';
|
|
3
3
|
import { ensureString } from './utilitas.mjs';
|
|
4
|
+
import { need } from './utilitas.mjs';
|
|
4
5
|
import { networkInterfaces } from 'os';
|
|
5
6
|
|
|
6
7
|
const defaultAlgorithm = 'sha256';
|
|
@@ -42,9 +43,20 @@ const hexToBigInt = (hex) => {
|
|
|
42
43
|
return BigInt(hex, 16).toString(10);
|
|
43
44
|
};
|
|
44
45
|
|
|
46
|
+
const getApiKeyCredentials = async (options) => {
|
|
47
|
+
// Included in @google-cloud/vision, @google-cloud/speech and @google-cloud/text-to-speech
|
|
48
|
+
const { GoogleAuth, grpc } = await need('google-gax');
|
|
49
|
+
const authClient = new GoogleAuth().fromAPIKey(options?.apiKey);
|
|
50
|
+
return grpc.credentials.combineChannelCredentials(
|
|
51
|
+
grpc.credentials.createSsl(),
|
|
52
|
+
grpc.credentials.createFromGoogleCredential(authClient)
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
45
56
|
export {
|
|
46
57
|
defaultAlgorithm,
|
|
47
58
|
digestObject,
|
|
59
|
+
getApiKeyCredentials,
|
|
48
60
|
getSortedQueryString,
|
|
49
61
|
hash as sha256,
|
|
50
62
|
hash,
|
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": "1993.3.
|
|
4
|
+
"version": "1993.3.22",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/utilitas",
|
|
7
7
|
"main": "index.mjs",
|
|
@@ -23,6 +23,7 @@ const manifest = {
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@google-cloud/speech": "^5.4.0",
|
|
25
25
|
"@google-cloud/text-to-speech": "^4.2.1",
|
|
26
|
+
"@google-cloud/vision": "^3.1.2",
|
|
26
27
|
"@mozilla/readability": "^0.4.4",
|
|
27
28
|
"@sentry/node": "^7.47.0",
|
|
28
29
|
"@waylaidwanderer/chatgpt-api": "^1.34.0",
|
package/lib/speech.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
base64Encode, log as _log, countKeys, ensureString, need, throwError
|
|
3
3
|
} from './utilitas.mjs';
|
|
4
4
|
|
|
5
|
+
import { getApiKeyCredentials } from './encryption.mjs';
|
|
5
6
|
import { readFile, writeFile, writeTempFile } from './storage.mjs';
|
|
6
7
|
|
|
7
8
|
const _NEED = ['@google-cloud/speech', '@google-cloud/text-to-speech'];
|
|
@@ -9,16 +10,6 @@ const log = (content) => _log(content, import.meta.url);
|
|
|
9
10
|
const [BUFFER, BASE64, FILE, clients, languageCode, audioEncoding, suffix, encoding]
|
|
10
11
|
= ['BUFFER', 'BASE64', 'FILE', {}, 'en-US', 'OGG_OPUS', 'OGG', { encoding: 'binary' }];
|
|
11
12
|
|
|
12
|
-
const getApiKeyCredentials = async (options) => {
|
|
13
|
-
// Included in @google-cloud/speech or @google-cloud/text-to-speech
|
|
14
|
-
const { GoogleAuth, grpc } = await need('google-gax');
|
|
15
|
-
const authClient = new GoogleAuth().fromAPIKey(options?.apiKey);
|
|
16
|
-
return grpc.credentials.combineChannelCredentials(
|
|
17
|
-
grpc.credentials.createSsl(),
|
|
18
|
-
grpc.credentials.createFromGoogleCredential(authClient)
|
|
19
|
-
);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
13
|
const init = async (options) => {
|
|
23
14
|
if (options) {
|
|
24
15
|
assert(options?.apiKey, 'Google Cloud API Key is required.', 500);
|
package/lib/vision.mjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { base64Decode, ensureString, need, throwError } from './utilitas.mjs';
|
|
2
|
+
import { getApiKeyCredentials } from './encryption.mjs';
|
|
3
|
+
import { writeTempFile } from './storage.mjs';
|
|
4
|
+
|
|
5
|
+
const _NEED = ['@google-cloud/vision'];
|
|
6
|
+
const [BUFFER, BASE64, FILE, encoding]
|
|
7
|
+
= ['BUFFER', 'BASE64', 'FILE', { encoding: 'binary' }];
|
|
8
|
+
|
|
9
|
+
let client;
|
|
10
|
+
|
|
11
|
+
const init = async (options) => {
|
|
12
|
+
if (options) {
|
|
13
|
+
assert(options?.apiKey, 'Google Cloud API Key is required.', 500);
|
|
14
|
+
const sslCreds = await getApiKeyCredentials(options);
|
|
15
|
+
const vision = (await need('@google-cloud/vision')).default;
|
|
16
|
+
client = new vision.ImageAnnotatorClient({ sslCreds });
|
|
17
|
+
}
|
|
18
|
+
assert(client, 'Vision API client has not been initialized.', 501);
|
|
19
|
+
return client;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const ocrImage = async (image, options) => {
|
|
23
|
+
assert(client, 'Vision API has not been initialized.', 500);
|
|
24
|
+
assert(image, 'Image data is required.', 400);
|
|
25
|
+
let content;
|
|
26
|
+
switch (ensureString(options?.input, { case: 'UP' })) {
|
|
27
|
+
case BASE64: image = base64Decode(image, true);
|
|
28
|
+
case BUFFER: case '': content = await writeTempFile(image, encoding); break;
|
|
29
|
+
case FILE: content = image; break;
|
|
30
|
+
default: throwError('Invalid input format.', 400);
|
|
31
|
+
}
|
|
32
|
+
const [response] = await client.textDetection(content);
|
|
33
|
+
let detections = response.textAnnotations;
|
|
34
|
+
options?.raw || (detections = detections.map(t => t.description).join(' '));
|
|
35
|
+
return detections;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
_NEED,
|
|
40
|
+
init,
|
|
41
|
+
ocrImage,
|
|
42
|
+
};
|
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": "1993.3.
|
|
4
|
+
"version": "1993.3.22",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/utilitas",
|
|
7
7
|
"main": "index.mjs",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@google-cloud/speech": "^5.4.0",
|
|
36
36
|
"@google-cloud/text-to-speech": "^4.2.1",
|
|
37
|
+
"@google-cloud/vision": "^3.1.2",
|
|
37
38
|
"@mozilla/readability": "^0.4.4",
|
|
38
39
|
"@sentry/node": "^7.47.0",
|
|
39
40
|
"@waylaidwanderer/chatgpt-api": "^1.34.0",
|