Add Matrix credential upload route + local seed script
Closes the noVNC-unavailable gap: when Dokploy's reverse proxy strips WebSocket upgrades for noVNC, there's no way to do a one-time interactive Reddit login in the deployed container. Without that, extractMatrixCredentials inside the container hits the /chat/ login wall and never sniffs a bearer. Add POST /api/debug/matrix-credentials that accepts a credentials JSON body, persists it to data/matrix-credentials.json, and hot-swaps it into the running ChatService via setMatrixClient. Also export saveCredentials from the chat module so the route can reuse the same cache-file logic as the in-container sniff. scripts/seed-matrix-creds.ts opens a headed Chromium on the dev's machine, waits for an interactive Reddit login (detected by polling /api/me.json from inside the page), opens www.reddit.com/chat/, sniffs the first authed matrix.redditspace.com request, resolves user_id via /whoami, and POSTs the result to BOT_URL/api/debug/matrix-credentials. End-to-end seeding without ever touching the container. Usage: BOT_URL=https://red.apps.jbrunton.co.uk tsx scripts/seed-matrix-creds.ts Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
e58bccf6b5
commit
0c7df6e1d3
3 files changed
+196
No files matched your search
@@ -2,6 +2,11 @@ import { Router } from 'express';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import type { WebContext } from '../context.js';
|
||||
import {
|
||||
MatrixClient,
|
||||
saveCredentials,
|
||||
type MatrixCredentials,
|
||||
} from '../../services/chat/index.js';
|
||||
|
||||
export function createDebugRouter(ctx: WebContext): Router {
|
||||
const router = Router();
|
||||
@@ -60,6 +65,40 @@ export function createDebugRouter(ctx: WebContext): Router {
|
||||
}
|
||||
});
|
||||
|
||||
// Accepts a Matrix credentials JSON body, persists it to the cache file,
|
||||
// and swaps it into the running ChatService. Lets us seed the deployed bot
|
||||
// from a sniff run on a developer's machine when the in-container sniff
|
||||
// can't reach an authed /chat/ surface and noVNC isn't an option.
|
||||
//
|
||||
// Body shape: { homeserver, accessToken, userId?, capturedAt? }
|
||||
router.post('/debug/matrix-credentials', (req, res) => {
|
||||
const body = (req.body ?? {}) as Partial<MatrixCredentials>;
|
||||
if (!body.homeserver || !body.accessToken) {
|
||||
res.status(400).json({ error: 'homeserver and accessToken are required' });
|
||||
return;
|
||||
}
|
||||
const creds: MatrixCredentials = {
|
||||
homeserver: body.homeserver,
|
||||
accessToken: body.accessToken,
|
||||
userId: body.userId ?? '',
|
||||
capturedAt: body.capturedAt ?? Date.now(),
|
||||
};
|
||||
try {
|
||||
saveCredentials(creds);
|
||||
ctx.logger.info(
|
||||
`[matrix] credentials uploaded via /api/debug/matrix-credentials (user=${creds.userId || 'unknown'})`,
|
||||
);
|
||||
if (ctx.services.chat) {
|
||||
ctx.services.chat.setMatrixClient(new MatrixClient(creds, ctx.logger));
|
||||
ctx.logger.info('[matrix] uploaded credentials swapped into running ChatService');
|
||||
}
|
||||
res.json({ success: true, homeserver: creds.homeserver, userId: creds.userId });
|
||||
} catch (error) {
|
||||
ctx.logger.error('Matrix credential upload failed:', error);
|
||||
res.status(500).json({ error: String(error) });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/debug/inspect-dom', async (req, res) => {
|
||||
if (!ctx.services.chat) {
|
||||
res.status(500).json({ error: 'Chat service not initialized' });
|
||||
|
||||
Reference in new issue
Block a user