Telegram user: fix timestamps and moltbot naming

This commit is contained in:
Muhammed Mukhthar CM 2026-01-28 19:05:57 +00:00
parent 125e09ac03
commit c434e49907
14 changed files with 120 additions and 63 deletions

5
.github/labeler.yml vendored
View File

@ -68,6 +68,11 @@
- "src/telegram/**" - "src/telegram/**"
- "extensions/telegram/**" - "extensions/telegram/**"
- "docs/channels/telegram.md" - "docs/channels/telegram.md"
"channel: telegram-user":
- changed-files:
- any-glob-to-any-file:
- "extensions/telegram-user/**"
- "docs/channels/telegram-user.md"
"channel: tlon": "channel: tlon":
- changed-files: - changed-files:
- any-glob-to-any-file: - any-glob-to-any-file:

View File

@ -3,7 +3,7 @@ summary: "Connect a Telegram user account via MTProto (DMs + groups)"
--- ---
# Telegram User # Telegram User
Telegram User connects Clawdbot to a **personal Telegram account** using MTProto. Telegram User connects Moltbot to a **personal Telegram account** using MTProto.
Use this when you need user-level DMs or want to message from your own account in groups. Use this when you need user-level DMs or want to message from your own account in groups.
## Requirements ## Requirements
@ -16,7 +16,7 @@ Use this when you need user-level DMs or want to message from your own account i
If the plugin is not bundled, install it: If the plugin is not bundled, install it:
```bash ```bash
clawdbot plugins install @clawdbot/telegram-user moltbot plugins install @moltbot/telegram-user
``` ```
## Configure ## Configure
@ -27,25 +27,25 @@ Option A: env vars (default account only)
```bash ```bash
export TELEGRAM_USER_API_ID="123456" export TELEGRAM_USER_API_ID="123456"
export TELEGRAM_USER_API_HASH="your_api_hash" export TELEGRAM_USER_API_HASH="your_api_hash"
clawdbot channels add --channel telegram-user --use-env moltbot channels add --channel telegram-user --use-env
``` ```
Option B: config Option B: config
```bash ```bash
clawdbot channels add --channel telegram-user --api-id 123456 --api-hash your_api_hash moltbot channels add --channel telegram-user --api-id 123456 --api-hash your_api_hash
``` ```
## Login (QR or phone code) ## Login (QR or phone code)
QR login (default): QR login (default):
```bash ```bash
clawdbot channels login --channel telegram-user moltbot channels login --channel telegram-user
``` ```
Phone login: Phone login:
```bash ```bash
export TELEGRAM_USER_PHONE="+15551234567" export TELEGRAM_USER_PHONE="+15551234567"
clawdbot channels login --channel telegram-user moltbot channels login --channel telegram-user
``` ```
Optional env helpers: Optional env helpers:
@ -57,7 +57,7 @@ Optional env helpers:
By default, DMs are protected with pairing. Approve requests with: By default, DMs are protected with pairing. Approve requests with:
```bash ```bash
clawdbot pairing approve telegram-user <code> moltbot pairing approve telegram-user <code>
``` ```
See [Pairing](/start/pairing) for details. See [Pairing](/start/pairing) for details.

View File

@ -1,4 +1,4 @@
import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk"; import type { MoltbotPluginApi } from "clawdbot/plugin-sdk";
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk"; import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
import { telegramUserPlugin } from "./src/channel.js"; import { telegramUserPlugin } from "./src/channel.js";
@ -9,7 +9,7 @@ const plugin = {
name: "Telegram User", name: "Telegram User",
description: "Telegram MTProto user channel plugin", description: "Telegram MTProto user channel plugin",
configSchema: emptyPluginConfigSchema(), configSchema: emptyPluginConfigSchema(),
register(api: ClawdbotPluginApi) { register(api: MoltbotPluginApi) {
setTelegramUserRuntime(api.runtime); setTelegramUserRuntime(api.runtime);
api.registerChannel({ plugin: telegramUserPlugin }); api.registerChannel({ plugin: telegramUserPlugin });
}, },

View File

@ -1,9 +1,9 @@
{ {
"name": "@clawdbot/telegram-user", "name": "@moltbot/telegram-user",
"version": "2026.1.22", "version": "2026.1.22",
"type": "module", "type": "module",
"description": "Clawdbot Telegram user (MTProto) channel plugin", "description": "Moltbot Telegram user (MTProto) channel plugin",
"clawdbot": { "moltbot": {
"extensions": [ "extensions": [
"./index.ts" "./index.ts"
], ],
@ -19,7 +19,7 @@
"quickstartAllowFrom": true "quickstartAllowFrom": true
}, },
"install": { "install": {
"npmSpec": "@clawdbot/telegram-user", "npmSpec": "@moltbot/telegram-user",
"localPath": "extensions/telegram-user", "localPath": "extensions/telegram-user",
"defaultChoice": "npm" "defaultChoice": "npm"
} }
@ -33,9 +33,9 @@
"zod": "^4.3.6" "zod": "^4.3.6"
}, },
"devDependencies": { "devDependencies": {
"clawdbot": "workspace:*" "moltbot": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {
"clawdbot": ">=2026.1.25" "moltbot": ">=2026.1.25"
} }
} }

