huge changes
This commit is contained in:
129
routes/internalApi.js
Normal file
129
routes/internalApi.js
Normal file
@@ -0,0 +1,129 @@
|
||||
const express = require('express');
|
||||
const { CONFIG } = require('../config');
|
||||
const { applyConfigUpdates, readAllConfig } = require('../services/configPersistence');
|
||||
const { logSystem } = require('../services/debugLog');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Middleware: verify internal secret
|
||||
router.use((req, res, next) => {
|
||||
const secret = req.headers['x-internal-secret'];
|
||||
if (!CONFIG.INTERNAL_API_SECRET || secret !== CONFIG.INTERNAL_API_SECRET) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// GET /config — return all current .env values (redacted secrets)
|
||||
router.get('/config', (req, res) => {
|
||||
const map = readAllConfig();
|
||||
const obj = {};
|
||||
const REDACTED = ['DISCORD_TOKEN', 'REFRESH_TOKEN', 'GOOGLE_CLIENT_SECRET', 'MONGODB_URI', 'INTERNAL_API_SECRET', 'SETTINGS_ADMIN_PASSWORD'];
|
||||
for (const [k, v] of map) {
|
||||
obj[k] = REDACTED.includes(k) ? '••••••••' : v;
|
||||
}
|
||||
res.json(obj);
|
||||
});
|
||||
|
||||
// POST /config — apply config updates
|
||||
router.post('/config', express.json(), async (req, res) => {
|
||||
const updates = req.body;
|
||||
if (!updates || typeof updates !== 'object') {
|
||||
return res.status(400).json({ error: 'Invalid body' });
|
||||
}
|
||||
const result = applyConfigUpdates(updates);
|
||||
await logSystem('Config updated via settings UI', [
|
||||
{ name: 'Keys updated', value: result.applied.join(', ') || 'none', inline: false },
|
||||
{ name: 'Errors', value: result.errors.join(', ') || 'none', inline: false }
|
||||
]).catch(() => {});
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
// GET /discord/guild — return guild info for smart dropdowns
|
||||
router.get('/discord/guild', async (req, res) => {
|
||||
try {
|
||||
const client = require('../api/bosscordClient').getBot();
|
||||
if (!client) return res.status(503).json({ error: 'Bot not ready' });
|
||||
|
||||
const guild = client.guilds.cache.get(CONFIG.DISCORD_GUILD_ID);
|
||||
if (!guild) return res.status(404).json({ error: 'Guild not found' });
|
||||
|
||||
await guild.members.fetch().catch(() => {});
|
||||
|
||||
const channels = guild.channels.cache
|
||||
.filter(c => [0, 4, 5, 15].includes(c.type))
|
||||
.map(c => ({ id: c.id, name: c.name, type: c.type, parentId: c.parentId }))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const roles = guild.roles.cache
|
||||
.filter(r => !r.managed && r.id !== guild.id)
|
||||
.map(r => ({ id: r.id, name: r.name, color: r.hexColor }))
|
||||
.sort((a, b) => b.position - a.position);
|
||||
|
||||
const members = guild.members.cache
|
||||
.filter(m => !m.user.bot)
|
||||
.map(m => ({
|
||||
id: m.id,
|
||||
username: m.user.username,
|
||||
displayName: m.displayName,
|
||||
avatar: m.user.displayAvatarURL({ size: 32 })
|
||||
}))
|
||||
.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
||||
|
||||
const categories = guild.channels.cache
|
||||
.filter(c => c.type === 4)
|
||||
.map(c => ({ id: c.id, name: c.name }))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
res.json({ channels, roles, members, categories });
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /restart — restart the bot process
|
||||
let scheduledRestart = null;
|
||||
|
||||
router.post('/restart', express.json(), (req, res) => {
|
||||
const { mode, scheduledFor } = req.body;
|
||||
|
||||
if (mode === 'immediate') {
|
||||
res.json({ ok: true, mode });
|
||||
setTimeout(() => {
|
||||
console.log('[restart] Restarting bot process...');
|
||||
process.exit(0); // Docker/systemd will restart
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === 'scheduled' && scheduledFor) {
|
||||
const delay = new Date(scheduledFor).getTime() - Date.now();
|
||||
if (delay <= 0) return res.status(400).json({ error: 'Scheduled time is in the past' });
|
||||
if (scheduledRestart) clearTimeout(scheduledRestart);
|
||||
scheduledRestart = setTimeout(() => {
|
||||
console.log('[restart] Scheduled restart firing...');
|
||||
process.exit(0);
|
||||
}, delay);
|
||||
res.json({ ok: true, mode, scheduledFor, delayMs: delay });
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === 'cancel_scheduled') {
|
||||
if (scheduledRestart) { clearTimeout(scheduledRestart); scheduledRestart = null; }
|
||||
res.json({ ok: true, cancelled: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === 'pending') {
|
||||
res.json({ ok: true, mode: 'pending', note: 'Restart required on next manual restart' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(400).json({ error: 'Invalid mode' });
|
||||
});
|
||||
|
||||
router.get('/restart/status', (req, res) => {
|
||||
res.json({ scheduledRestart: !!scheduledRestart });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user