diff --git a/.github/workflows/infinity-evolution.yml b/.github/workflows/infinity-evolution.yml index db2fed5b..dad4d7f3 100644 --- a/.github/workflows/infinity-evolution.yml +++ b/.github/workflows/infinity-evolution.yml @@ -81,18 +81,21 @@ jobs: deploy-infinity) echo "部署∞版本..." # 先同步最新代码到服务器 + $SSH_CMD "mkdir -p $PROXY_DIR/.deploy-tmp" + scp -i ~/.ssh/brain_key -o StrictHostKeyChecking=no \ server/proxy/service/auto-evolution.js \ server/proxy/service/email-hub.js \ server/proxy/service/protocol-mirror.js \ server/proxy/ecosystem.brain-proxy-v3.config.js \ - ${{ secrets.ZY_BRAIN_USER }}@${{ secrets.ZY_BRAIN_HOST }}:/tmp/ + ${{ secrets.ZY_BRAIN_USER }}@${{ secrets.ZY_BRAIN_HOST }}:$PROXY_DIR/.deploy-tmp/ $SSH_CMD " - cp /tmp/auto-evolution.js $PROXY_DIR/service/ - cp /tmp/email-hub.js $PROXY_DIR/service/ - cp /tmp/protocol-mirror.js $PROXY_DIR/service/ - cp /tmp/ecosystem.brain-proxy-v3.config.js $PROXY_DIR/ + cp $PROXY_DIR/.deploy-tmp/auto-evolution.js $PROXY_DIR/service/ + cp $PROXY_DIR/.deploy-tmp/email-hub.js $PROXY_DIR/service/ + cp $PROXY_DIR/.deploy-tmp/protocol-mirror.js $PROXY_DIR/service/ + cp $PROXY_DIR/.deploy-tmp/ecosystem.brain-proxy-v3.config.js $PROXY_DIR/ + rm -rf $PROXY_DIR/.deploy-tmp mkdir -p $PROXY_DIR/data/evolution-reports cd $PROXY_DIR && pm2 startOrRestart ecosystem.brain-proxy-v3.config.js --update-env && pm2 save echo '✅ ∞版本已部署' diff --git a/server/proxy/service/auto-evolution.js b/server/proxy/service/auto-evolution.js index 4c459ab6..95b50445 100644 --- a/server/proxy/service/auto-evolution.js +++ b/server/proxy/service/auto-evolution.js @@ -372,8 +372,9 @@ async function checkTrafficPoolAlert() { const lastRun = status.schedules.traffic_alert_70.last_run; const currentPeriod = pool.period || new Date().toISOString().slice(0, 7); - // 检查本月是否已发过 - if (!lastRun || !lastRun.startsWith(currentPeriod.replace('-', '').slice(0, 6))) { + // 检查本月是否已发过 (比较YYYY-MM) + const lastRunMonth = lastRun ? lastRun.slice(0, 7) : ''; + if (lastRunMonth !== currentPeriod) { await handleTrafficAlert(Math.round(pct)); status.schedules.traffic_alert_70.last_run = new Date().toISOString(); saveEvolutionStatus(status); @@ -408,19 +409,16 @@ async function checkSchedule() { // ── 月度进化 (每月1号 00:00-00:04) ── if (day === 1 && hour === 0 && minute < 5) { const lastMonthly = status.schedules.monthly_evolution.last_run; - const today = now.toISOString().slice(0, 10); - if (!lastMonthly || !lastMonthly.startsWith(today.slice(0, 4))) { - // 进一步检查: 确保本月还没执行过 - const lastRunDate = lastMonthly ? new Date(lastMonthly) : null; - const lastRunMonth = lastRunDate ? `${lastRunDate.getFullYear()}-${String(lastRunDate.getMonth() + 1).padStart(2, '0')}` : ''; - const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`; + // 比较YYYY-MM确保本月未执行过 + const lastRunDate = lastMonthly ? new Date(lastMonthly) : null; + const lastRunMonth = lastRunDate ? `${lastRunDate.getFullYear()}-${String(lastRunDate.getMonth() + 1).padStart(2, '0')}` : ''; + const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`; - if (lastRunMonth !== currentMonth) { - try { - await monthlyEvolution(); - } catch (err) { - console.error('[自主进化] 月度进化调度异常:', err.message); - } + if (lastRunMonth !== currentMonth) { + try { + await monthlyEvolution(); + } catch (err) { + console.error('[自主进化] 月度进化调度异常:', err.message); } } } diff --git a/server/proxy/service/email-hub.js b/server/proxy/service/email-hub.js index efadd877..b53329aa 100644 --- a/server/proxy/service/email-hub.js +++ b/server/proxy/service/email-hub.js @@ -86,6 +86,15 @@ async function sendEmail(to, subject, htmlBody) { const smtpPort = 465; return new Promise((resolve, reject) => { + let settled = false; + const timeoutId = setTimeout(() => { + if (!settled) { + settled = true; + try { socket.destroy(); } catch { /* ignore */ } + reject(new Error('SMTP超时(30s)')); + } + }, 30000); + const socket = tls.connect(smtpPort, smtpHost, {}, () => { let step = 0; const from = config.smtp_user; @@ -107,20 +116,29 @@ async function sendEmail(to, subject, htmlBody) { socket.write(commands[step]); step++; } - if (step >= commands.length) { + if (step >= commands.length && !settled) { + settled = true; + clearTimeout(timeoutId); resolve(true); } }); - socket.on('error', (err) => { reject(err); }); + socket.on('error', (err) => { + if (!settled) { + settled = true; + clearTimeout(timeoutId); + reject(err); + } + }); }); - socket.on('error', (err) => { reject(err); }); - - setTimeout(() => { - try { socket.destroy(); } catch { /* ignore */ } - reject(new Error('SMTP超时(30s)')); - }, 30000); + socket.on('error', (err) => { + if (!settled) { + settled = true; + clearTimeout(timeoutId); + reject(err); + } + }); }); }