@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
2 | 2 | import fs from "node:fs"; |
3 | 3 | import type { Message } from "grammy/types"; |
4 | 4 | import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound"; |
| 5 | +import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime"; |
5 | 6 | import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime"; |
6 | 7 | import { logVerbose } from "openclaw/plugin-sdk/runtime-env"; |
7 | 8 | import { appendRegularFileSync, replaceFileAtomicSync } from "openclaw/plugin-sdk/security-runtime"; |
@@ -240,6 +241,10 @@ function readOptionalString(record: Record<string, unknown>, key: string): strin
|
240 | 241 | return isString(value) ? value : undefined; |
241 | 242 | } |
242 | 243 | |
| 244 | +function parseSafeMessageId(value: string | undefined): number | undefined { |
| 245 | +return value === undefined ? undefined : parseStrictPositiveInteger(value); |
| 246 | +} |
| 247 | + |
243 | 248 | function isTelegramSourceMessage(value: unknown): value is Message { |
244 | 249 | return ( |
245 | 250 | isRecord(value) && |
@@ -788,14 +793,14 @@ export function createTelegramMessageCache(params?: {
|
788 | 793 | if (!messageId || limit <= 0) { |
789 | 794 | return []; |
790 | 795 | } |
791 | | -const targetId = Number(messageId); |
792 | | -if (!Number.isFinite(targetId)) { |
| 796 | +const targetId = parseSafeMessageId(messageId); |
| 797 | +if (targetId === undefined) { |
793 | 798 | return []; |
794 | 799 | } |
795 | 800 | return (await listChatMessages({ accountId, chatId, threadId })) |
796 | 801 | .filter((entry) => { |
797 | | -const entryId = Number(entry.messageId); |
798 | | -return Number.isFinite(entryId) && entryId < targetId; |
| 802 | +const entryId = parseSafeMessageId(entry.messageId); |
| 803 | +return entryId !== undefined && entryId < targetId; |
799 | 804 | }) |
800 | 805 | .slice(-limit); |
801 | 806 | }, |
@@ -820,9 +825,9 @@ function compareCachedMessageNodes(
|
820 | 825 | left: TelegramCachedMessageNode, |
821 | 826 | right: TelegramCachedMessageNode, |
822 | 827 | ) { |
823 | | -const leftId = Number(left.messageId); |
824 | | -const rightId = Number(right.messageId); |
825 | | -if (Number.isFinite(leftId) && Number.isFinite(rightId)) { |
| 828 | +const leftId = parseSafeMessageId(left.messageId); |
| 829 | +const rightId = parseSafeMessageId(right.messageId); |
| 830 | +if (leftId !== undefined && rightId !== undefined) { |
826 | 831 | return leftId - rightId; |
827 | 832 | } |
828 | 833 | return (left.messageId ?? "").localeCompare(right.messageId ?? ""); |
@@ -845,9 +850,9 @@ function isAfterSessionBoundary(
|
845 | 850 | if (!boundary) { |
846 | 851 | return true; |
847 | 852 | } |
848 | | -const nodeId = Number(node.messageId); |
849 | | -const boundaryId = Number(boundary.messageId); |
850 | | -if (Number.isFinite(nodeId) && Number.isFinite(boundaryId)) { |
| 853 | +const nodeId = parseSafeMessageId(node.messageId); |
| 854 | +const boundaryId = parseSafeMessageId(boundary.messageId); |
| 855 | +if (nodeId !== undefined && boundaryId !== undefined) { |
851 | 856 | return nodeId > boundaryId; |
852 | 857 | } |
853 | 858 | if ( |
|