任务 ID: task-webhook-260119  |  文件: task.md  |  最后修改: 2026-02-26 16:07:24

Task task-webhook-260119 — 260119.xyz 余额预警 Webhook 接收服务

文件路径

原始需求

260119.xyz 会在余额不足时发送如下 webhook 通知:

{
  "type": "quota_exceed",
  "title": "额度预警通知",
  "content": "您的额度即将用尽,当前剩余额度为 {{value}}",
  "values": ["$0.99"],
  "timestamp": 1739950503
}

需要在服务器上起一个轻量 HTTP 服务接收此通知,收到后通过 OpenClaw message 工具通知主人(Telegram)。


执行链

reviewer → 爱衣质检


各 Agent 职责


reviewer(Ai.Rev)

职责: 审查以下方案设计,输出审查报告到 session.md,然后 sessions_send 给爱衣。

审查对象: 本文件「方案设计」章节

审查重点:
1. 安全性:端口暴露、无认证风险、SSRF/注入风险
2. 可靠性:服务崩溃后能否自动恢复、日志是否可查
3. 与 OpenClaw 集成方式是否合理(用 cron systemEvent 还是直接 shell 调 openclaw CLI)
4. 有无更简单的替代方案

输出格式:

## Ai.Rev 审查报告 — task-webhook-260119

### 总体评级:🟢/🟡/🔴

### 问题列表
- [严重度] 问题描述 → 建议修改

### 结论

完成后 sessions_send(timeoutSeconds=0):

task_id=task-webhook-260119
task=/root/.openclaw/workspace/tasks/task-webhook-260119/task.md

目标:agent:main:main


爱衣质检 SOP(固定,不修改)

  1. 读 session.md,确认 reviewer 已输出审查报告
  2. 评级 🟢 → 通知主人方案通过,附报告摘要
  3. 评级 🟡/🔴 → 通知主人需修改,列出问题

方案设计

整体架构

260119.xyz
    │ POST /webhook
    ▼
webhook-server.py(本机 127.0.0.1:18790)
    │ 收到 quota_exceed
    ▼
调用 openclaw CLI 发 Telegram 通知

组件

1. webhook-server.py

路径:/root/.openclaw/workspace/scripts/webhook-server.py

#!/usr/bin/env python3
"""
260119.xyz 余额预警 Webhook 接收服务
监听 127.0.0.1:18790,仅接受本机 nginx 反代流量
"""
from http.server import HTTPServer, BaseHTTPRequestHandler
import json, subprocess, logging, os

logging.basicConfig(
    filename='/var/log/webhook-260119.log',
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s'
)

SECRET = os.environ.get('WEBHOOK_SECRET', '')

class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path != '/webhook':
            self.send_response(404); self.end_headers(); return

        # 可选 secret 校验
        if SECRET and self.headers.get('X-Webhook-Secret') != SECRET:
            self.send_response(403); self.end_headers()
            logging.warning('invalid secret from %s', self.client_address)
            return

        length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(length)
        try:
            data = json.loads(body)
        except Exception:
            self.send_response(400); self.end_headers(); return

        self.send_response(200); self.end_headers()
        logging.info('received: %s', data)

        if data.get('type') == 'quota_exceed':
            value = data.get('values', ['?'])[0]
            content = data.get('content', '').replace('{{value}}', value)
            msg = f"⚠️ 260119.xyz 余额预警\n{content}"
            try:
                subprocess.run(
                    ['openclaw', 'send', '--to', 'telegram:92763607', msg],
                    timeout=10, check=True
                )
                logging.info('notification sent')
            except Exception as e:
                logging.error('send failed: %s', e)

    def log_message(self, *args):
        pass  # 静默 access log,只记录业务日志

if __name__ == '__main__':
    server = HTTPServer(('127.0.0.1', 18790), Handler)
    logging.info('webhook server started on 127.0.0.1:18790')
    server.serve_forever()

2. systemd 服务

路径:/etc/systemd/system/webhook-260119.service

[Unit]
Description=260119.xyz Webhook Receiver
After=network.target

[Service]
ExecStart=/usr/bin/python3 /root/.openclaw/workspace/scripts/webhook-server.py
Restart=always
RestartSec=5
Environment=WEBHOOK_SECRET=(待填写)
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

3. nginx 反代(可选,用于公网接收)

若 260119 需要公网 URL,在 nginx 加:

location /webhook-260119 {
    proxy_pass http://127.0.0.1:18790/webhook;
    proxy_set_header X-Webhook-Secret "(同上 secret)";
}

对外 URL:https://aichan.guuax.com/webhook-260119(或其他已有域名)

通知方式

openclaw send CLI 是否支持直接发消息待确认;备选方案:写一个 flag 文件,由 heartbeat 检测并通知。

待确认事项

  1. openclaw send CLI 命令格式是否正确(需 reviewer 确认或建议替代)
  2. 260119 webhook 是否支持自定义 Header(用于 secret 校验)
  3. 对外域名用哪个