// Telegram pairing page (page_id `telegram`, visible to any user with a // `plugin_access` grant). // // Self-service chat linking: the user sends any message to the bot, gets a // 6-character code back, and pastes it here. Reuses the core per-user config // endpoints — `GET /api/plugins/mine` to read the `{linked, chat_id}` status // blob, `PUT /api/plugins/telegram/my-config` to submit the code (the // plugin's `update_user_config` override turns it into a chat↔user binding) — // so this fragment needs no backend of its own. Default-exports the element // class; the host registers it. import { LitElement, html, nothing } from 'lit'; import { t, addStrings, I18nMixin } from '/lib/i18n.js'; import STRINGS from './i18n.js'; addStrings(STRINGS); const P = 'plugin.telegram'; const ID = 'telegram'; /// JSON fetch that throws the server's error text on non-2xx and tolerates an /// empty (204) body. The server's error text is already localized, so it is /// safe to surface directly. async function jf(url, opts = {}) { const res = await fetch(url, { headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) }, ...opts, }); if (!res.ok) { const txt = await res.text().catch(() => ''); throw new Error(txt || `HTTP ${res.status}`); } if (res.status === 204) return null; const ct = res.headers.get('content-type') || ''; return ct.includes('application/json') ? res.json() : res.text(); } export default class TelegramPage extends I18nMixin(LitElement) { // Light DOM, so Bootstrap classes and the app's theme CSS variables apply. createRenderRoot() { return this; } static get properties() { return { _row: { state: true }, // UserPluginView | null (null once loaded = not granted) _code: { state: true }, // pairing code draft _status: { state: true }, // { ok?, err? } _error: { state: true }, _loading: { state: true }, }; } constructor() { super(); this._row = null; this._code = ''; this._status = {}; this._error = null; this._loading = true; } connectedCallback() { super.connectedCallback(); this._load(); } async _load() { this._loading = true; this._error = null; try { const mine = await jf('/api/plugins/mine'); this._row = (mine ?? []).find(x => x.id === ID) ?? null; } catch (e) { this._error = e.message; } finally { this._loading = false; } } async _save() { this._status = {}; try { await jf(`/api/plugins/${ID}/my-config`, { method: 'PUT', body: JSON.stringify({ pairing_code: this._code.trim() }), }); this._code = ''; this._status = { ok: t(`${P}.saved`) }; await this._load(); } catch (e) { this._status = { err: e.message }; } } render() { return html`
${t(`${P}.unavailable`)}
${t(`${P}.intro`)}
${t(`${P}.howto_body`)}