Discord
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { createRouter } from '@@/create-router';
|
||||
import {
|
||||
getServerIntegration,
|
||||
upsertServerIntegration,
|
||||
getUserIntegration,
|
||||
deleteUserIntegration,
|
||||
} from 'officerdb';
|
||||
import { startDiscordBot, stopDiscordBot, isDiscordBotRunning, getDiscordBotUsername } from './discord/bot';
|
||||
import { generatePairingCode } from './pairing';
|
||||
|
||||
export const channelsRouter = createRouter();
|
||||
|
||||
// ── Admin: Discord config ──
|
||||
|
||||
channelsRouter.get('/discord/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const integration = await getServerIntegration('discord');
|
||||
if (!integration) return ctx.json({ configured: false });
|
||||
|
||||
const config = integration.config as Record<string, unknown>;
|
||||
const botToken = config.botToken as string | undefined;
|
||||
|
||||
return ctx.json({
|
||||
configured: !!botToken,
|
||||
enabled: integration.enabled,
|
||||
botToken: botToken ? `${botToken.slice(0, 8)}...${botToken.slice(-4)}` : null,
|
||||
serverInvite: (config.serverInvite as string) ?? null,
|
||||
botHandle: (config.botHandle as string) ?? null,
|
||||
});
|
||||
});
|
||||
|
||||
channelsRouter.put('/discord/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const body = ctx.get('body') as Record<string, unknown>;
|
||||
const botToken = body.botToken as string | undefined;
|
||||
const enabled = body.enabled as boolean | undefined;
|
||||
const serverInvite = body.serverInvite as string | undefined;
|
||||
const botHandle = body.botHandle as string | undefined;
|
||||
|
||||
if (!botToken && enabled === undefined && serverInvite === undefined && botHandle === undefined) {
|
||||
return ctx.json({ error: 'At least one field required' }, 400);
|
||||
}
|
||||
|
||||
const existing = await getServerIntegration('discord');
|
||||
const existingConfig = (existing?.config ?? {}) as Record<string, unknown>;
|
||||
const newConfig = { ...existingConfig };
|
||||
if (botToken) newConfig.botToken = botToken;
|
||||
if (serverInvite !== undefined) newConfig.serverInvite = serverInvite;
|
||||
if (botHandle !== undefined) newConfig.botHandle = botHandle;
|
||||
|
||||
await upsertServerIntegration('discord', newConfig, enabled ?? existing?.enabled ?? true);
|
||||
|
||||
// Restart bot if running or if we have a token and it's enabled
|
||||
const shouldRun = enabled ?? existing?.enabled ?? true;
|
||||
const token = (botToken ?? existingConfig.botToken) as string | undefined;
|
||||
|
||||
if (token && shouldRun) {
|
||||
try {
|
||||
await startDiscordBot(token);
|
||||
} catch (err) {
|
||||
console.error('[channels] Failed to start Discord bot:', err);
|
||||
return ctx.json({ success: true, botStarted: false, error: String(err) });
|
||||
}
|
||||
return ctx.json({ success: true, botStarted: true });
|
||||
}
|
||||
|
||||
if (!shouldRun) {
|
||||
await stopDiscordBot();
|
||||
}
|
||||
|
||||
return ctx.json({ success: true, botStarted: false });
|
||||
});
|
||||
|
||||
channelsRouter.get('/discord/status', async (ctx) => {
|
||||
const integration = await getServerIntegration('discord');
|
||||
const config = (integration?.config ?? {}) as Record<string, unknown>;
|
||||
|
||||
return ctx.json({
|
||||
configured: !!config.botToken,
|
||||
enabled: integration?.enabled ?? false,
|
||||
running: isDiscordBotRunning(),
|
||||
botUsername: getDiscordBotUsername(),
|
||||
serverInvite: (config.serverInvite as string) ?? null,
|
||||
botHandle: (config.botHandle as string) ?? null,
|
||||
});
|
||||
});
|
||||
|
||||
// ── User: Discord pairing ──
|
||||
|
||||
channelsRouter.post('/discord/pair', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
const code = generatePairingCode(user.id, user.email, 'discord');
|
||||
return ctx.json({ code, expiresIn: 600 });
|
||||
});
|
||||
|
||||
channelsRouter.get('/discord/connection', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
const integration = await getUserIntegration(user.id, 'discord');
|
||||
if (!integration) return ctx.json({ linked: false });
|
||||
|
||||
const config = integration.config as Record<string, unknown>;
|
||||
return ctx.json({
|
||||
linked: true,
|
||||
discordId: config.discordId,
|
||||
});
|
||||
});
|
||||
|
||||
channelsRouter.delete('/discord/connection', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
const deleted = await deleteUserIntegration(user.id, 'discord');
|
||||
return ctx.json({ success: deleted });
|
||||
});
|
||||
Reference in New Issue
Block a user