mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
refactor: share thread binding id parser
This commit is contained in:
43
src/channels/thread-binding-id.test.ts
Normal file
43
src/channels/thread-binding-id.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveThreadBindingConversationIdFromBindingId } from "./thread-binding-id.js";
|
||||
|
||||
describe("resolveThreadBindingConversationIdFromBindingId", () => {
|
||||
it("returns the conversation id for matching account-prefixed binding ids", () => {
|
||||
expect(
|
||||
resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId: "default",
|
||||
bindingId: "default:thread-123",
|
||||
}),
|
||||
).toBe("thread-123");
|
||||
});
|
||||
|
||||
it("returns undefined when binding id is missing or account prefix does not match", () => {
|
||||
expect(
|
||||
resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId: "default",
|
||||
bindingId: undefined,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId: "default",
|
||||
bindingId: "work:thread-123",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("trims whitespace and rejects empty ids after the account prefix", () => {
|
||||
expect(
|
||||
resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId: "default",
|
||||
bindingId: " default:group-1:topic:99 ",
|
||||
}),
|
||||
).toBe("group-1:topic:99");
|
||||
expect(
|
||||
resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId: "default",
|
||||
bindingId: "default: ",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
15
src/channels/thread-binding-id.ts
Normal file
15
src/channels/thread-binding-id.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export function resolveThreadBindingConversationIdFromBindingId(params: {
|
||||
accountId: string;
|
||||
bindingId?: string;
|
||||
}): string | undefined {
|
||||
const bindingId = params.bindingId?.trim();
|
||||
if (!bindingId) {
|
||||
return undefined;
|
||||
}
|
||||
const prefix = `${params.accountId}:`;
|
||||
if (!bindingId.startsWith(prefix)) {
|
||||
return undefined;
|
||||
}
|
||||
const conversationId = bindingId.slice(prefix.length).trim();
|
||||
return conversationId || undefined;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Routes } from "discord-api-types/v10";
|
||||
import { resolveThreadBindingConversationIdFromBindingId } from "../../channels/thread-binding-id.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import {
|
||||
registerSessionBindingAdapter,
|
||||
@@ -157,22 +158,6 @@ function toSessionBindingRecord(
|
||||
};
|
||||
}
|
||||
|
||||
function resolveThreadIdFromBindingId(params: {
|
||||
accountId: string;
|
||||
bindingId?: string;
|
||||
}): string | undefined {
|
||||
const bindingId = params.bindingId?.trim();
|
||||
if (!bindingId) {
|
||||
return undefined;
|
||||
}
|
||||
const prefix = `${params.accountId}:`;
|
||||
if (!bindingId.startsWith(prefix)) {
|
||||
return undefined;
|
||||
}
|
||||
const threadId = bindingId.slice(prefix.length).trim();
|
||||
return threadId || undefined;
|
||||
}
|
||||
|
||||
export function createThreadBindingManager(
|
||||
params: {
|
||||
accountId?: string;
|
||||
@@ -617,7 +602,10 @@ export function createThreadBindingManager(
|
||||
return binding ? toSessionBindingRecord(binding, { idleTimeoutMs, maxAgeMs }) : null;
|
||||
},
|
||||
touch: (bindingId, at) => {
|
||||
const threadId = resolveThreadIdFromBindingId({ accountId, bindingId });
|
||||
const threadId = resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId,
|
||||
bindingId,
|
||||
});
|
||||
if (!threadId) {
|
||||
return;
|
||||
}
|
||||
@@ -631,7 +619,7 @@ export function createThreadBindingManager(
|
||||
});
|
||||
return removed.map((entry) => toSessionBindingRecord(entry, { idleTimeoutMs, maxAgeMs }));
|
||||
}
|
||||
const threadId = resolveThreadIdFromBindingId({
|
||||
const threadId = resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId,
|
||||
bindingId: input.bindingId,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { resolveThreadBindingConversationIdFromBindingId } from "../channels/thread-binding-id.js";
|
||||
import { formatThreadBindingDurationLabel } from "../channels/thread-bindings-messages.js";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { logVerbose } from "../globals.js";
|
||||
@@ -312,22 +313,6 @@ async function persistBindingsToDisk(params: {
|
||||
});
|
||||
}
|
||||
|
||||
function resolveThreadIdFromBindingId(params: {
|
||||
accountId: string;
|
||||
bindingId?: string;
|
||||
}): string | undefined {
|
||||
const bindingId = params.bindingId?.trim();
|
||||
if (!bindingId) {
|
||||
return undefined;
|
||||
}
|
||||
const prefix = `${params.accountId}:`;
|
||||
if (!bindingId.startsWith(prefix)) {
|
||||
return undefined;
|
||||
}
|
||||
const conversationId = bindingId.slice(prefix.length).trim();
|
||||
return conversationId || undefined;
|
||||
}
|
||||
|
||||
function normalizeTimestampMs(raw: unknown): number {
|
||||
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
||||
return Date.now();
|
||||
@@ -575,7 +560,7 @@ export function createTelegramThreadBindingManager(
|
||||
: null;
|
||||
},
|
||||
touch: (bindingId, at) => {
|
||||
const conversationId = resolveThreadIdFromBindingId({
|
||||
const conversationId = resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId,
|
||||
bindingId,
|
||||
});
|
||||
@@ -598,7 +583,7 @@ export function createTelegramThreadBindingManager(
|
||||
}),
|
||||
);
|
||||
}
|
||||
const conversationId = resolveThreadIdFromBindingId({
|
||||
const conversationId = resolveThreadBindingConversationIdFromBindingId({
|
||||
accountId,
|
||||
bindingId: input.bindingId,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user