utilitas 1995.3.11 → 1995.3.13

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/lib/bot.mjs CHANGED
@@ -230,14 +230,18 @@ const newCommand = (command, description) => ({
230
230
  const reply = async (ctx, md, text, extra) => {
231
231
  try {
232
232
  if (md) {
233
- return await ctx.replyWithMarkdown(text, extra);
233
+ return await (extra?.reply_to_message_id
234
+ ? ctx.replyWithMarkdown(text, { ...extra, parse_mode: 'Markdown' })
235
+ : ctx.sendMessage(text, { ...extra, parse_mode: 'Markdown' }));
234
236
  }
235
237
  } catch (err) {
236
238
  assert(isMarkdownError(err), err, 500);
237
239
  await ctx.timeout();
238
240
  }
239
241
  return await ignoreErrFunc(
240
- async () => await ctx.reply(text, extra), logOptions
242
+ async () => await (extra?.reply_to_message_id
243
+ ? ctx.reply(text, extra) : ctx.sendMessage(text, extra)
244
+ ), logOptions
241
245
  );
242
246
  };
243
247
 
@@ -262,7 +266,7 @@ const editMessageText = async (ctx, md, lastMsgId, text, extra) => {
262
266
  const memorize = async (ctx) => {
263
267
  if (ctx._skipMemorize) { return; }
264
268
  const received = ctx.update;
265
- const received_text = ctx.text;
269
+ const received_text = ctx.txt;
266
270
  const id = received.update_id;
267
271
  const response = lastItem(ctx.done.filter(x => x.text)) || {};
268
272
  const response_text = response?.text || '';
@@ -309,7 +313,7 @@ const subconscious = [{
309
313
  };
310
314
  ctx.collect = (content, type) => type ? ctx.collected.push(
311
315
  { type, content }
312
- ) : (ctx.text = content);
316
+ ) : (ctx.txt = content);
313
317
  ctx.skipMemorize = () => ctx._skipMemorize = true;
314
318
  ctx.ok = async (message, options) => {
315
319
  let pages = paging(message);
@@ -384,30 +388,33 @@ const subconscious = [{
384
388
  }, {
385
389
  run: true, priority: -8950, name: 'subconscious', func: async (ctx, next) => {
386
390
  for (let t of KNOWN_UPDATE_TYPES) {
387
- if (ctx.update[t]) { ctx.msg = ctx.update[ctx.type = t]; break; }
391
+ if (ctx.update[t]) {
392
+ ctx.m = ctx.update[ctx.type = t];
393
+ break;
394
+ }
388
395
  }
389
- if (ctx.type === 'callback_query') { ctx.msg = ctx.msg.message; }
396
+ if (ctx.type === 'callback_query') { ctx.m = ctx.msg.message; }
390
397
  else if (ctx.type === 'my_chat_member') {
391
398
  log(
392
399
  'Group member status changed: '
393
- + ctx.msg.new_chat_member.user.id + ' => '
394
- + ctx.msg.new_chat_member.status
400
+ + ctx.m.new_chat_member.user.id + ' => '
401
+ + ctx.m.new_chat_member.status
395
402
  );
396
- if (ctx.msg.new_chat_member.user.id !== ctx.botInfo.id
397
- || ctx.msg.new_chat_member.status === 'left') { return }
403
+ if (ctx.m.new_chat_member.user.id !== ctx.botInfo.id
404
+ || ctx.m.new_chat_member.status === 'left') { return }
398
405
  else { ctx.hello(); }
399
406
  } else if (!ctx.type) { return log(`Unsupported update type.`); }
400
407
  ctx._ = bot._;
401
- ctx.chatId = ctx.msg.chat.id;
402
- ctx.chatType = ctx.msg.chat.type;
403
- ctx.messageId = ctx.msg.message_id;
404
- ctx.msg.text && ctx.collect(ctx.msg.text);
408
+ ctx.chatId = ctx.m.chat.id;
409
+ ctx.chatType = ctx.m.chat.type;
410
+ ctx.messageId = ctx.m.message_id;
411
+ ctx.m.text && ctx.collect(ctx.m.text);
405
412
  ctx.session = await sessionGet(ctx.chatId);
406
413
  ctx.limit = ctx.chatType === PRIVATE ? PRIVATE_LIMIT : GROUP_LIMIT;
407
414
  ctx.entities = [
408
- ...(ctx.msg.entities || []).map(e => ({ ...e, text: ctx.msg.text })),
409
- ...(ctx.msg.caption_entities || []).map(e => ({ ...e, text: ctx.msg.caption })),
410
- ...(ctx.msg.reply_to_message?.entities || []).map(e => ({ ...e, text: ctx.msg.reply_to_message.text })),
415
+ ...(ctx.m.entities || []).map(e => ({ ...e, text: ctx.m.text })),
416
+ ...(ctx.m.caption_entities || []).map(e => ({ ...e, text: ctx.m.caption })),
417
+ ...(ctx.m.reply_to_message?.entities || []).map(e => ({ ...e, text: ctx.m.reply_to_message.text })),
411
418
  ].map(e => ({
412
419
  ...e, matched: e.text.substring(e.offset, e.offset + e.length),
413
420
  ...e.type === 'text_link' ? { type: 'url', matched: e.url } : {},
@@ -419,16 +426,39 @@ const subconscious = [{
419
426
  case bot_command: target = e.matched.split('@')[1]; break;
420
427
  }
421
428
  return target === ctx.botInfo.username;
422
- }) || ctx.msg.reply_to_message?.from?.username === ctx.botInfo.username)
429
+ }) || ctx.m.reply_to_message?.from?.username === ctx.botInfo.username)
423
430
  && (ctx.chatType = MENTION);
424
- if ((ctx.text || ctx.msg.voice || ctx.msg.poll || ctx.msg.data
425
- || ctx.msg.document || ctx.msg.photo) && ctx.messageId) {
431
+ if ((ctx.txt || ctx.m.voice || ctx.m.poll || ctx.m.data
432
+ || ctx.m.document || ctx.m.photo) && ctx.messageId) {
426
433
  await next();
427
434
  }
428
435
  await sessionSet(ctx.chatId);
429
436
  },
430
437
  }, {
431
- run: true, priority: -8940, name: 'echo', hidden: true, func: async (ctx, next) => {
438
+ run: true, priority: -8940, name: 'commands', func: async (ctx, next) => {
439
+ for (let e of ctx.entities) {
440
+ if (e.type !== bot_command) { continue; }
441
+ if (!COMMAND_REGEXP.test(e.matched)) { continue; }
442
+ const cmd = trim(e.matched.replace(
443
+ COMMAND_REGEXP, '$1'
444
+ ), { case: 'LOW' });
445
+ ctx.cmd = { cmd, args: e.text.substring(e.offset + e.length + 1) };
446
+ break;
447
+ }
448
+ for (let str of [ctx.txt || '', ctx.m.caption || ''].map(trim)) {
449
+ if (!ctx.cmd && COMMAND_REGEXP.test(str)) {
450
+ ctx.cmd = { // this will faild if command includes urls
451
+ cmd: str.replace(COMMAND_REGEXP, '$1').toLowerCase(),
452
+ args: str.replace(COMMAND_REGEXP, '$4'),
453
+ };
454
+ break;
455
+ }
456
+ }
457
+ ctx.cmd && log(`Command: ${JSON.stringify(ctx.cmd)}`);
458
+ await next();
459
+ },
460
+ }, {
461
+ run: true, priority: -8930, name: 'echo', hidden: true, func: async (ctx, next) => {
432
462
  let resp, md = false;
433
463
  switch (ctx.cmd.cmd) {
434
464
  case 'echo':
@@ -488,10 +518,10 @@ const subconscious = [{
488
518
  lorem: '[Lorem ipsum](https://en.wikipedia.org/wiki/Lorem_ipsum)',
489
519
  },
490
520
  }, {
491
- run: true, priority: -8930, name: 'authenticate', func: async (ctx, next) => {
521
+ run: true, priority: -8920, name: 'authenticate', func: async (ctx, next) => {
492
522
  if (!await ctx.shouldReply()) { return; } // if chatType is not in whitelist, exit.
493
523
  if (!ctx._.private) { return await next(); } // if not private, go next.
494
- if (ctx._.magicWord && insensitiveHas(ctx._.magicWord, ctx.text)) { // auth by magicWord
524
+ if (ctx._.magicWord && insensitiveHas(ctx._.magicWord, ctx.txt)) { // auth by magicWord
495
525
  ctx._.private.add(String(ctx.chatId));
496
526
  await ctx.ok('😸 You are now allowed to talk to me.');
497
527
  ctx.hello();
@@ -515,11 +545,11 @@ const subconscious = [{
515
545
  await ctx.ok('😿 Sorry, I am not allowed to talk to strangers.');
516
546
  },
517
547
  }, {
518
- run: true, priority: -8920, name: 'speech-to-text', func: async (ctx, next) => {
519
- if (ctx._.speech?.stt && ctx.msg.voice?.mime_type === 'audio/ogg') {
548
+ run: true, priority: -8910, name: 'speech-to-text', func: async (ctx, next) => {
549
+ if (ctx._.speech?.stt && ctx.m.voice?.mime_type === 'audio/ogg') {
520
550
  await ctx.ok(EMOJI_SPEECH);
521
551
  try {
522
- const file = await getFile(ctx.msg.voice.file_id, BUFFER_ENCODE);
552
+ const file = await getFile(ctx.m.voice.file_id, BUFFER_ENCODE);
523
553
  const resp = await ignoreErrFunc(
524
554
  async () => await ctx._.speech?.stt(file), logOptions
525
555
  ) || ' ';
@@ -530,7 +560,7 @@ const subconscious = [{
530
560
  await next();
531
561
  },
532
562
  }, {
533
- run: true, priority: -8910, name: 'callback', func: async (ctx, next) => {
563
+ run: true, priority: -8900, name: 'callback', func: async (ctx, next) => {
534
564
  if (ctx.type === 'callback_query') {
535
565
  const data = parseJson(ctx.update[ctx.type].data);
536
566
  const cb = ctx.session.callback.filter(x => x.id == data?.callback)[0];
@@ -539,29 +569,29 @@ const subconscious = [{
539
569
  ctx.collect(cb.text);
540
570
  } else {
541
571
  return await ctx.er(
542
- `Command is invalid or expired: ${ctx.msg.data}`
572
+ `Command is invalid or expired: ${ctx.m.data}`
543
573
  );
544
574
  }
545
575
  }
546
576
  await next();
547
577
  },
548
578
  }, {
549
- run: true, priority: -8900, name: 'poll', func: async (ctx, next) => {
550
- ctx.msg.poll && ctx.collect(lines([
551
- 'Question:', ctx.msg.poll.question, '',
552
- 'Options:', oList(ctx.msg.poll.options.map(x => x.text)),
579
+ run: true, priority: -8890, name: 'poll', func: async (ctx, next) => {
580
+ ctx.m.poll && ctx.collect(lines([
581
+ 'Question:', ctx.m.poll.question, '',
582
+ 'Options:', oList(ctx.m.poll.options.map(x => x.text)),
553
583
  ]));
554
584
  await next();
555
585
  },
556
586
  }, {
557
- run: true, priority: -8890, name: 'contaxt', func: async (ctx, next) => {
558
- ctx.msg.reply_to_message?.text && ctx.collect(
559
- ctx.msg.reply_to_message.text, 'CONTAXT'
587
+ run: true, priority: -8880, name: 'contaxt', func: async (ctx, next) => {
588
+ ctx.m.reply_to_message?.text && ctx.collect(
589
+ ctx.m.reply_to_message.text, 'CONTAXT'
560
590
  );
561
591
  await next();
562
592
  },
563
593
  }, {
564
- run: true, priority: -8880, name: 'web', func: async (ctx, next) => {
594
+ run: true, priority: -8870, name: 'web', func: async (ctx, next) => {
565
595
  if (ctx.entities.some(e => e.type === 'url')) {
566
596
  await ctx.ok(EMOJI_LOOK);
567
597
  for (let e of ctx.entities) {
@@ -575,37 +605,37 @@ const subconscious = [{
575
605
  await next();
576
606
  },
577
607
  }, {
578
- run: true, priority: -8870, name: 'vision', func: async (ctx, next) => {
608
+ run: true, priority: -8860, name: 'vision', func: async (ctx, next) => {
579
609
  let fileId, type, file_name, mime_type, ocrFunc, asPrompt = false;
580
- if ('application/pdf' === ctx.msg.document?.mime_type) {
610
+ if ('application/pdf' === ctx.m.document?.mime_type) {
581
611
  ocrFunc = ctx._.vision?.read;
582
- fileId = ctx.msg.document.file_id;
583
- file_name = ctx.msg.document.file_name;
584
- mime_type = ctx.msg.document.mime_type;
612
+ fileId = ctx.m.document.file_id;
613
+ file_name = ctx.m.document.file_name;
614
+ mime_type = ctx.m.document.mime_type;
585
615
  type = 'DOCUMENT';
586
- } else if (/^image\/.*$/ig.test(ctx.msg.document?.mime_type)) {
587
- asPrompt = bot._.supportedMimeTypes.has(ctx.msg.document.mime_type);
616
+ } else if (/^image\/.*$/ig.test(ctx.m.document?.mime_type)) {
617
+ asPrompt = bot._.supportedMimeTypes.has(ctx.m.document.mime_type);
588
618
  ocrFunc = ctx._.vision?.see;
589
- fileId = ctx.msg.document.file_id;
590
- file_name = ctx.msg.document.file_name;
591
- mime_type = ctx.msg.document.mime_type;
619
+ fileId = ctx.m.document.file_id;
620
+ file_name = ctx.m.document.file_name;
621
+ mime_type = ctx.m.document.mime_type;
592
622
  type = 'IMAGE';
593
- } else if (/^.*\.(docx|xlsx|pptx)$/.test(ctx.msg.document?.file_name)) {
623
+ } else if (/^.*\.(docx|xlsx|pptx)$/.test(ctx.m.document?.file_name)) {
594
624
  ocrFunc = officeParser;
595
- fileId = ctx.msg.document.file_id;
596
- file_name = ctx.msg.document.file_name;
597
- mime_type = ctx.msg.document.mime_type;
625
+ fileId = ctx.m.document.file_id;
626
+ file_name = ctx.m.document.file_name;
627
+ mime_type = ctx.m.document.mime_type;
598
628
  type = 'DOCUMENT';
599
- } else if (ctx.msg.document) {
629
+ } else if (ctx.m.document) {
600
630
  ocrFunc = async file => (await isTextFile(file)) && file.toString();
601
- fileId = ctx.msg.document.file_id;
602
- file_name = ctx.msg.document.file_name;
603
- mime_type = ctx.msg.document.mime_type;
631
+ fileId = ctx.m.document.file_id;
632
+ file_name = ctx.m.document.file_name;
633
+ mime_type = ctx.m.document.mime_type;
604
634
  type = 'FILE';
605
- } else if (ctx.msg.photo) {
635
+ } else if (ctx.m.photo) {
606
636
  asPrompt = true;
607
637
  ocrFunc = ctx._.vision?.see;
608
- fileId = ctx.msg.photo[ctx.msg.photo.length - 1]?.file_id;
638
+ fileId = ctx.m.photo[ctx.m.photo.length - 1]?.file_id;
609
639
  mime_type = 'image';
610
640
  type = 'PHOTO';
611
641
  }
@@ -615,7 +645,7 @@ const subconscious = [{
615
645
  const image_url = await getFileUrl(fileId);
616
646
  const file = (await get(image_url, BUFFER_ENCODE)).content;
617
647
  if (asPrompt) {
618
- ctx.collect(ctx.msg.caption || '');
648
+ ctx.collect(ctx.m.caption || '');
619
649
  ctx.collect({
620
650
  mime_type: mime_type === 'image' ? 'image/jpeg' : mime_type,
621
651
  image_url, data: base64Encode(file, true),
@@ -628,7 +658,7 @@ const subconscious = [{
628
658
  ), logOptions)
629
659
  ).filter(x => x).join('\n'));
630
660
  if (content) {
631
- ctx.collect(ctx.msg.caption || '');
661
+ ctx.collect(ctx.m.caption || '');
632
662
  ctx.collect(lines([
633
663
  '---', ...file_name ? [`file_name: ${file_name}`] : [],
634
664
  `mime_type: ${mime_type}`, `type: ${type}`, '---',
@@ -640,29 +670,6 @@ const subconscious = [{
640
670
  }
641
671
  await next();
642
672
  },
643
- }, {
644
- run: true, priority: -8860, name: 'commands', func: async (ctx, next) => {
645
- for (let e of ctx.entities) {
646
- if (e.type !== bot_command) { continue; }
647
- if (!COMMAND_REGEXP.test(e.matched)) { continue; }
648
- const cmd = trim(e.matched.replace(
649
- COMMAND_REGEXP, '$1'
650
- ), { case: 'LOW' });
651
- ctx.cmd = { cmd, args: e.text.substring(e.offset + e.length + 1) };
652
- break;
653
- }
654
- for (let str of [ctx.text || '', ctx.msg.caption || ''].map(trim)) {
655
- if (!ctx.cmd && COMMAND_REGEXP.test(str)) {
656
- ctx.cmd = { // this will faild if command includes urls
657
- cmd: str.replace(COMMAND_REGEXP, '$1').toLowerCase(),
658
- args: str.replace(COMMAND_REGEXP, '$4'),
659
- };
660
- break;
661
- }
662
- }
663
- ctx.cmd && log(`Command: ${JSON.stringify(ctx.cmd)}`);
664
- await next();
665
- },
666
673
  }, {
667
674
  run: true, priority: -8850, name: 'help', func: async (ctx, next) => {
668
675
  const help = ctx._.info ? [ctx._.info] : [];
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": "1995.3.11",
4
+ "version": "1995.3.13",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
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": "1995.3.11",
4
+ "version": "1995.3.13",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",