v0.2.4: fix ad key-words comma split + deleteAdFiles entry for extensions only

This commit is contained in:
root
2026-05-16 19:49:58 +08:00
parent e38adee8ff
commit b5d3620273
30 changed files with 1458 additions and 335 deletions

View File

@@ -5,6 +5,8 @@ import { execSync } from 'child_process';
import { adminLimiter, loginLimiter } from '../middleware/rate-limit';
import { getSaveRecords } from '../cloud/cloud.service';
import { getCloudConfigs, getCloudConfigById, saveCloudConfig, deleteCloudConfig, getCloudConfigByType, testCloudConnection, testCloudConnectionWithCookie, togglePrimary } from '../cloud/credential.service';
import { testChannel, saveConfigNotifySettings, getConfigNotifySettingsJSON, getAllNotifierParams } from '../cloud/notification.service';
import { getAllPushUsers, getPushUserById, upsertPushUser, updatePushUser, deletePushUser } from '../cloud/push-user.service';
// Note: check-in routes were removed (sign-in feature removed)
import { getAllCloudTypes } from '../cloud/cloud-types.service';
import { login, authMiddleware, verifyToken, changePassword } from '../admin/auth.service';
@@ -134,6 +136,12 @@ router.post("/admin/baidu/qr-login/:sessionId/cancel", async (req: Request, res:
// Auth wall — all routes below require JWT
// ═══════════════════════════════════════
router.use('/admin', authMiddleware);
router.use('/admin', (_req: Request, res: Response, next) => {
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
next();
});
// ═══════════════════════════════════════
// Cloud Configs CRUD
@@ -626,4 +634,104 @@ router.post('/admin/update-pansou', async (_req: Request, res: Response) => {
}
});
export default router;
/** GET /api/admin/cloud-configs/:id/notify — get per-config notification settings */
router.get('/admin/cloud-configs/:id/notify', (req: Request, res: Response) => {
try {
const id = parseInt(req.params.id as string);
const settings = getConfigNotifySettingsJSON(id);
res.json(settings);
} catch (err: any) {
res.status(400).json({ error: err.message || 'Failed to get notification settings' });
}
});
/** PUT /api/admin/cloud-configs/:id/notify — update per-config notification settings */
router.put('/admin/cloud-configs/:id/notify', (req: Request, res: Response) => {
try {
const id = parseInt(req.params.id as string);
const settings = req.body;
saveConfigNotifySettings(id, settings);
res.json({ success: true, message: '推送配置已保存' });
} catch (err: any) {
res.status(400).json({ error: err.message || 'Failed to save notification settings' });
}
});
/** POST /api/admin/notify/test — test a notification channel */
router.post('/admin/notify/test', async (req: Request, res: Response) => {
try {
const { channelType, account, configId } = req.body;
const ctx = account || (configId ? String(configId) : undefined);
const result = await testChannel(channelType as string, ctx);
res.json(result);
} catch (err: any) {
res.json({ success: false, message: err.message || '测试发送失败' });
}
});
/** GET /api/admin/notify/providers — get all available notifier providers */
router.get('/admin/notify/providers', (_req: Request, res: Response) => {
try {
const providers = getAllNotifierParams();
res.json(providers);
} catch (err: any) {
res.status(500).json({ error: err.message || 'Failed to get providers' });
}
});
/** GET /api/admin/push-users — list all push users */
router.get('/admin/push-users', (_req: Request, res: Response) => {
try {
const users = getAllPushUsers();
// Parse notify_config for each user for frontend display
const parsed = users.map(u => ({
...u,
notify_config: (() => { try { return JSON.parse(u.notify_config); } catch { return {}; } })(),
}));
res.json(parsed);
} catch (err: any) {
res.status(500).json({ error: err.message || 'Failed to list push users' });
}
});
/** POST /api/admin/push-users — create or update a push user */
router.post('/admin/push-users', (req: Request, res: Response) => {
try {
const { account, notify_config } = req.body;
if (!account) return res.status(400).json({ error: 'account is required' });
const configStr = typeof notify_config === 'string' ? notify_config : JSON.stringify(notify_config || {});
const user = upsertPushUser(account, configStr);
res.json({ ...user, notify_config: JSON.parse(user.notify_config) });
} catch (err: any) {
res.status(400).json({ error: err.message || 'Failed to save push user' });
}
});
/** PUT /api/admin/push-users/:id — update push user */
router.put('/admin/push-users/:id', (req: Request, res: Response) => {
try {
const id = parseInt(req.params.id as string);
const { account, notify_config } = req.body;
if (!account) return res.status(400).json({ error: 'account is required' });
const configStr = typeof notify_config === 'string' ? notify_config : JSON.stringify(notify_config || {});
const user = updatePushUser(id, account, configStr);
res.json({ ...user, notify_config: JSON.parse(user.notify_config) });
} catch (err: any) {
res.status(400).json({ error: err.message || 'Failed to update push user' });
}
});
/** DELETE /api/admin/push-users/:id — delete push user */
router.delete('/admin/push-users/:id', (req: Request, res: Response) => {
try {
const id = parseInt(req.params.id as string);
const ok = deletePushUser(id);
if (ok) res.json({ success: true });
else res.status(404).json({ error: 'Push user not found' });
} catch (err: any) {
res.status(400).json({ error: err.message || 'Failed to delete push user' });
}
});
export default router;