mcpField
W
webhook-push

webhook-push

github.com/fanchouProductivity1195 installsUpdated 42w ago
Repository

About webhook-push

webhook-push is a Python skill for sending notifications to WeCom, DingTalk, and Feishu through a shared message interface. It converts supported content for each platform and includes retries for transient failures.

Key features

  1. 01Unified message format
  2. 02Text, Markdown, cards, images, and files
  3. 03Automatic platform-specific conversion
  4. 04Fallback for unsupported formats
  5. 05Exponential backoff retries
  6. 06Multi-platform and automatic sending

Use cases

  1. 01Send monitoring alerts to team chats
  2. 02Post CI/CD pipeline notifications
  3. 03Distribute reports across chat platforms
  4. 04Create incident notification workflows

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/fanchou/webhook-push --skill webhook-push

After installing, type/webhook-pushin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

pyproject.toml
CONTRIBUTING.md
.gitignore
README_CN.md
LICENSE
README.md
CHANGELOG.md
references/
platform-docs.md
webhook-push-skill-design.md
api-reference.md
webhook-push-unified-message-design.md
src/webhook_push/
__init__.py
config.py
cli.py
src/webhook_push/adapters/
__init__.py
src/webhook_push/converters/
__init__.py
src/webhook_push/models/
__init__.py
src/webhook_push/sender/
__init__.py
tests/
__init__.py
pytest.ini
test_adapters.py
test_converters.py
test_sender.py
test_cli.py
test_models.py

Details

From the project README

Webhook Push Skill

Overview

This skill provides a unified interface for sending webhook notifications to three major Chinese enterprise communication platforms:

  • WeCom (企业微信) - Enterprise WeChat by Tencent
  • DingTalk (钉钉) - Enterprise communication platform by Alibaba
  • Feishu (飞书) - Collaboration platform by ByteDance

When to Use This Skill

Use this skill when you need to:

  • Send notifications to enterprise chat groups
  • Integrate monitoring alerts into enterprise platforms
  • Automate notifications for CI/CD pipelines
  • Build incident management workflows
  • Send reports and updates to team channels
  • Create multi-platform notification systems

Core Capabilities

1. Unified Message Model

Send messages using a single, platform-agnostic interface:

from webhook_push import UnifiedMessage, MessageSender

message = UnifiedMessage(
    content={
        "type": "text",
        "body": {"text": "Deployment completed successfully!"}
    }
)

sender = MessageSender()
result = await sender.send(message, "dingtalk", webhook_url="https://oapi.dingtalk.com/robot/send?access_token=xxx")
2. Rich Message Types

Support for various message types:

  • Text - Simple text messages with @mentions
  • Markdown - Rich formatted messages
  • Image - Send images (WeCom, Feishu)
  • Link - Link cards (DingTalk)
  • Card - Interactive cards with buttons
  • File - File attachments (WeCom, Feishu)
  • Feed - Multiple link cards (DingTalk)
3. Automatic Platform Conversion

Messages are automatically converted to platform-specific formats:

# Same message works across platforms
message = UnifiedMessage(
    content={
        "type": "markdown",
        "title": "Daily Report",
        "body": {
            "content": "# Daily Stats\n- Users: 128\n- Revenue: $5,000"
        }
    }
)

# Send to all platforms automatically
result = await sender.send_auto(message)
4. Graceful Degradation

Unsupported features are automatically downgraded:

  • Cards → Markdown with links
  • Markdown → Plain text
  • Rich features → Simple alternatives
5. Retry Mechanism

Built-in exponential backoff retry logic handles transient failures.

Message Types

Text Message
message = UnifiedMessage(
    content={
        "type": "text",
        "body": {"text": "Hello, team!"},
        "mentions": [
            {"type": "mobile", "value": "13800000000", "display_name": "Zhang San"}
        ]
    }
)
Markdown Message
message = UnifiedMessage(
    content={
        "type": "markdown",
        "title": "Deployment Report",
        "body": {
            "content": """# Deployment Complete

## Status: ✅ Success
- Version: v1.2.3
- Environment: Production
- Deployed by: @zhangsan

[View Logs](https://example.com/logs)"""
        }
    }
)
Card Message

Card messages provide interactive elements with buttons and rich content. Each platform has its own card format:

WeCom Template Card (text_notice)
from webhook_push import UnifiedMessage, MessageContent

