vault backup: 2026-11-09 09:52:30
This commit is contained in:
1 parent
5022dc27b2
commit
d58a4b3fa9
4 files changed
+88
-8
No files matched your search
+44
-4
@@ -27,12 +27,52 @@ async function postJson(url, payload, headers = {}) {
|
||||
async function sendWebhook(hook, title, text, extra) {
|
||||
const type = (hook.type || 'custom').toLowerCase();
|
||||
// url 支持 "env:变量名" —— 密钥不落在配置文件里(Obsidian 库会同步/进 Git)
|
||||
const url = typeof hook.url === 'string' && hook.url.startsWith('env:')
|
||||
? process.env[hook.url.slice(4)]
|
||||
: hook.url;
|
||||
if (!url) throw new Error('webhook.url 为空(或 env: 指定的环境变量未设置)');
|
||||
const rawUrl = hook.url;
|
||||
const url = typeof rawUrl === 'string' && rawUrl.startsWith('env:')
|
||||
? process.env[rawUrl.slice(4)]
|
||||
: rawUrl;
|
||||
const needsUrl = !['wecomapp', 'email'].includes(type);
|
||||
if (needsUrl && !url) throw new Error('webhook.url 为空(或 env: 指定的环境变量未设置)');
|
||||
|
||||
switch (type) {
|
||||
case 'wecomapp': { // 企业微信自建应用:推给自己单聊,需管理员在后台建应用
|
||||
const secret = hook.corpsecret && hook.corpsecret.startsWith('env:')
|
||||
? process.env[hook.corpsecret.slice(4)]
|
||||
: hook.corpsecret;
|
||||
if (!hook.corpid || !secret || !hook.agentid) throw new Error('wecomapp 需要 corpid / corpsecret / agentid');
|
||||
const tr = await fetch(`https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${encodeURIComponent(hook.corpid)}&corpsecret=${encodeURIComponent(secret)}`, { signal: AbortSignal.timeout(10000) });
|
||||
const tj = await tr.json();
|
||||
if (!tj.access_token) throw new Error(`gettoken 失败: ${tj.errcode} ${tj.errmsg}`);
|
||||
return postJson(`https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${tj.access_token}`, {
|
||||
touser: hook.touser || '@all',
|
||||
msgtype: 'text',
|
||||
agentid: Number(hook.agentid),
|
||||
text: { content: `${title}\n${text}` },
|
||||
safe: 0
|
||||
});
|
||||
}
|
||||
|
||||
case 'email': { // 邮件:QQ/163 等 SMTP,微信里能收到邮件提醒
|
||||
const pass = hook.passEnv ? process.env[hook.passEnv] : hook.pass;
|
||||
if (!hook.smtp || !hook.from || !hook.to) throw new Error('email 需要 smtp / from / to');
|
||||
if (!pass) throw new Error('email 缺少密码/授权码');
|
||||
const ps1 = path.join(__dirname, 'send-mail.ps1');
|
||||
const args = [
|
||||
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', ps1,
|
||||
'-Smtp', hook.smtp, '-Port', String(hook.port || 465),
|
||||
'-From', hook.from, '-To', hook.to,
|
||||
'-User', hook.user || hook.from, '-Pass', pass,
|
||||
'-Subject', title, '-Body', text
|
||||
];
|
||||
const code = await new Promise((res, rej) => {
|
||||
try {
|
||||
execFile('powershell', args, { windowsHide: true }, (err) => res(err ? (err.code ?? 1) : 0));
|
||||
} catch (e) { rej(e); }
|
||||
});
|
||||
if (code !== 0) throw new Error(`Send-MailMessage 失败 (exit ${code})`);
|
||||
return { status: 200, text: 'smtp ok' };
|
||||
}
|
||||
|
||||
case 'feishu': // 飞书自定义机器人
|
||||
return postJson(url, { msg_type: 'text', content: { text: `${title}\n${text}` } });
|
||||
|
||||
|
||||
Reference in new issue
Block a user