@wrongstack/telegram 0.319.1 → 1.0.0
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/dist/inbox.d.ts +25 -1
- package/dist/index.js +40 -4
- package/dist/poller.d.ts +1 -1
- package/package.json +3 -3
package/dist/inbox.d.ts
CHANGED
|
@@ -26,12 +26,36 @@ export declare class TelegramInbox {
|
|
|
26
26
|
private readonly deps;
|
|
27
27
|
readonly buffer: TelegramIncomingMessage[];
|
|
28
28
|
constructor(deps: TelegramInboxDeps);
|
|
29
|
+
/**
|
|
30
|
+
* Replace the inbound identity policy sets. Called by the plugin's
|
|
31
|
+
* hot-reload path (api.onConfigChange) so changes to `inboundMode`,
|
|
32
|
+
* `allowedUsers`, and `allowedChats` — all classified `hot` — take effect
|
|
33
|
+
* on the live gate without a plugin restart. The new sets carry the same
|
|
34
|
+
* semantics as construction (empty set = that dimension unrestricted,
|
|
35
|
+
* non-empty = mandatory constraint, fail closed on missing identity).
|
|
36
|
+
*/
|
|
37
|
+
updateAllowlist(allowedUsers: Set<string>, allowedChats: Set<string>): void;
|
|
29
38
|
/** Return buffered messages, newest first. Optionally filter by chat. */
|
|
30
39
|
getMessages(opts?: {
|
|
31
40
|
chatId?: string | number | undefined;
|
|
32
41
|
limit?: number | undefined;
|
|
33
42
|
}): TelegramIncomingMessage[];
|
|
34
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Drop messages older than or equal to the given message ID from the buffer
|
|
45
|
+
* (optionally scoped to a specific chat).
|
|
46
|
+
*
|
|
47
|
+
* Telegram `message_id` is a PER-CHAT counter: ids are ordered only inside
|
|
48
|
+
* one chat and are never comparable across chats. With an explicit
|
|
49
|
+
* `chatId`, the drop is scoped to that chat. Without one, the drop is
|
|
50
|
+
* scoped to the chat(s) that actually contain a buffered message with this
|
|
51
|
+
* exact id — the anchor names a message in a specific chat, and only that
|
|
52
|
+
* chat's `<= anchor` range is meaningful. Other chats keep their mail, so
|
|
53
|
+
* the documented read→ack_last pattern (read newest-first across all
|
|
54
|
+
* chats, ack the highest id seen) can never destroy mail from a chat the
|
|
55
|
+
* agent never read — including messages truncated away by `limit`. A
|
|
56
|
+
* single-chat deployment is unaffected: the one chat owns the anchor,
|
|
57
|
+
* exactly as before.
|
|
58
|
+
*/
|
|
35
59
|
acknowledge(lastMessageId: number, chatId?: string | number | undefined): number;
|
|
36
60
|
get bufferCount(): number;
|
|
37
61
|
/**
|
package/dist/index.js
CHANGED
|
@@ -419,6 +419,18 @@ var TelegramInbox = class {
|
|
|
419
419
|
constructor(deps) {
|
|
420
420
|
this.deps = deps;
|
|
421
421
|
}
|
|
422
|
+
/**
|
|
423
|
+
* Replace the inbound identity policy sets. Called by the plugin's
|
|
424
|
+
* hot-reload path (api.onConfigChange) so changes to `inboundMode`,
|
|
425
|
+
* `allowedUsers`, and `allowedChats` — all classified `hot` — take effect
|
|
426
|
+
* on the live gate without a plugin restart. The new sets carry the same
|
|
427
|
+
* semantics as construction (empty set = that dimension unrestricted,
|
|
428
|
+
* non-empty = mandatory constraint, fail closed on missing identity).
|
|
429
|
+
*/
|
|
430
|
+
updateAllowlist(allowedUsers, allowedChats) {
|
|
431
|
+
this.deps.allowedUsers = allowedUsers;
|
|
432
|
+
this.deps.allowedChats = allowedChats;
|
|
433
|
+
}
|
|
422
434
|
/** Return buffered messages, newest first. Optionally filter by chat. */
|
|
423
435
|
getMessages(opts) {
|
|
424
436
|
let msgs = [...this.buffer].reverse();
|
|
@@ -429,17 +441,35 @@ var TelegramInbox = class {
|
|
|
429
441
|
const limit = opts?.limit ?? 20;
|
|
430
442
|
return msgs.slice(0, limit);
|
|
431
443
|
}
|
|
432
|
-
/**
|
|
444
|
+
/**
|
|
445
|
+
* Drop messages older than or equal to the given message ID from the buffer
|
|
446
|
+
* (optionally scoped to a specific chat).
|
|
447
|
+
*
|
|
448
|
+
* Telegram `message_id` is a PER-CHAT counter: ids are ordered only inside
|
|
449
|
+
* one chat and are never comparable across chats. With an explicit
|
|
450
|
+
* `chatId`, the drop is scoped to that chat. Without one, the drop is
|
|
451
|
+
* scoped to the chat(s) that actually contain a buffered message with this
|
|
452
|
+
* exact id — the anchor names a message in a specific chat, and only that
|
|
453
|
+
* chat's `<= anchor` range is meaningful. Other chats keep their mail, so
|
|
454
|
+
* the documented read→ack_last pattern (read newest-first across all
|
|
455
|
+
* chats, ack the highest id seen) can never destroy mail from a chat the
|
|
456
|
+
* agent never read — including messages truncated away by `limit`. A
|
|
457
|
+
* single-chat deployment is unaffected: the one chat owns the anchor,
|
|
458
|
+
* exactly as before.
|
|
459
|
+
*/
|
|
433
460
|
acknowledge(lastMessageId, chatId) {
|
|
434
461
|
const before = this.buffer.length;
|
|
435
462
|
const cid = chatId !== void 0 && chatId !== null && String(chatId).trim() !== "" ? String(chatId).trim() : void 0;
|
|
463
|
+
const anchorChats = cid === void 0 ? new Set(
|
|
464
|
+
this.buffer.filter((buffered) => buffered.messageId === lastMessageId).map((buffered) => String(buffered.chatId))
|
|
465
|
+
) : void 0;
|
|
436
466
|
const remaining = [];
|
|
437
467
|
for (const buffered of this.buffer) {
|
|
438
468
|
if (cid !== void 0) {
|
|
439
469
|
if (String(buffered.chatId) === cid && buffered.messageId <= lastMessageId) {
|
|
440
470
|
continue;
|
|
441
471
|
}
|
|
442
|
-
} else if (buffered.messageId <= lastMessageId) {
|
|
472
|
+
} else if (anchorChats?.has(String(buffered.chatId)) && buffered.messageId <= lastMessageId) {
|
|
443
473
|
continue;
|
|
444
474
|
}
|
|
445
475
|
remaining.push(buffered);
|
|
@@ -505,6 +535,8 @@ var Poller = class _Poller {
|
|
|
505
535
|
api;
|
|
506
536
|
pollIntervalMs;
|
|
507
537
|
log;
|
|
538
|
+
// Not readonly: start() swaps in a fresh controller when a previous stop()
|
|
539
|
+
// aborted this one (see start()).
|
|
508
540
|
controller;
|
|
509
541
|
offsetStore;
|
|
510
542
|
lock;
|
|
@@ -549,6 +581,7 @@ var Poller = class _Poller {
|
|
|
549
581
|
if (this.pollActive) return;
|
|
550
582
|
this.pollActive = true;
|
|
551
583
|
this._startedAt = Date.now();
|
|
584
|
+
if (this.controller.signal.aborted) this.controller = new AbortController();
|
|
552
585
|
this.acquireAndPoll();
|
|
553
586
|
}
|
|
554
587
|
stop() {
|
|
@@ -626,13 +659,12 @@ var Poller = class _Poller {
|
|
|
626
659
|
}
|
|
627
660
|
try {
|
|
628
661
|
this.onMessageUpdate(raw);
|
|
629
|
-
this.offset = upd.update_id + 1;
|
|
630
662
|
} catch (err) {
|
|
631
663
|
this.log.debug(
|
|
632
664
|
`Telegram processMessage failed: ${err instanceof Error ? err.message : String(err)}`
|
|
633
665
|
);
|
|
634
|
-
break;
|
|
635
666
|
}
|
|
667
|
+
this.offset = upd.update_id + 1;
|
|
636
668
|
}
|
|
637
669
|
if (this.offsetStore && updates.length > 0) void this.saveOffset();
|
|
638
670
|
} catch (err) {
|
|
@@ -2549,6 +2581,10 @@ var plugin = {
|
|
|
2549
2581
|
for (const [key, apply] of HOT_APPLIERS) {
|
|
2550
2582
|
if (hotSet.has(key)) apply(runtimeCfg, fresh);
|
|
2551
2583
|
}
|
|
2584
|
+
if (hotSet.has("inboundMode") || hotSet.has("allowedUsers") || hotSet.has("allowedChats")) {
|
|
2585
|
+
const sets = inboundAllowlist(nextTg);
|
|
2586
|
+
bot.inbox.updateAllowlist(sets.allowedUsers, sets.allowedChats);
|
|
2587
|
+
}
|
|
2552
2588
|
if (restartKeys.length > 0) {
|
|
2553
2589
|
log.warn(
|
|
2554
2590
|
"Telegram config changed restart-required keys \u2014 restart the plugin for these to take effect",
|
package/dist/poller.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/telegram",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack plugin — Telegram bridge: send messages, receive prompts, get notified.",
|
|
6
6
|
"repository": {
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"!dist/**/*.map"
|
|
27
27
|
],
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@wrongstack/core": "0.
|
|
29
|
+
"@wrongstack/core": "1.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^26.2.0",
|
|
33
|
-
"@wrongstack/core": "0.
|
|
33
|
+
"@wrongstack/core": "1.0.0",
|
|
34
34
|
"typescript": "^7.0.2"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|