message = UnifiedMessage(
    content=MessageContent(
        type="card",
        body={
            "card_type": "text_notice",
            "title": "系统告警",
            "description": "CPU使用率超过阈值",
            "emphasis": {
                "title": "95%",
                "desc": "当前CPU使用率"
            },
            "horizontal_content_list": [
                {"keyname": "服务器", "value": "web-01"},
                {"keyname": "阈值", "value": "80%"}
            ],
            "jump_list": [
                {"type": 1, "url": "https://example.com/alerts", "title": "查看详情"}
            ],
            "action": {"type": 1, "url": "https://example.com/alerts"}
        }
    )
)

result = await sender.send(message, "wecom")
WeCom News (Article Card)
message = UnifiedMessage(
    content={
        "type": "news",
        "body": {
            "links": [
                {
                    "title": "技术分享: Webhook 最佳实践",
                    "description": "了解如何设计可靠的 webhook 系统",
                    "url": "https://example.com/article",
                    "image_url": "https://example.com/cover.jpg"
                }
            ]
        }
    }
)

result = await sender.send(message, "wecom")
DingTalk Action Card (single button)
from webhook_push import UnifiedMessage, MessageContent

message = UnifiedMessage(
    content=MessageContent(
        type="card",
        body={
            "card_type": "single",
            "config": {"hide_avatar": "0"},
            "title": "审批请求",
            "elements": [{"type": "div", "text": "您有一个新的审批请求待处理"}],
            "actions": [
                {"text": "立即审批", "url": "https://example.com/approve", "style": "positive"}
            ]
        }
    )
)

result = await sender.send(message, "dingtalk")
DingTalk Action Card (multiple buttons)
message = UnifiedMessage(
    content=MessageContent(
        type="card",
        body={
            "card_type": "multi",
            "config": {"hide_avatar": "0", "btn_orientation": "1"},
            "title": "满意度调查",
            "elements": [{"type": "div", "text": "请对本次服务进行评价"}],
            "actions": [
                {"text": "非常满意", "url": "https://example.com/survey/1", "style": "positive"},
                {"text": "满意", "url": "https://example.com/survey/2", "style": "default"},
                {"text": "不满意", "url": "https://example.com/survey/3", "style": "default"}
            ]
        }
    )
)

result = await sender.send(message, "dingtalk")
Feishu Interactive Card
message = UnifiedMessage(
    content={
        "type": "card",
        "body": {
            "config": {
                "wide_screen_mode": True,
                "enable_forward": True
            },
            "elements": [
                {
                    "tag": "div",
                    "text": {"tag": "lark_md", "content": "**审批提醒**\n您有一个新的待审批事项"}
                }
            ],
            "actions": [
                {
                    "tag": "button",
                    "text": {"tag": "plain_text", "content": "立即审批"},
                    "url": "https://example.com/approve",
                    "type": "primary"
                }
            ]
        }
    }
)

result = await sender.send(message, "feishu")
Image Message
message = UnifiedMessage(
    content={
        "type": "image",
        "body": {
            "url": "https://example.com/screenshot.png",
            "alt": "System dashboard screenshot"
        }
    }
)

Usage Patterns

Basic Pattern
from webhook_push import MessageSender, UnifiedMessage

# Create message
message = UnifiedMessage(
    content={
        "type": "text",
        "body": {"text": "Your notification message"}
    }
)

# Send to specific platform
sender = MessageSender()
result = await sender.send(
    message,
    "dingtalk",
    webhook_url="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
)

if result.success:
    print("Sent!")
else:
    print(f"Failed: {result.error}")
Multi-Platform
# Send to multiple platforms
result = await sender.send_multi(
    message,
    platforms=["wecom", "dingtalk", "feishu"],
    webhook_urls={
        "wecom": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX",
        "dingtalk": "https://oapi.dingtalk.com/robot/send?access_token=YYY",
        "feishu": "https://open.feishu.cn/open-apis/bot/v2/hook/ZZZ"
    }
)

print(f"Success: {result.success_count}, Failed: {result.failed_count}")
Automatic Selection
# Send to all configured platforms
result = await sender.send_auto(message)

print(f"Sent to: {result.sent_platforms}")
print(f"Skipped: {result.skipped_platforms}")

Platform Configuration

Enterprise WeChat
# Via webhook URL
webhook_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"

message = UnifiedMessage(content={"type": "text", "body": {"text": "Hello WeCom!"}})
await sender.send(message, "wecom", webhook_url)

Message Types: text, markdown, markdown_v2, image, news, file, voice, template_card

DingTalk
# Via webhook URL
webhook_url = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"

