拒绝邮件通知延迟!手把手教你把 Waline 评论推送到 Gotify
前言
由于我的博客用的是静态框架 VitePress,本身是没有评论区的,需要额外引入 Waline 才能实现评论功能。
Waline 是一个支持多平台部署、多数据库以及多种通知方式的评论系统,在之前的文章《通过 Waline 给你的静态网站添加评论功能 (以 VitePress 为例)》中已经介绍过如何在静态网站中使用它了。
通知方式
尽管 Waline 支持非常多的通知方式——邮件、微信、企业微信、QQ、电报、PushPlus、Discord、飞书……几乎所有的 IM 软件都支持了,但唯独少了对自建通知方式的支持,例如 Gotify、Ntfy 之类的。
在此之前,我只配置了邮件通知方式,无论是通知我自己还是回复评论,都是通过邮件方式发送的,但在官方文档的 FAQ 中可以看到邮件通知会导致发布评论变慢。
发布评论很慢怎么办?
因为一些技术性原因,在发布评论时垃圾邮件检测、评论通知都是串联操作。
同时,如果评论的数量比较多的话,邮箱里几乎全是 Waline 的通知邮件,并且还会浪费域名邮箱的发件次数。
因此,对于博主的通知最好还是采用其他的通知渠道,只有回复访客的评论时才使用邮件通知。
实现
关闭博主邮件通知
如果你用的就是 Waline 支持的通知方式,例如 QQ、微信等,则不需要特地去关闭博主的邮件通知。
在源码中可以看到开启了其他的通知方式后,邮件通知就会自动关闭。
if ([wechat, qq, telegram, qywxAmWechat, pushplus, discord, lark].every((item) => think.isEmpty(item))) {
mailList.push({ to: AUTHOR, title, content });
}但如果没有配置这些通知方式,就需要在环境变量中把 DISABLE_AUTHOR_NOTIFY 设置为 true 才可以将博主的新评论通知关闭
危险
需要注意的是这个环境变量会关闭所有的通知渠道!
Webhook
对于 Gotify、Ntfy 这些自建的通知方式,在 Issue #2401 有提到可以通过 Webhook 发送,但文档中并没有提及怎么使用,只是简单的说明了 “评论成功后会向 WEBHOOK 配置的地址发送一条 POST 请求”,也没有具体的请求格式。
提示
Webhook 不受 DISABLE_AUTHOR_NOTIFY 控制,只要评论就会发送 POST 请求,因此需要自己实现通知过滤
翻阅源码之后,找到请求的格式如下:
fetch(WEBHOOK, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({ type, data })
}).then((resp) => resp.json());这和大多数通知软件要求的格式并不相同,以 Gotify 为例,POST 请求的格式如下:
{
"message": "**Backup** was successfully finished.",
"priority": 2,
"title": "Backup"
}转换格式
那么接下来的思路就比较清晰了,我们可以先接收 Waline 的 Webhook 请求,按照 Gotify 要求的格式修改之后,最后再通过 POST 请求发送给 Gotify。
这一需求可以把上面两种 POST 请求格式发送给 AI,让它直接实现可用的代码,然后部署到 Worker 或者云函数上。
以下是使用 Node.js 原生的 HTTP 模块实现的:
const http = require('http');
const AUTHOR_EMAIL = 'hi@zhichao.org';
const SITE_URL = 'https://zhichao.org';
const GOTIFY_URL = `http://127.0.0.1:6666`;
const PORT = 8888;
const IS_FULL = false;
function json(res, obj, code = 200) {
res.statusCode = code;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(obj));
}
http
.createServer((req, res) => {
if (req.method !== 'POST') {
res.statusCode = 405;
return res.end('only POST');
}
if (req.url === '/favicon.ico') {
return res.end('');
}
const token = req.url.slice(1);
if (!token) {
return json(res, { error: 'missing token' }, 400);
}
const REQUEST_URL = `${GOTIFY_URL}/message?token=${token}`;
let body = '';
req.on('data', (chunk) => (body += chunk));
req.on('end', async () => {
try {
const { type, data } = JSON.parse(body);
const comment = data?.comment || {};
const reply = data?.reply || null;
const mail = comment.mail;
if (mail && mail.toLowerCase() === AUTHOR_EMAIL.toLowerCase()) {
return json(res, { ignored: true });
}
const message = `
👤 评论者
${comment.nick || '匿名'} (${mail || '无'})
📝 评论内容
${comment.comment || ''}
${comment.url?.startsWith('http') ? comment.url : `${SITE_URL + comment.url || ''}`}
${
reply
? `──────回复信息──────
👤 被回复者
${reply.nick || ''} (${reply.mail || ''})
📝 原评论
${reply.comment || ''}
`
: ''
}`;
const messageFull = `
👤 评论者:${comment.nick || '匿名'} (${mail || '无'})
🌐 IP:${comment.ip || ''}
🕒 时间:${comment.createdAt || ''}
📱 UA:${comment.ua || ''}
📄 页面:${comment.url?.startsWith('http') ? comment.url : `${SITE_URL + comment.url || ''}`}
📝 评论内容:
${comment.comment || ''}
${
reply
? `──────回复信息──────
👤 被回复者:${reply.nick || ''} (${reply.mail || ''})
📝 原评论:
${reply.comment || ''}
`
: ''
}`;
await fetch(REQUEST_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: `💬 Waline 评论`,
message: IS_FULL ? messageFull : message
})
});
return json(res, { success: true });
} catch (err) {
console.error(err);
return json(res, { error: true }, 500);
}
});
})
.listen(PORT, () => {
console.log(`Webhook running on http://0.0.0.0:${PORT}`);
});假设 Waline、Gotify 以及这一段代码都运行在同一台 VPS 中,此时只需要在 Waline 添加 WEBHOOK 环境变量
WEBHOOK: http://127.0.0.1:6666/{token}最终效果就是像下图这样,当用户评论时,由于不再需要给博主发送邮件通知,评论发送的速度会快很多,同时会通过 Webhook 同步给 Gotify 发送通知,几乎零延迟!



