merlyn/server/models/externalCommunicationConnector.js
Sean Hatfield 192ca411f2
Telegram bot connector (#5190)
* wip telegram bot connector

* encrypt bot token, reorg telegram bot modules, secure pairing codes

* offload telegram chat to background worker, add @agent support with chart png rendering, reconnect ui

* refactor telegram bot settings page into subcomponents

* response.locals for mum, telemetry for connecting to telegram

* simplify telegram command registration

* improve telegram bot ux: rework switch/history/resume commands

* add voice, photo, and TTS support to telegram bot with long message handling

* lint

* rename external_connectors to external_communication_connectors, add voice response mode, persist chat workspace/thread selection

* lint

* fix telegram bot connect/disconnect bugs, kill telegram bot on multiuser mode enable

* add english translations

* fix qr code in light mode

* repatch migration

* WIP checkpoint

* pipeline overhaul for using response obj

* format functions

* fix comment block

* remove conditional dumpENV + lint

* remove .end() from sendStatus calls

* patch broken streaming where streaming only first chunk

* refactor

* use Ephemeral handler now

* show metrics and citations in real GUI

* bugfixes

* prevent MuM persistence, UI cleanup, styling for status

* add new workspace flow in UI
Add thread chat count
fix 69 byte payload callback limit bug

* handle pagination for workspaces, threads, and models

* modularize commands and navigation

* add /proof support for citation recall

* handle backlog message spam

* support abort of response streams

* code cleanup

* spam prevention

* fix translations, update voice typing indicator, fix token bug

* frontend refactor, update tips on /status and voice response improvements

* collapse agent though blocks

* support images

* Fix mime issues with audio from other devices

* fix config issue post server stop

* persist image on agentic chats

* 5189 i18n (#5245)

* i18n translations
connect #5189

* prune translations

* fix errors

* fix translation gaps

---------

Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
2026-03-23 15:10:21 -07:00

111 lines
3.1 KiB
JavaScript

const prisma = require("../utils/prisma");
const { safeJsonParse } = require("../utils/http");
const ExternalCommunicationConnector = {
supportedTypes: ["telegram"],
/**
* Get a connector by type.
* @param {'telegram'} type
* @returns {Promise<{id: number, type: string, config: object, active: boolean}|null>}
*/
get: async function (type) {
try {
const connector =
await prisma.external_communication_connectors.findUnique({
where: { type },
});
if (!connector) return null;
return {
...connector,
config: safeJsonParse(connector.config, {}),
};
} catch (error) {
console.error("ExternalCommunicationConnector.get", error.message);
return null;
}
},
/**
* Create or update a connector's config and active state.
* @param {'telegram'} type
* @param {object} config
* @param {boolean} active
* @returns {Promise<{connector: object|null, error: string|null}>}
*/
upsert: async function (type, config = {}) {
if (!this.supportedTypes.includes(type))
return { connector: null, error: `Unsupported connector type: ${type}` };
try {
let update = {},
create = {};
if (config.hasOwnProperty("active")) {
update.active = Boolean(config.active);
create.active = Boolean(config.active);
delete config.active;
}
update = Object.assign(update, {
config: JSON.stringify(config),
lastUpdatedAt: new Date(),
});
create = Object.assign(create, {
config: JSON.stringify(config),
type: String(type),
});
const connector = await prisma.external_communication_connectors.upsert({
where: { type: String(type) },
update,
create,
});
return {
connector: {
...connector,
config: safeJsonParse(connector.config, {}),
},
error: null,
};
} catch (error) {
console.error("ExternalCommunicationConnector.upsert", error.message);
return { connector: null, error: error.message };
}
},
/**
* Merge partial config updates into an existing connector.
* @param {'telegram'} type
* @param {object} configUpdates - Partial config to merge.
* @returns {Promise<{connector: object|null, error: string|null}>}
*/
updateConfig: async function (type, configUpdates = {}) {
const existing = await this.get(type);
if (!existing)
return { connector: null, error: `No ${type} connector found` };
const mergedConfig = { ...existing.config, ...configUpdates };
return this.upsert(type, mergedConfig, existing.active);
},
/**
* Delete a connector entirely.
* @param {'telegram'} type
* @returns {Promise<boolean>}
*/
delete: async function (type) {
try {
await prisma.external_communication_connectors.delete({
where: { type },
});
return true;
} catch (error) {
console.error("ExternalCommunicationConnector.delete", error.message);
return false;
}
},
};
module.exports = { ExternalCommunicationConnector };