remove the telegram and whatsapp channels, reduce discord to notifications

All three existed to drive the platform from a chat app. The phone app does that now, so
they are dead weight — three bot gateways, three command parsers, account pairing, admin
config screens and bot tokens sitting in the database.

Gone entirely: telegram/ and whatsapp/, discord/'s bot and command handler, the shared
channel plumbing they were the only users of (pairing.ts, send-and-await.ts, types.ts,
routes.ts and its 20 config/pairing/status endpoints), the six settings components, and
their sections in the integrations screen.

What Discord keeps is the one piece worth keeping — pushing a message out — as
notify/discord.ts, configured by DISCORD_WEBHOOK_URL in the env. No UI, no pairing, no
stored credential, and it never throws: a notification that fails to send is logged and
dropped. Unset means notifications are silently skipped, which is the default state.

Kept deliberately: send-claude-code.ts and send-opencode.ts. They live under channels/ but
have nothing to do with chat apps — they are how /chat and the pipeline executor drive an
agent turn.

Also drops four dependencies with no remaining importer (discord.js,
node-telegram-bot-api, whatsapp-web.js, qrcode), and the /sync-now route added to the email
sidecar an hour ago, whose only consumer was the channel handlers.

The "Channel Models" settings section stays, with its description corrected — it is keyed
off the general access policy rather than anything channel-specific, so it governs non-owner
accounts, not chat apps. Whether that whole class still earns its place is the open
question already noted against origin-validation.

Not touched: the telegram, whatsapp and discord rows in server_integrations, which still
hold their bot tokens. Deleting rows is a different kind of decision and the SQL is in the
handover.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 14:05:28 +00:00
co-authored by Claude Opus 5
parent e9e144962d
commit c9d680b133
27 changed files with 58 additions and 3576 deletions
-28
View File
@@ -8,7 +8,6 @@ import { getEmailAttachmentCacheDir } from '@@/data-path';
import { getEmailAccounts } from 'officerdb';
import { openEmailDb, openUserEmailDb, rowToSummary, getSyncMeta, searchEmails } from './store';
import { accountsRouter } from './accounts';
import { performResync } from './resync';
export const emailRouter = createRouter();
@@ -365,33 +364,6 @@ emailRouter.delete('/messages/:id', async (ctx) => {
}
});
// POST /sync-now — run a resync and report what arrived.
//
// For the chat channels ("sync my email" from Telegram/Discord/WhatsApp). They used to open the mail
// store directly and enqueue a `gmail-sync` job, which stopped existing when sync moved in here; and the
// job type was hardcoded to the OAuth path even though an app-password account syncs over IMAP, so that
// command had been failing regardless. One call now: sync, then say what is new.
emailRouter.post('/sync-now', async (ctx) => {
const user = ctx.get('user');
const accounts = await getEmailAccounts(user.id);
const account = accounts.find((a) => a.enabled) ?? accounts[0];
if (!account) return ctx.json({ saved: 0, newest: [], error: 'No email account configured' });
const result = await performResync({ accountId: account.id, userEmail: user.email, userId: user.id });
const db = openEmailDb(user.email, account.email);
try {
const newest =
result.saved > 0
? (db
.query('SELECT from_name, from_address, subject FROM emails WHERE deleted = 0 ORDER BY date DESC LIMIT ?')
.all(Math.min(result.saved, 20)) as Array<{ from_name: string | null; from_address: string; subject: string }>)
: [];
return ctx.json({ saved: result.saved, skipped: result.skipped, errors: result.errors, newest });
} finally {
db.close();
}
});
emailRouter.get('/sync-status', async (ctx) => {
const user = ctx.get('user');