halbot 1995.1.22 → 1995.1.24

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "halbot",
3
3
  "description": "Just another AI powered Telegram bot, which is simple design, easy to use, extendable and fun.",
4
- "version": "1995.1.22",
4
+ "version": "1995.1.24",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/halbot",
7
7
  "type": "module",
@@ -46,9 +46,9 @@
46
46
  "pg": "^8.16.3",
47
47
  "pgvector": "^0.2.1",
48
48
  "telegraf": "^4.16.3",
49
- "tellegram": "^1.1.2",
49
+ "tellegram": "^1.1.3",
50
50
  "tesseract.js": "^7.0.0",
51
- "utilitas": "^2001.1.94",
51
+ "utilitas": "^2001.1.98",
52
52
  "youtube-transcript": "^1.2.1"
53
53
  }
54
54
  }
@@ -174,6 +174,10 @@ const ctxExt = ctx => {
174
174
  ctx.image = async (s, o) => await replyWith(ctx, 'replyWithPhoto', s, o);
175
175
  ctx.video = async (s, o) => await replyWith(ctx, 'replyWithVideo', s, o);
176
176
  ctx.media = async (s, o) => await replyWith(ctx, 'replyWithMediaGroup', s, o);
177
+ ctx.sessionSet = async () => {
178
+ ctx._.saved || await sessionSet(ctx._.chatId, ctx._.session);
179
+ ctx._.saved = true;
180
+ };
177
181
  };
178
182
 
179
183
  const action = async (ctx, next) => {
@@ -251,7 +255,7 @@ const action = async (ctx, next) => {
251
255
  || (ctx._.message.new_chat_member || ctx._.message.left_chat_member))
252
256
  && await next();
253
257
  // persistence
254
- await sessionSet(ctx._.chatId, ctx._.session);
258
+ await ctx.sessionSet();
255
259
  // fallback response and log
256
260
  if (ctx._.done.length) { return; }
257
261
  const errStr = ctx._.cmd?.cmd
@@ -26,8 +26,8 @@ const action = async (ctx, next) => {
26
26
  }
27
27
  };
28
28
  Object.keys(ctx._.config).map(x => _config[x] += ` ${hal.CHECK}`);
29
- ctx._.result = hal.map(_config);
30
29
  ctx.hello();
30
+ await ctx.sessionSet(); // save config before break
31
31
  break;
32
32
  case 'toggle':
33
33
  parsed = {};
@@ -43,12 +43,14 @@ const action = async (ctx, next) => {
43
43
  };
44
44
  assert(utilitas.countKeys(ctx._.config), 'No option matched.');
45
45
  Object.keys(ctx._.config).map(x => _config[x] += ` ${hal.CHECK}`);
46
+ await ctx.sessionSet(); // save config before return
46
47
  return await ctx.sendConfig(_config);
47
48
  } catch (err) {
48
49
  return await ctx.err(err.message || err);
49
50
  }
50
51
  case 'reset':
51
52
  ctx._.session.config = ctx._.config = {};
53
+ await ctx.sessionSet(); // save config before return
52
54
  return await ctx.complete({ keyboards: ctx.getKeyboard() });
53
55
  }
54
56
  await next();
@@ -1,7 +1,6 @@
1
1
  import { bot, hal, media, storage, utilitas, vision, web } from '../index.mjs';
2
2
 
3
3
  const collectableFiles = ['document', 'sticker', 'video_note', 'video'];
4
- const sendInit = async (ctx, txt) => ctx._.done.length || await ctx.ok(txt);
5
4
 
6
5
  const [API_ROOT, BUFFER_ENCODE, EMOJI_SPEECH, EMOJI_LOOK, ATTACHMENT, PROMPT]
7
6
  = [
@@ -16,6 +15,10 @@ const collectableObjects = [
16
15
 
17
16
  const metaPrompt = "The following are meta information changes or attachment details for the current chat. Please respond appropriately. For example, if it's a poll, make a selection based on your understanding. If there are changes in group members, greet or bid farewell to the respective individuals. If it's a geographical location description, provide a suitable answer based on the context. You may also receive other types of information, for which a reasonable, human-like response is expected.";
18
17
 
18
+ // Processing will bypass the keyboard update while keeping the message editable.
19
+ const sendInit = async (ctx, txt) => ctx._.done.length
20
+ || await ctx.ok(txt, { processing: true });
21
+
19
22
  const getFileUrl = async (ctx, file_id) => {
20
23
  assert(file_id, 'File ID is required.', 400);
21
24
  const file = await ctx.telegram.getFile(file_id);
@@ -5,29 +5,35 @@ const log = (c, o) => utilitas.log(c, _name, { time: 1, ...o || {} });
5
5
 
6
6
  const action = async (ctx, next) => {
7
7
  if (!ctx._.text && !ctx._.collected.length) { return await next(); }
8
- let [resp, extra, delay, lock, sResp, lastMsg, lastSent] =
9
- [null, { buttons: [] }, 1000 * 3, false, null, null, 0];
8
+ let [resp, extra, lastLen, status] = [null, { buttons: [] }, 0, 0];
10
9
  const ok = async options => {
11
- if (options?.processing && (
12
- Date.now() - lastSent < ctx._.limit || lastMsg === resp.text || lock
13
- )) { return; }
14
- [lastSent, lastMsg, lock] = [Date.now() + delay, resp.text, true];
10
+ const newLen = ~~resp?.text?.length;
11
+ if (options?.processing && lastLen === newLen) { return; }
12
+ lastLen = newLen;
15
13
  if (!options?.processing) {
16
14
  (resp.annotations || []).map((x, i) => extra.buttons.push({
17
15
  label: `${i + 1}. ${x.title}`, url: x.url,
18
16
  }));
19
17
  }
20
- sResp = await ctx.ok(resp.text, {
18
+ return await ctx.ok(resp.text, {
21
19
  ...ctx._.keyboards ? { keyboards: ctx._.keyboards } : {},
22
20
  ...extra, ...options || {},
23
21
  });
24
- [lastSent, lock] = [Date.now(), false];
25
- return sResp;
26
22
  };
23
+ (async () => {
24
+ while (!status) {
25
+ // console.log('Processing...');
26
+ await ok({ processing: true });
27
+ await ctx.timeout(1000 * ctx._.limit);
28
+ }
29
+ status++;
30
+ })();
27
31
  resp = await alan.talk(ctx._.text, {
28
32
  ...ctx._, sessionId: ctx._.chatId, // THIS LINE IS IMPORTANT
29
- stream: async rsp => { resp = rsp; ok({ processing: true }); }, // Never await, it will block the stream.
33
+ stream: rsp => resp = rsp, // Never await, it will block the stream.
30
34
  });
35
+ status++;
36
+ // console.log('Done');
31
37
  for (let image of resp?.images || []) {
32
38
  await ctx.timeout();
33
39
  await ctx.image(image.data, { caption: image.caption });
@@ -41,7 +47,11 @@ const action = async (ctx, next) => {
41
47
  await ctx.audio(audio.data, { caption: audio.caption });
42
48
  }
43
49
  // print(resp);
44
- await ctx.timeout(1000 * ctx._.done.length);
50
+ while (status < 2) {
51
+ // console.log('Waiting...');
52
+ await ctx.timeout();
53
+ }
54
+ // console.log('Finished');
45
55
  await (resp.text.trim() ? ok({ processing: false })
46
56
  : ctx.deleteMessage(ctx._.done[0].message_id));
47
57
  ctx._.request = resp.request;