message = UnifiedMessage(content={"type": "markdown", "body": {"content": "Hello DingTalk!"}})
await sender.send(message, "dingtalk", webhook_url)

Message Types: text, markdown, link, actionCard, feedCard

Note: Supports signature verification for security

Feishu
# Via webhook URL
webhook_url = "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_ID"

# With signature verification (recommended)
from webhook_push import FeishuAdapter

adapter = FeishuAdapter(
    webhook_id="YOUR_ID",
    secret="YOUR_SECRET"  # Enable signature verification
)

message = UnifiedMessage(content={"type": "text", "body": {"text": "Hello Feishu!"}})
await sender.send(message, "feishu", webhook_url)

Message Types: text, post, image, file, card, audio

Note: Supports HMAC-SHA256 signature verification for enhanced security (recommended)

Environment Variables

# Optional: Configure default platforms
WECOM_WEBHOOK_KEY=your-key
DINGTALK_ACCESS_TOKEN=your-token
DINGTALK_SECRET=your-secret
FEISHU_WEBHOOK_ID=your-id
FEISHU_SECRET=your-secret  # Optional, for signature verification

CLI Usage

# Send a text message
webhook-push send dingtalk "https://oapi.dingtalk.com/robot/send?access_token=xxx" \
    --content "Hello from CLI!"

# Send a markdown message
webhook-push send wecom "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx" \
    --type markdown \
    --title "Report" \
    --content "# Daily Report\n- Metrics here"

# Send to multiple platforms
webhook-push send-multi wecom dingtalk --content "Notification"

# Send to all available platforms
webhook-push send-auto --content "All platforms"

# Show platform info
webhook-push info dingtalk

Best Practices

1. Use Markdown for Rich Content

Markdown provides the best compatibility across platforms:

message = UnifiedMessage(
    content={
        "type": "markdown",
        "body": {
            "content": """# Report

## Summary
- Metric 1: **128**
- Metric 2: 3,421

> Last updated: 18:00"""
        }
    }
)
2. Handle Failures Gracefully
result = await sender.send(message, "dingtalk", webhook_url)

if not result.success:
    if result.retry_suggested:
        # Retry later or queue for retry
        await retry_queue.add(message)
    else:
        # Log the error
        logger.error(f"Send failed: {result.error}")
3. Use Card Messages for Actions

Cards with buttons provide better user experience:

message = UnifiedMessage(
    content={
        "type": "card",
        "body": {
            "card_type": "interactive",
            "elements": [{"type": "div", "text": "Review required"}],
            "actions": [
                {"type": "button", "text": "Approve", "url": "...", "style": "primary"},
                {"type": "button", "text": "Reject", "url": "..."}
            ]
        }
    }
)
4. Monitor Rate Limits

Each platform has different rate limits:

PlatformRate Limit
WeCom20/min
DingTalk20/min
Feishu~100/min

The sender automatically handles rate limit errors.

Advanced Features

Custom Retry Policy
from webhook_push import MessageSender, RetryPolicy, SenderOptions

options = SenderOptions(
    retry_policy=RetryPolicy(
        max_retries=5,
        initial_delay=1000,
        max_delay=30000,
        backoff_multiplier=2.0
    )
)

sender = MessageSender(options)
Message Deduplication

Use message_id for deduplication:

message = UnifiedMessage(
    metadata={"message_id": "unique-id-123"},
    content={"type": "text", "body": {"text": "Same message"}}
)
Correlation Tracking

Use correlation_id to track related messages:

message = UnifiedMessage(
    metadata={"correlation_id": "deployment-123"},
    content={"type": "markdown", "body": {"content": "Deployment update"}}
)

Error Handling

Common error codes:

CodeMeaningAction
UNKNOWN_PLATFORMInvalid platform nameCheck platform name
UNSUPPORTEDPlatform doesn't support message typeUse different message type
RATE_LIMITToo many requestsWait and retry
NETWORK_ERRORNetwork failureRetry later
PLATFORM_ERRORPlatform returned errorCheck error message

Performance Tips

  1. Use send_multi for sending to multiple platforms
  2. Use send_auto to leverage all available platforms
  3. Configure timeouts for long-running operations
  4. Monitor rate limits for high-volume scenarios

Dependencies

  • Python 3.9+
  • httpx (HTTP client)
  • pydantic (Data validation)
  • tenacity (Retry logic)

See pyproject.toml for full dependencies.

References

Comments

Markdown supported