// src/lib/monitor/wechat-pusher.ts import type { MonitorConfig } from './types' import { formatBeijingTime } from './types' const logger = { info: (msg: string) => console.log(`[Worker] ${formatBeijingTime()} INFO ${msg}`), error: (msg: string) => console.error(`[Worker] ${formatBeijingTime()} ERROR ${msg}`), } export class WeChatPusher { async pushText(text: string, webhookUrl: string): Promise { if (!webhookUrl) { logger.error('Webhook URL not configured'); return false } try { const response = await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ msgtype: 'text', text: { content: text } }), signal: AbortSignal.timeout(5_000), }) if (!response.ok) { logger.error(`Webhook HTTP ${response.status}`); return false } const result = await response.json() as { errcode?: number; errmsg?: string } if (result.errcode === 0) { logger.info('WeChat message sent'); return true } logger.error(`WeChat error: ${result.errmsg}`) return false } catch (e) { logger.error(`Webhook failed: ${e instanceof Error ? e.message : e}`) return false } } formatAvailabilityMessage( deadlines: Record, faultInfo: { server_ip: string | null; server_sn: string | null; fault_time: string | null }, isOemDiag: boolean, oemDeadline: string | null, orderNumber: string | null, rackPosition: string | null, faultDetail: string | null, ): string { let msg = '' const typeLabel = isOemDiag ? 'OEM诊断' : 'OEM维修' msg += `【服务器故障单】 - ${typeLabel}\n\n` if (orderNumber) msg += `工单号:${orderNumber}\n` msg += `服务器IP:${faultInfo.server_ip || '未知'}\n` msg += `服务器SN:${faultInfo.server_sn || '未知'}\n` msg += `机架位置:${rackPosition || '未知'}\n` if (faultInfo.fault_time) msg += `故障时间:${faultInfo.fault_time}\n` if (faultDetail) msg += `故障信息:${faultDetail}\n` if (isOemDiag && oemDeadline) { msg += `到期时间:${oemDeadline}\n` } else if (!isOemDiag) { msg += '\n📊 服务可用性各档位截止时间:\n\n' const tierDesc: Record = { '第一档': '99%(含)以上(不扣费)', '第二档': '99%-97%(含)(扣10%)', '第三档': '97%-95%(含)(扣25%)', '第四档': '95%-90%(含)(扣50%)', '第五档': '90%(不含)以下(扣100%)', } const emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣'] let i = 0 for (const [tier, desc] of Object.entries(tierDesc)) { const d = deadlines[tier] if (d) { msg += `${emojis[i]} ${desc}\n` msg += ` 截止时间:${d.deadline}` if (d.hours > 0) msg += `(${d.hours}小时)` msg += '\n\n' } i++ } } return msg.trim() } }