← Back to Skills Marketplace
534422530

Webhook接收服务

by 534422530 · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
39
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install laosi-webhook-receiver
Description
Webhook接收 - 本地HTTP服务接收和处理webhook事件,支持日志记录、事件过滤、自动重试
README (SKILL.md)

Webhook Receiver - Webhook接收服务

激活词: webhook / 接收webhook / hook

功能

  • 本地HTTP服务接收webhook事件
  • 事件日志持久化
  • 事件类型过滤
  • 自动重试机制
  • 支持多种webhook格式(GitHub/Slack/Generic)

Python 实现

import os, json, hashlib, hmac
from datetime import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler
from typing import Callable, Dict, List, Optional

WEBHOOK_LOG = os.path.join(os.path.dirname(__file__), "webhook_logs.json")

class WebhookEvent:
    def __init__(self, headers: dict, body: str, source: str = "unknown"):
        self.headers = headers
        self.body = body
        self.source = source
        self.timestamp = datetime.now().isoformat()
        self.id = hashlib.sha256(body.encode()).hexdigest()[:16]
        self.parsed = self._parse_body()
    
    def _parse_body(self) -> dict:
        try:
            return json.loads(self.body)
        except json.JSONDecodeError:
            return {"raw": self.body[:200]}
    
    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "source": self.source,
            "timestamp": self.timestamp,
            "headers": self.headers,
            "parsed": self.parsed,
        }

class WebhookReceiver:
    def __init__(self, log_file: str = None):
        self.log_file = log_file or WEBHOOK_LOG
        self.handlers: Dict[str, Callable] = {}
        self.events: List[dict] = self._load_events()
        os.makedirs(os.path.dirname(self.log_file), exist_ok=True)
    
    def _load_events(self) -> list:
        if os.path.exists(self.log_file):
            try:
                with open(self.log_file, encoding="utf-8") as f:
                    return json.load(f).get("events", [])
            except (json.JSONDecodeError, ValueError):
                return []
        return []
    
    def _save_events(self):
        with open(self.log_file, "w", encoding="utf-8") as f:
            json.dump({"events": self.events[-500:]}, f,
                      ensure_ascii=False, indent=2)
    
    def register_handler(self, event_type: str, handler: Callable):
        """注册事件处理函数"""
        self.handlers[event_type] = handler
    
    def receive(self, event: WebhookEvent) -> dict:
        """处理接收到的webhook"""
        event_dict = event.to_dict()
        self.events.append(event_dict)
        self._save_events()
        
        result = {"received": True, "id": event.id, "source": event.source}
        
        # 查找匹配的handler
        event_type = event.parsed.get("event", "generic")
        if event_type in self.handlers:
            try:
                handler_result = self.handlers[event_type](event.parsed)
                result["handler_result"] = handler_result
                result["processed"] = True
            except Exception as e:
                result["error"] = str(e)
                result["processed"] = False
        else:
            result["processed"] = False
            result["note"] = f"No handler for event type: {event_type}"
        
        return result
    
    def verify_github_signature(self, payload: str, signature: str,
                                 secret: str) -> bool:
        """验证GitHub webhook签名"""
        expected = "sha256=" + hmac.new(
            secret.encode(), payload.encode(), hashlib.sha256
        ).hexdigest()
        return hmac.compare_digest(expected, signature)
    
    def list_events(self, source: str = None, limit: int = 20) -> list:
        """列出最近事件"""
        events = self.events
        if source:
            events = [e for e in events if e.get("source") == source]
        return events[-limit:]
    
    def get_stats(self) -> dict:
        """统计信息"""
        sources = {}
        for e in self.events:
            src = e.get("source", "unknown")
            sources[src] = sources.get(src, 0) + 1
        return {
            "total_events": len(self.events),
            "by_source": sources,
            "oldest": self.events[0]["timestamp"] if self.events else None,
            "newest": self.events[-1]["timestamp"] if self.events else None,
        }

# 使用示例
receiver = WebhookReceiver()

# 注册handler
def handle_github_push(data):
    repo = data.get("repository", {}).get("name", "unknown")
    commits = len(data.get("commits", []))
    print(f"  Push to {repo}: {commits} commits")
    return {"repo": repo, "commits": commits}

receiver.register_handler("push", handle_github_push)

# 模拟接收webhook
event = WebhookEvent(
    headers={"X-GitHub-Event": "push", "Content-Type": "application/json"},
    body=json.dumps({
        "event": "push",
        "repository": {"name": "my-repo"},
        "commits": [{"message": "feat: add webhook"}]
    }),
    source="github"
)

result = receiver.receive(event)
print(f"Event: {result['id']}, processed: {result.get('processed')}")

# 统计
stats = receiver.get_stats()
print(f"Total events: {stats['total_events']}, by source: {stats['by_source']}")

验证签名

def verify_webhook(payload, signature, secret):
    """GitHub/Stripe webhook签名验证"""
    import hmac, hashlib
    expected = "sha256=" + hmac.new(
        secret.encode(), payload.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

使用场景

  1. CI/CD: 接收GitHub/GitLab push事件触发构建
  2. 支付通知: 接收Stripe/PayPal支付成功回调
  3. 监控告警: 接收Grafana/Prometheus告警
  4. 聊天机器人: 接收Slack/Discord消息事件

依赖

  • Python 3.8+
  • 标准库(http.server, json, hashlib)
Usage Guidance
Install only if you are comfortable with webhook event logs being written locally. Avoid sending secrets in webhook headers or payloads unless you add redaction, restrict file permissions, and periodically clear or rotate the log file.
Capability Assessment
Purpose & Capability
The stated purpose is to receive, parse, filter, verify, and record webhook events; the Python example matches that purpose and uses standard-library code only.
Instruction Scope
The activation phrase includes the generic term "hook", which could invoke the skill in broader conversations, but there is no evidence of hidden or automatic execution.
Install Mechanism
The package contains a single SKILL.md file with no install scripts, bundled executables, external dependencies, or package-manager actions.
Credentials
Local file writes are proportionate for webhook logging, but webhook data can include sensitive operational or personal information.
Persistence & Privilege
The sample persists up to 500 events in webhook_logs.json, including headers and parsed payloads; this is disclosed as event persistence but lacks redaction or retention controls beyond the fixed cap.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install laosi-webhook-receiver
  3. After installation, invoke the skill by name or use /laosi-webhook-receiver
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release of the webhook-receiver skill. - Provides a local HTTP service to receive and process webhook events. - Supports event logging, event type filtering, and automatic retry mechanism. - Handles multiple webhook formats including GitHub, Slack, and generic sources. - Offers event persistence, statistics, and simple signature verification for security. - Python 3.8+ implementation using only standard library modules.
Metadata
Slug laosi-webhook-receiver
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Webhook接收服务?

Webhook接收 - 本地HTTP服务接收和处理webhook事件,支持日志记录、事件过滤、自动重试. It is an AI Agent Skill for Claude Code / OpenClaw, with 39 downloads so far.

How do I install Webhook接收服务?

Run "/install laosi-webhook-receiver" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Webhook接收服务 free?

Yes, Webhook接收服务 is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Webhook接收服务 support?

Webhook接收服务 is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Webhook接收服务?

It is built and maintained by 534422530 (@534422530); the current version is v1.0.0.

💬 Comments