v0.3.5: restore full push notification system (14 channels)

Restored from v0.2.4:
- notifiers/: 14 push channels (bark/serverchan/telegram/lark/webhook/wechat/discord/smtp/...)
- push-user.service.ts: multi-user push config linked to cloud_configs.promotion_account
- notification.service.ts: full dispatcher with per-config + global fallback

New integrations:
- cloud.service.ts: notifyConfigEvent on save_success/cookie_expire/save_fail
- admin.routes.ts: 7 new API endpoints for push users, notify providers, channel test
- database.ts: migration for cloud_configs.notify_config column

How it works:
- Configure push channels in /admin/system-configs (global_notify_config JSON)
- Or per-cloud: link push_users.account = cloud_configs.promotion_account
- Notify events: save_success (green), cookie_expire (red), save_fail >=3 consecutive (yellow)
This commit is contained in:
2026-05-17 05:15:26 +08:00
parent 29e0fcbd43
commit 64b00661a2
22 changed files with 985 additions and 68 deletions

View File

@@ -0,0 +1,63 @@
/**
* notifiers/index.ts — Registry
* Unified management of all notification channels
*/
import { Notifier, NotifyParams, NotifyResult } from './notifier.types';
import { barkNotifier } from './bark.notifier';
import { serverchanNotifier } from './serverchan.notifier';
import { serverchanturboNotifier } from './serverchanturbo.notifier';
import { telegramNotifier } from './telegram.notifier';
import { larkNotifier } from './lark.notifier';
import { webhookNotifier } from './webhook.notifier';
import { wechatWorkBotNotifier } from './wechat_work_bot.notifier';
import { pushplusNotifier } from './pushplus.notifier';
import { dingtalkNotifier } from './dingtalk.notifier';
import { gotifyNotifier } from './gotify.notifier';
import { ntfyNotifier } from './ntfy.notifier';
import { discordNotifier } from './discord.notifier';
import { smtpNotifier } from './smtp.notifier';
import { qmsgNotifier } from './qmsg.notifier';
const registry = new Map<string, Notifier>();
function register(n: Notifier): void {
registry.set(n.name, n);
}
// Register all built-in notifiers
register(barkNotifier);
register(serverchanNotifier);
register(serverchanturboNotifier);
register(telegramNotifier);
register(larkNotifier);
register(webhookNotifier);
register(wechatWorkBotNotifier);
register(pushplusNotifier);
register(dingtalkNotifier);
register(gotifyNotifier);
register(ntfyNotifier);
register(discordNotifier);
register(smtpNotifier);
register(qmsgNotifier);
export function getNotifier(name: string): Notifier | undefined {
return registry.get(name);
}
export function getAllNotifiers(): Notifier[] {
return Array.from(registry.values());
}
export function getAllNotifierParams(): Record<string, { name: string; label: string; params: any[] }> {
const result: Record<string, any> = {};
for (const [name, n] of registry) {
result[name] = { name: n.name, label: n.label, params: n.params };
}
return result;
}
export async function notifyWith(name: string, params: NotifyParams): Promise<NotifyResult> {
const n = getNotifier(name);
if (!n) return { success: false, message: `Unknown channel: ${name}` };
return n.notify(params);
}