fix: keep the paired user when the poll loop commits its offset

The poll loop persisted the config object it captured when polling started.
The store swaps in a fresh object on every persist, so after the initial sync
that captured copy lacked later changes: the next offset commit erased the
paired user and the bridge re-paired on every message.
This commit is contained in:
evandrodevbr committed 2026-10-01 11:14:02 -03:00
1 parent 033a92f3bb
commit 60254b288b
2 files changed
+47 -1

No files matched your search

+38
View File
@@ -4,6 +4,9 @@
*/
import assert from "node:assert/strict";
import { mkdtempSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import {
@@ -29,6 +32,7 @@ import {
stopTelegramPollingRuntime,
TELEGRAM_ALLOWED_UPDATES,
} from "../lib/polling.ts";
import { createTelegramConfigStore } from "../lib/config.ts";
const TEST_CONTEXT = "ctx";
@@ -601,6 +605,40 @@ test("Poll loop runner binds config, status, and transport ports", async () => {
assert.deepEqual(events, ["deleteWebhook", "handle:ctx:6", "persist:6"]);
});
test("Poll loop keeps the paired user when the offset is committed after the initial sync replaced the stored config", async () => {
const dir = mkdtempSync(join(tmpdir(), "telegram-pairing-"));
const configPath = join(dir, "telegram.json");
const store = createTelegramConfigStore({ agentDir: dir, configPath });
await store.load();
store.update((config) => {
config.botToken = "123:abc";
});
await store.persist();
let calls = 0;
const runPollLoop = createTelegramPollLoopRunner({
getConfig: store.get,
deleteWebhook: async () => {},
getUpdates: async () => {
calls += 1;
if (calls === 1) return [{ update_id: 1 }]; // initial sync
if (calls === 2) return [{ update_id: 2 }]; // the owner's /start
throw new DOMException("stop", "AbortError");
},
persistConfig: store.persist,
handleUpdate: async () => {
store.setAllowedUserId(777);
await store.persist();
},
updateStatus: () => {},
sleep: async () => {},
});
await runPollLoop("ctx", new AbortController().signal);
assert.equal(store.getAllowedUserId(), 777);
const saved = JSON.parse(readFileSync(configPath, "utf8"));
assert.equal(saved.allowedUserId, 777);
assert.equal(saved.lastUpdateId, 2);
});
test("Poll loop runner ignores stale-context status failures while retrying", async () => {
const config = { botToken: "123:abc", lastUpdateId: 1 };
const events: string[] = [];