View File

@ -1,11 +1,25 @@
import type { TelegramClient } from "@mtcute/node"; import type { TelegramClient } from "@mtcute/node";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
let activeClient: TelegramClient | null = null; const activeClients = new Map<string, TelegramClient>();
export function setActiveTelegramUserClient(next: TelegramClient | null) { function resolveAccountKey(accountId?: string | null): string {
activeClient = next; return normalizeAccountId(accountId ?? DEFAULT_ACCOUNT_ID);
} }
export function getActiveTelegramUserClient(): TelegramClient | null { export function setActiveTelegramUserClient(
return activeClient; accountId: string | null | undefined,
next: TelegramClient | null,
) {
const key = resolveAccountKey(accountId);
if (next) {
activeClients.set(key, next);
return;
}
activeClients.delete(key);
}
export function getActiveTelegramUserClient(accountId?: string | null): TelegramClient | null {
const key = resolveAccountKey(accountId);
return activeClients.get(key) ?? null;
} }

View File

@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
import type { ClawdbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk"; import type { MoltbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk";
const sendMediaTelegramUser = vi.fn< const sendMediaTelegramUser = vi.fn<
typeof import("./send.js").sendMediaTelegramUser typeof import("./send.js").sendMediaTelegramUser
@ -37,7 +37,7 @@ describe("telegram-user channel plugin", () => {
mediaMaxMb: 7, mediaMaxMb: 7,
}, },
}, },
} satisfies Partial<ClawdbotConfig> as unknown as ClawdbotConfig; } satisfies Partial<MoltbotConfig> as unknown as MoltbotConfig;
const mod = await import("./channel.js"); const mod = await import("./channel.js");
await mod.telegramUserPlugin.outbound?.sendMedia?.({ await mod.telegramUserPlugin.outbound?.sendMedia?.({
@ -60,7 +60,7 @@ describe("telegram-user channel plugin", () => {
channels: { channels: {
"telegram-user": {}, "telegram-user": {},
}, },
} satisfies Partial<ClawdbotConfig> as unknown as ClawdbotConfig; } satisfies Partial<MoltbotConfig> as unknown as MoltbotConfig;
const mod = await import("./channel.js"); const mod = await import("./channel.js");
await mod.telegramUserPlugin.outbound?.sendMedia?.({ await mod.telegramUserPlugin.outbound?.sendMedia?.({
@ -88,7 +88,7 @@ describe("telegram-user channel plugin", () => {
}, },
}, },
}, },
} satisfies Partial<ClawdbotConfig> as unknown as ClawdbotConfig; } satisfies Partial<MoltbotConfig> as unknown as MoltbotConfig;
const mod = await import("./channel.js"); const mod = await import("./channel.js");
const runtime = { const runtime = {

View File

@ -7,12 +7,13 @@ import {
deleteAccountFromConfigSection, deleteAccountFromConfigSection,
formatPairingApproveHint, formatPairingApproveHint,
normalizeAccountId, normalizeAccountId,
PAIRING_APPROVED_MESSAGE,
resolveChannelMediaMaxBytes, resolveChannelMediaMaxBytes,
setAccountEnabledInConfigSection, setAccountEnabledInConfigSection,
type ChannelGroupContext, type ChannelGroupContext,
type ChannelPlugin, type ChannelPlugin,
type ChannelSetupInput, type ChannelSetupInput,
type ClawdbotConfig, type MoltbotConfig,
type GroupToolPolicyConfig, type GroupToolPolicyConfig,
} from "clawdbot/plugin-sdk"; } from "clawdbot/plugin-sdk";
@ -108,7 +109,7 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
normalizeAllowEntry: (entry) => normalizeAllowEntry: (entry) =>
entry.replace(/^(telegram-user|telegram|tg):/i, "").toLowerCase(), entry.replace(/^(telegram-user|telegram|tg):/i, "").toLowerCase(),
notifyApproval: async ({ id }) => { notifyApproval: async ({ id }) => {
await sendMessageTelegramUser(String(id), "Clawdbot: access approved.", {}); await sendMessageTelegramUser(String(id), PAIRING_APPROVED_MESSAGE, {});
}, },
}, },
capabilities: { capabilities: {
@ -337,7 +338,7 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId), resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
applyAccountName: ({ cfg, accountId, name }) => applyAccountName: ({ cfg, accountId, name }) =>
applyAccountNameToChannelSection({ applyAccountNameToChannelSection({
cfg: cfg as ClawdbotConfig, cfg: cfg as MoltbotConfig,
channelKey: "telegram-user", channelKey: "telegram-user",
accountId, accountId,
name, name,
@ -355,7 +356,7 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
applyAccountConfig: ({ cfg, accountId, input }) => { applyAccountConfig: ({ cfg, accountId, input }) => {
const setupInput = input as TelegramUserSetupInput; const setupInput = input as TelegramUserSetupInput;
const namedConfig = applyAccountNameToChannelSection({ const namedConfig = applyAccountNameToChannelSection({
cfg: cfg as ClawdbotConfig, cfg: cfg as MoltbotConfig,
channelKey: "telegram-user", channelKey: "telegram-user",
accountId, accountId,
name: setupInput.name, name: setupInput.name,
@ -432,13 +433,13 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
throw err; throw err;
} }
}, },
stopAccount: async () => { stopAccount: async ({ accountId }) => {
const { getActiveTelegramUserClient, setActiveTelegramUserClient } = const { getActiveTelegramUserClient, setActiveTelegramUserClient } =
await import("./active-client.js"); await import("./active-client.js");
const active = getActiveTelegramUserClient(); const active = getActiveTelegramUserClient(accountId);
if (active) { if (active) {
await active.destroy().catch(() => undefined); await active.destroy().catch(() => undefined);
setActiveTelegramUserClient(null); setActiveTelegramUserClient(accountId, null);
} }
}, },
logoutAccount: async ({ accountId, cfg, runtime }) => { logoutAccount: async ({ accountId, cfg, runtime }) => {
@ -453,7 +454,7 @@ export const telegramUserPlugin: ChannelPlugin<ResolvedTelegramUserAccount> = {
} }
} }
const nextCfg = { ...cfg } as ClawdbotConfig; const nextCfg = { ...cfg } as MoltbotConfig;
const nextSection = cfg.channels?.["telegram-user"] const nextSection = cfg.channels?.["telegram-user"]
? { ...cfg.channels["telegram-user"] } ? { ...cfg.channels["telegram-user"] }
: undefined; : undefined;

View File

@ -17,10 +17,10 @@ export async function createTelegramUserClient(params: {
// the "import" condition (ESM), eliminating the warning. // the "import" condition (ESM), eliminating the warning.
const { BaseTelegramClient, TelegramClient, NodePlatform } = await loadMtcuteNode(); const { BaseTelegramClient, TelegramClient, NodePlatform } = await loadMtcuteNode();
class ClawdbotTelegramUserPlatform extends NodePlatform { class MoltbotTelegramUserPlatform extends NodePlatform {
// mtcute's default NodePlatform.beforeExit installs SIGINT/SIGTERM handlers that re-send the // mtcute's default NodePlatform.beforeExit installs SIGINT/SIGTERM handlers that re-send the
// signal, which can race with Clawdbot's graceful shutdown and close sqlite while writes are // signal, which can race with Moltbot's graceful shutdown and close sqlite while writes are
// pending. We only hook into process exit events (no signal handlers) and rely on Clawdbot to // pending. We only hook into process exit events (no signal handlers) and rely on Moltbot to
// stop cleanly. // stop cleanly.
override beforeExit(fn: () => void): () => void { override beforeExit(fn: () => void): () => void {
const onBeforeExit = () => fn(); const onBeforeExit = () => fn();
@ -38,7 +38,7 @@ export async function createTelegramUserClient(params: {
apiId: params.apiId, apiId: params.apiId,
apiHash: params.apiHash, apiHash: params.apiHash,
storage: params.storagePath, storage: params.storagePath,
platform: new ClawdbotTelegramUserPlatform(), platform: new MoltbotTelegramUserPlatform(),
}); });
return new TelegramClient({ client }); return new TelegramClient({ client });
} }

View File

@ -1,10 +1,10 @@
import type { ChannelDirectoryEntry, ClawdbotConfig } from "clawdbot/plugin-sdk"; import type { ChannelDirectoryEntry, MoltbotConfig } from "clawdbot/plugin-sdk";
import { resolveTelegramUserAccount } from "./accounts.js"; import { resolveTelegramUserAccount } from "./accounts.js";
import type { CoreConfig } from "./types.js"; import type { CoreConfig } from "./types.js";
export type TelegramUserDirectoryConfigParams = { export type TelegramUserDirectoryConfigParams = {
cfg: ClawdbotConfig; cfg: MoltbotConfig;
accountId?: string | null; accountId?: string | null;
query?: string | null; query?: string | null;
limit?: number | null; limit?: number | null;
@ -65,4 +65,3 @@ export async function listTelegramUserDirectoryGroupsFromConfig(
.slice(0, params.limit && params.limit > 0 ? params.limit : undefined) .slice(0, params.limit && params.limit > 0 ? params.limit : undefined)
.map((id) => ({ kind: "group", id }) as const); .map((id) => ({ kind: "group", id }) as const);
} }

View File

@ -0,0 +1,23 @@
import { describe, expect, it } from "vitest";
import { resolveTelegramUserTimestampMs } from "./handler.js";
describe("resolveTelegramUserTimestampMs", () => {
it("uses Date values directly", () => {
const date = new Date("2025-01-02T03:04:05Z");
expect(resolveTelegramUserTimestampMs(date)).toBe(date.getTime());
});
it("converts seconds to milliseconds", () => {
expect(resolveTelegramUserTimestampMs(1_710_000_000)).toBe(1_710_000_000 * 1000);
});
it("passes through millisecond values", () => {
expect(resolveTelegramUserTimestampMs(1_710_000_000_000)).toBe(1_710_000_000_000);
});
it("returns undefined for invalid dates", () => {
const invalid = new Date("invalid");
expect(resolveTelegramUserTimestampMs(invalid)).toBeUndefined();
});
});

View File

@ -115,6 +115,20 @@ function buildTelegramUserSelfMentionRegexes(params: {
.filter((entry): entry is RegExp => Boolean(entry)); .filter((entry): entry is RegExp => Boolean(entry));
} }
export function resolveTelegramUserTimestampMs(
value: Date | number | null | undefined,
): number | undefined {
if (value == null) return undefined;
if (value instanceof Date) {
const ms = value.getTime();
return Number.isFinite(ms) ? ms : undefined;
}
if (typeof value === "number" && Number.isFinite(value)) {
return value < 1_000_000_000_000 ? Math.round(value * 1000) : Math.round(value);
}
return undefined;
}
async function safeSendTyping(params: { async function safeSendTyping(params: {
client: TelegramClient; client: TelegramClient;
target: number | string; target: number | string;
@ -348,9 +362,7 @@ export function createTelegramUserMessageHandler(params: TelegramUserHandlerPara
const chatId = msg.chat.type === "chat" ? msg.chat.id : undefined; const chatId = msg.chat.type === "chat" ? msg.chat.id : undefined;
const isForum = msg.chat.type === "chat" && msg.chat.isForum === true; const isForum = msg.chat.type === "chat" && msg.chat.isForum === true;
const threadId = const threadId =
isGroup && msg.isTopicMessage isGroup && isForum ? msg.replyToMessage?.threadId ?? undefined : undefined;
? msg.replyToMessage?.threadId ?? undefined
: undefined;
const { groupConfig, topicConfig } = const { groupConfig, topicConfig } =
isGroup && chatId != null isGroup && chatId != null
? resolveTelegramUserGroupConfig(accountConfig, chatId, threadId) ? resolveTelegramUserGroupConfig(accountConfig, chatId, threadId)
@ -452,7 +464,7 @@ export function createTelegramUserMessageHandler(params: TelegramUserHandlerPara
const media = allMedia[0] ?? null; const media = allMedia[0] ?? null;
const rawBody = [text, locationText, pollText].filter(Boolean).join("\n").trim(); const rawBody = [text, locationText, pollText].filter(Boolean).join("\n").trim();
if (!rawBody && !media) return; if (!rawBody && !media) return;
const timestampMs = msg.date ? msg.date * 1000 : undefined; const timestampMs = resolveTelegramUserTimestampMs(msg.date);
const replyInfo = msg.replyToMessage ?? null; const replyInfo = msg.replyToMessage ?? null;
const replyToId = replyInfo?.id != null ? String(replyInfo.id) : undefined; const replyToId = replyInfo?.id != null ? String(replyInfo.id) : undefined;
const replyToSender = replyInfo?.sender const replyToSender = replyInfo?.sender

View File

@ -60,15 +60,15 @@ export async function monitorTelegramUserProvider(opts: MonitorTelegramUserOpts
const storagePath = resolveTelegramUserSessionPath(account.accountId); const storagePath = resolveTelegramUserSessionPath(account.accountId);
if (!fs.existsSync(storagePath)) { if (!fs.existsSync(storagePath)) {
throw new Error( throw new Error(
"Telegram user session missing. Run `clawdbot channels login --channel telegram-user` first.", "Telegram user session missing. Run `moltbot channels login --channel telegram-user` first.",
); );
} }
const client = await createTelegramUserClient({ apiId, apiHash, storagePath }); const client = await createTelegramUserClient({ apiId, apiHash, storagePath });
setActiveTelegramUserClient(client); setActiveTelegramUserClient(account.accountId, client);
const stop = async () => { const stop = async () => {
shuttingDown = true; shuttingDown = true;
setActiveTelegramUserClient(null); setActiveTelegramUserClient(account.accountId, null);
await client.destroy().catch(() => undefined); await client.destroy().catch(() => undefined);
}; };

View File

@ -6,7 +6,7 @@ import {
normalizeAccountId, normalizeAccountId,
type ChannelOnboardingAdapter, type ChannelOnboardingAdapter,
type ChannelOnboardingDmPolicy, type ChannelOnboardingDmPolicy,
type ClawdbotConfig, type MoltbotConfig,
type DmPolicy, type DmPolicy,
type WizardPrompter, type WizardPrompter,
} from "clawdbot/plugin-sdk"; } from "clawdbot/plugin-sdk";
@ -24,10 +24,10 @@ const channel = "telegram-user" as const;
type TelegramUserChannelConfig = NonNullable<CoreConfig["channels"]>["telegram-user"]; type TelegramUserChannelConfig = NonNullable<CoreConfig["channels"]>["telegram-user"];
function setTelegramUserDmPolicy( function setTelegramUserDmPolicy(
cfg: ClawdbotConfig, cfg: MoltbotConfig,
policy: DmPolicy, policy: DmPolicy,
accountId?: string, accountId?: string,
): ClawdbotConfig { ): MoltbotConfig {
const resolvedAccountId = normalizeAccountId(accountId) ?? DEFAULT_ACCOUNT_ID; const resolvedAccountId = normalizeAccountId(accountId) ?? DEFAULT_ACCOUNT_ID;
const current = cfg.channels?.["telegram-user"] as TelegramUserChannelConfig | undefined; const current = cfg.channels?.["telegram-user"] as TelegramUserChannelConfig | undefined;
const allowFrom = const allowFrom =
@ -38,13 +38,13 @@ function setTelegramUserDmPolicy(
if (resolvedAccountId === DEFAULT_ACCOUNT_ID) { if (resolvedAccountId === DEFAULT_ACCOUNT_ID) {
return { return {
...cfg, ...cfg,
channels: { channels: {
...cfg.channels, ...cfg.channels,
"telegram-user": { "telegram-user": {
...(current ?? {}), ...(current ?? {}),
dmPolicy: policy, dmPolicy: policy,
...(allowFrom ? { allowFrom } : {}), ...(allowFrom ? { allowFrom } : {}),
}, },
}, },
}; };
} }
@ -73,7 +73,7 @@ async function noteTelegramUserAuthHelp(prompter: WizardPrompter): Promise<void>
[ [
"Telegram User (MTProto) needs an API ID + API hash from my.telegram.org.", "Telegram User (MTProto) needs an API ID + API hash from my.telegram.org.",
"You can store them in config or set TELEGRAM_USER_API_ID/TELEGRAM_USER_API_HASH.", "You can store them in config or set TELEGRAM_USER_API_ID/TELEGRAM_USER_API_HASH.",
"Login happens via `clawdbot channels login --channel telegram-user`.", "Login happens via `moltbot channels login --channel telegram-user`.",
`Docs: ${formatDocsLink("/channels/telegram-user", "channels/telegram-user")}`, `Docs: ${formatDocsLink("/channels/telegram-user", "channels/telegram-user")}`,
].join("\n"), ].join("\n"),
"Telegram user setup", "Telegram user setup",
@ -94,10 +94,10 @@ function parseAllowFromInput(raw: string): string[] {
} }
async function promptTelegramUserAllowFrom(params: { async function promptTelegramUserAllowFrom(params: {
cfg: ClawdbotConfig; cfg: MoltbotConfig;
prompter: WizardPrompter; prompter: WizardPrompter;
accountId?: string; accountId?: string;
}): Promise<ClawdbotConfig> { }): Promise<MoltbotConfig> {
const accountId = normalizeAccountId(params.accountId) ?? DEFAULT_ACCOUNT_ID; const accountId = normalizeAccountId(params.accountId) ?? DEFAULT_ACCOUNT_ID;
const resolved = resolveTelegramUserAccount({ const resolved = resolveTelegramUserAccount({
cfg: params.cfg as CoreConfig, cfg: params.cfg as CoreConfig,
@ -197,7 +197,7 @@ export const telegramUserOnboardingAdapter: ChannelOnboardingAdapter = {
let accountId = override ? normalizeAccountId(override) : defaultAccountId; let accountId = override ? normalizeAccountId(override) : defaultAccountId;
if (shouldPromptAccountIds && !override) { if (shouldPromptAccountIds && !override) {
accountId = await promptAccountId({ accountId = await promptAccountId({
cfg: cfg as ClawdbotConfig, cfg: cfg as MoltbotConfig,
prompter, prompter,
label: "Telegram User", label: "Telegram User",
currentId: accountId ?? defaultAccountId, currentId: accountId ?? defaultAccountId,
@ -344,7 +344,7 @@ export const telegramUserOnboardingAdapter: ChannelOnboardingAdapter = {
} catch (err) { } catch (err) {
runtime.error(`Telegram user login failed: ${String(err)}`); runtime.error(`Telegram user login failed: ${String(err)}`);
await prompter.note( await prompter.note(
`Run \`clawdbot channels login --channel telegram-user\` later to link.`, `Run \`moltbot channels login --channel telegram-user\` later to link.`,
"Telegram user login", "Telegram user login",
); );
} }
@ -353,7 +353,7 @@ export const telegramUserOnboardingAdapter: ChannelOnboardingAdapter = {
await prompter.note( await prompter.note(
[ [
"Next: link the account via QR or phone code.", "Next: link the account via QR or phone code.",
"Run: clawdbot channels login --channel telegram-user", "Run: moltbot channels login --channel telegram-user",
].join("\n"), ].join("\n"),
"Telegram user login", "Telegram user login",
); );

View File

@ -6,6 +6,7 @@ import { getTelegramUserRuntime } from "./runtime.js";
import { resolveTelegramUserAccount } from "./accounts.js"; import { resolveTelegramUserAccount } from "./accounts.js";
import { createTelegramUserClient } from "./client.js"; import { createTelegramUserClient } from "./client.js";
import { resolveTelegramUserSessionPath } from "./session.js"; import { resolveTelegramUserSessionPath } from "./session.js";
import { getActiveTelegramUserClient } from "./active-client.js";
import type { CoreConfig } from "./types.js"; import type { CoreConfig } from "./types.js";
export type TelegramUserSendResult = { export type TelegramUserSendResult = {
@ -145,6 +146,8 @@ async function resolveClient(params: {
cfg: params.cfg, cfg: params.cfg,
accountId: params.accountId, accountId: params.accountId,
}); });
const active = getActiveTelegramUserClient(account.accountId);
if (active) return { client: active, stopOnDone: false };
const apiId = account.credentials.apiId; const apiId = account.credentials.apiId;
const apiHash = account.credentials.apiHash; const apiHash = account.credentials.apiHash;
if (!apiId || !apiHash) { if (!apiId || !apiHash) {
@ -153,7 +156,7 @@ async function resolveClient(params: {
const storagePath = resolveTelegramUserSessionPath(account.accountId); const storagePath = resolveTelegramUserSessionPath(account.accountId);
if (!fs.existsSync(storagePath)) { if (!fs.existsSync(storagePath)) {
throw new Error( throw new Error(
"Telegram user session missing. Run `clawdbot channels login --channel telegram-user` first.", "Telegram user session missing. Run `moltbot channels login --channel telegram-user` first.",
); );
} }
const client = await createTelegramUserClient({ apiId, apiHash, storagePath }); const client = await createTelegramUserClient({ apiId, apiHash, storagePath });