Skill: xiaoqiangclub/send-to-me (version 1.0.0)

--- name: send-to-me description: 企业微信消息发送工具。当需要发送消息、报告、通知或告警时使用，支持指定消息来源（sender）和接收人（touser）。 --- # Send To Me ## 概述 本技能用于向企业微信发送文本消息。当需要发送消息、报告、通知、告警等任何需要向我发送消息的场景时，都可以使用此技能。 > **作者微信公众号：XiaoqiangClub** <br/> > **配置教程：https://xiaoqiangclub.blog.csdn.net/article/details/144614019** ## 特点 - **使用广泛验证的 python-dotenv 库**: 稳定可靠的 .env 配置解析 - **CLI 支持**: 提供命令行工具，可直接终端调用 - **灵活配置**: 支持命令行参数、环境变量、.env 文件配置 - **美化格式**: 内置多种消息格式模板，支持 emoji 和结构化内容 - **指定接收人**: 支持通过参数或配置文件指定消息接收人 ## 快速开始 ### 1. 安装依赖 ```bash pip install python-dotenv ``` ### 2. 配置企业微信 首次使用需要配置企业微信参数，详见：[配置教程](https://xiaoqiangclub.blog.csdn.net/article/details/144614019) ```bash # 复制配置文件 cp env_example.txt .env # 编辑 .env 文件，填入你的企业微信配置 ``` ### 3. 发送消息 ```bash # 发送简单消息 python scripts/send_message.py "你好，这是一条测试消息" # 指定消息来源 python scripts/send_message.py "备份任务已完成" -s "📦 数据备份服务" # 指定接收人（发送给指定用户，多个用 | 分隔） python scripts/send_message.py "重要通知" -t "zhangsan|lisi" # 发送给部门 python scripts/send_message.py "部门通知" -p "2" # 使用格式化模板 python scripts/send_message.py "$(python -c 'from scripts.message_formatter import MessageFormatter; print(MessageFormatter.task_report("数据备份", "success", "备份完成", "文件大小: 1.2GB"))')" ``` ## 配置 ### 配置文件（推荐） 在 skill 目录下创建 `.env` 文件： ```bash WECOM_CORP_ID=your_corp_id WECOM_CORP_SECRET=your_corp_secret WECOM_AGENT_ID=your_agent_id WECOM_TOUSER=@all WECOM_SENDER=🎸 XiaoqiangClub ``` > **如何获取配置信息？请阅读：** > https://xiaoqiangclub.blog.csdn.net/article/details/144614019 ### 环境变量 ```bash # Windows set WECOM_CORP_ID=your_corp_id set WECOM_CORP_SECRET=your_corp_secret set WECOM_AGENT_ID=your_agent_id # Linux/Mac export WECOM_CORP_ID=your_corp_id export WECOM_CORP_SECRET=your_corp_secret export WECOM_AGENT_ID=your_agent_id ``` ### 命令行参数 ```bash python scripts/send_message.py "消息内容" -c corp_id -k corp_secret -a agent_id ``` ### 配置优先级 ``` 命令行参数 > 环境变量 > .env 文件 ``` ## 接收人配置 (touser / toparty / totag) 企业微信支持三种接收方式，可以组合使用： | 参数 | 说明 | 示例 | | --------- | ------------ | -------------------------------------- | | `touser` | 指定用户账号 | `zhangsan` 或 `zhangsan\|lisi\|wangwu` | | `toparty` | 指定部门 ID | `2` 或 `2\|3\|4` | | `totag` | 指定标签 ID | `1` 或 `1\|2\|3` | | `@all` | 发送给所有人 | `touser=@all` | > **注意**：touser、toparty、totag 至少要有一个非空，否则消息无法送达 ### 如何获取用户账号？ 企业微信管理后台 → 通讯录 → 查看用户的 **账号** 字段 ## 消息来源 (sender) `sender` 参数用于标识**消息的发送来源**，让接收者知道这条消息是从哪个服务/系统/应用发出的。 ### sender 命名建议 | 场景 | sender 示例 | 说明 | | ---------- | ------------------ | ---------------------- | | 定时任务 | `📦 数据备份服务` | 标识备份任务发送的消息 | | 监控系统 | `🚨 系统监控中心` | 标识监控告警消息 | | CI/CD | `🔄 CI/CD 流水线` | 标识构建/部署消息 | | 数据分析 | `📊 数据分析平台` | 标识报表消息 | | 定时脚本 | `⏰ 定时清理任务` | 标识定时任务消息 | | 通用机器人 | `🎸 XiaoqiangClub` | 通用自动发送的消息 | ### 使用示例 ```python from scripts.send_message import send_wechat_message send_wechat_message( message="备份任务已完成", sender="📦 数据备份服务" ) ``` ## 消息格式模板 本 skill 内置了 `MessageFormatter` 类，提供多种预设的消息格式： ### 1. 任务报告 (task_report) 适用于定期任务执行结果的汇报。 ```python from scripts.message_formatter import MessageFormatter message = MessageFormatter.task_report( task_name="数据备份", status="success", message="数据库备份任务已成功完成", details="备份文件: backup_2024.db\n备份大小: 1.2GB\n耗时: 5分30秒" ) ``` **输出效果：** ``` 📋 任务报告 ━━━━━━━━━━ 🏷️ 任务名称: 数据备份 📊 执行状态: ✅ SUCCESS ⏰ 执行时间: 2024-11-04 18:30:00 ━━━━━━━━━━ 📝 简要说明: 数据库备份任务已成功完成 📌 详细信息: 备份文件: backup_2024.db 备份大小: 1.2GB 耗时: 5分30秒 ``` ### 2. 任务通知 (job_notification) 适用于实时任务状态变更通知。 ```python message = MessageFormatter.job_notification( job_name="每日报表生成", event="completed", message="已生成今日报表，请查收附件。" ) ``` **输出效果：** ``` 🚀 任务通知 ━━━━━━━━━━ 📦 任务名称: 每日报表生成 📌 事件类型: 🏁 COMPLETED ⏰ 通知时间: 2024-11-04 18:30:00 ━━━━━━━━━━ 已生成今日报表，请查收附件。 ``` ### 3. 系统告警 (system_alert) 适用于系统异常或告警信息的推送。 ```python message = MessageFormatter.system_alert( level="error", title="数据库连接失败", message="主数据库连接超时，请检查网络和数据库状态。", details="1. 检查数据库服务器状态\n2. 检查防火墙规则\n3. 查看数据库日志" ) ``` **输出效果：** ``` 🚨 系统告警 ━━━━━━━━━━ ⚠️ 告警级别: 🟠 错误 ❌ 📌 告警标题: 数据库连接失败 ⏰ 发生时间: 2024-11-04 18:30:00 ━━━━━━━━━━ 📝 告警内容: 主数据库连接超时，请检查网络和数据库状态。 📌 处理建议: 1. 检查数据库服务器状态 2. 检查防火墙规则 3. 查看数据库日志 ``` ### 4. 每日汇总 (daily_summary) 适用于日报、周报等汇总信息。 ```python message = MessageFormatter.daily_summary( date="2024-11-04", stats={ "处理任务": "128 个", "成功": "125 个", "失败": "3 个", "总耗时": "2小时30分" }, highlights="- 优化了数据处理流程，处理速度提升20%\n- 修复了定时任务的时区问题" ) ``` **输出效果：** ``` 📊 每日汇总 ━━━━━━━━━━ 📅 汇总日期: 2024-11-04 ⏰ 生成时间: 2024-11-04 18:30:00 ━━━━━━━━━━ 📈 统计数据: • 处理任务: 128 个 • 成功: 125 个 • 失败: 3 个 • 总耗时: 2小时30分 ✨ 今日要点: - 优化了数据处理流程，处理速度提升20% - 修复了定时任务的时区问题 ``` ### 5. 自定义消息 (custom) 适用于灵活的自定义消息格式。 ```python message = MessageFormatter.custom( title="项目更新", content="项目开发进度报告", fields={ "当前阶段": "开发中", "完成度": "65%", "预计完成": "2024-12-01" } ) ``` **输出效果：** ``` 📌 项目更新 ━━━━━━━━━━ 项目开发进度报告 • 当前阶段: 开发中 • 完成度: 65% • 预计完成: 2024-12-01 ``` ## 命令行参数 | 参数 | 简写 | 说明 | 默认值 | | --------------- | ---- | -------------------- | ----------------- | | `message` | - | 消息内容（必填） | - | | `--sender` | `-s` | 消息发送来源 | .env 配置 | | `--corp-id` | `-c` | 企业微信 CorpID | .env 配置 | | `--corp-secret` | `-k` | 企业微信密钥 | .env 配置 | | `--agent-id` | `-a` | 企业微信应用 AgentID | .env 配置 | | `--touser` | `-t` | 接收用户 | @all 或 .env 配置 | | `--toparty` | `-p` | 接收部门 | 空 | | `--totag` | `-g` | 接收标签 | 空 | ## 代码调用 ```python from scripts.send_message import send_wechat_message success = send_wechat_message( message="任务执行完成", sender="📦 数据备份服务", touser="@all", toparty="", totag="" ) if success: print("消息发送成功") else: print("消息发送失败") ``` ## 返回值 - 发送成功: `True` - 发送失败: `False` ## 注意事项 1. 企业微信 API 有调用频率限制，请合理使用 2. touser、toparty、totag 至少要有一个非空，否则消息无法送达 3. 请妥善保管 CorpID 和 CorpSecret，不要泄露到代码仓库 4. 建议使用 `MessageFormatter` 格式化消息，可读性更好 --- **作者微信公众号：XiaoqiangClub** <br/> **配置教程：https://xiaoqiangclub.blog.csdn.net/article/details/144614019**

path: env_example.txt
content: # =============================================================================
# 企业微信消息发送配置 (WeChat Work Message Configuration)
# =============================================================================
#
# 如何获取以下配置信息？请参考配置教程：
# https://xiaoqiangclub.blog.csdn.net/article/details/144614019
#
# 作者微信公众号：XiaoqiangClub
# =============================================================================

# -----------------------------------------------------------------------------
# 必需配置 (Required Configuration)
# -----------------------------------------------------------------------------

# 企业微信 CorpID
# 作用：标识企业身份的唯一ID
# 获取方式：企业微信管理后台 -> "我的企业" -> "企业信息" -> "企业ID"
WECOM_CORP_ID=your_corp_id_here

# 企业微信应用密钥
# 作用：调用企业微信API的密钥凭证
# 获取方式：企业微信管理后台 -> "应用管理" -> 选择应用 -> "Secret"
# 注意：请妥善保管此密钥，不要泄露或提交到代码仓库
WECOM_CORP_SECRET=your_corp_secret_here

# 企业微信应用 AgentID
# 作用：指定使用哪个应用发送消息
# 获取方式：企业微信管理后台 -> "应用管理" -> 选择应用 -> 顶部显示的"AgentId"
WECOM_AGENT_ID=1000004

# -----------------------------------------------------------------------------
# 可选配置 (Optional Configuration)
# -----------------------------------------------------------------------------

# 默认接收人 (touser)
# 作用：设置默认消息接收人
# 可选值：
#   - "@all" : 发送给所有用户
#   - "user1|user2|user3" : 发送给指定用户（多个用户用 | 分隔）
#   - "部门ID" : 发送给指定部门的所有成员（需配合 toparty 使用）
# 获取用户账号：企业微信管理后台 -> "通讯录" -> 可见范围内用户的"账号"
WECOM_TOUSER=@all

# 默认接收部门 (toparty)
# 作用：设置默认接收消息的部门
# 获取方式：企业微信管理后台 -> "通讯录" -> 部门名称旁边的 ID
# 注意：touser、toparty、totag 至少要有一个非空
WECOM_TOPARTY=

# 默认接收标签 (totag)
# 作用：设置默认接收消息的标签
# 获取方式：企业微信管理后台 -> "通讯录" -> 标签 -> 标签 ID
WECOM_TOTAG=

# -----------------------------------------------------------------------------
# 发送来源标识 (Sender Configuration)
# -----------------------------------------------------------------------------
# 作用：标识消息的发送来源，让接收者知道消息来自哪个服务/系统
# 示例值：
#   - "📦 数据备份服务"  : 定时备份任务
#   - "🚨 系统监控中心"  : 监控告警通知
#   - "🔄 CI/CD 流水线"  : 持续集成/部署
#   - "📊 数据分析平台"  : 数据报表
#   - "⏰ 定时清理任务"  : 定时任务
# 注意：此配置为默认发送来源，也可通过命令行 -s 参数覆盖
WECOM_SENDER=🎸 XiaoqiangClub

# =============================================================================
# 配置说明
# =============================================================================
# 1. 复制本文件为 .env 文件：
#    cp env_example.txt .env
#
# 2. 编辑 .env 文件，填入你的企业微信配置信息
#
# 3. 确保 .env 文件不会被提交到代码仓库（已加入 .gitignore）
#
# 4. 配置优先级：命令行参数 > 环境变量 > .env 文件 > 默认值
# =============================================================================


path: scripts/message_formatter.py
content: #!/usr/bin/env python3
from datetime import datetime


class MessageFormatter:
    @staticmethod
    def task_report(
        task_name: str, status: str, message: str = "", details: str = ""
    ) -> str:
        status_emoji = {
            "success": "✅",
            "failed": "❌",
            "running": "🔄",
            "warning": "⚠️",
            "info": "ℹ️",
        }.get(status.lower(), "ℹ️")

        report = f"""📋 任务报告

━━━━━━━━━━
🏷️ 任务名称: {task_name}
📊 执行状态: {status_emoji} {status.upper()}
⏰ 执行时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
━━━━━━━━━━"""

        if message:
            report += f"\n📝 简要说明: {message}"

        if details:
            report += f"\n📌 详细信息:\n{details}"

        return report

    @staticmethod
    def job_notification(job_name: str, event: str, message: str = "") -> str:
        event_emoji = {
            "started": "🚀",
            "completed": "🏁",
            "failed": "💥",
            "scheduled": "⏰",
        }.get(event.lower(), "📌")

        return f"""🚀 任务通知

━━━━━━━━━━
📦 任务名称: {job_name}
📌 事件类型: {event_emoji} {event}
⏰ 通知时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
━━━━━━━━━━

{message}"""

    @staticmethod
    def system_alert(level: str, title: str, message: str, details: str = "") -> str:
        level_config = {
            "critical": ("🔴 严重", "🚨"),
            "error": ("🟠 错误", "❌"),
            "warning": ("🟡 警告", "⚠️"),
            "info": ("🔵 信息", "ℹ️"),
        }.get(level.lower(), ("🔵 信息", "ℹ️"))

        alert_emoji, level_text = level_config

        alert = f"""🚨 系统告警

━━━━━━━━━━
⚠️ 告警级别: {alert_emoji} {level_text}
📌 告警标题: {title}
⏰ 发生时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
━━━━━━━━━━

📝 告警内容:
{message}"""

        if details:
            alert += f"\n\n📌 处理建议:\n{details}"

        return alert

    @staticmethod
    def daily_summary(date: str = "", stats: dict = None, highlights: str = "") -> str:
        if not date:
            date = datetime.now().strftime("%Y-%m-%d")

        summary = f"""📊 每日汇总

━━━━━━━━━━
📅 汇总日期: {date}
⏰ 生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
━━━━━━━━━━"""

        if stats:
            summary += "\n\n📈 统计数据:"
            for key, value in stats.items():
                summary += f"\n  • {key}: {value}"

        if highlights:
            summary += f"\n\n✨ 今日要点:\n{highlights}"

        return summary

    @staticmethod
    def custom(title: str, content: str = "", fields: dict = None) -> str:
        msg = f"""📌 {title}

━━━━━━━━━━"""

        if content:
            msg += f"\n{content}"

        if fields:
            for key, value in fields.items():
                msg += f"\n  • {key}: {value}"

        return msg


if __name__ == "__main__":
    print(
        MessageFormatter.task_report(
            task_name="数据备份",
            status="success",
            message="数据库备份任务已成功完成",
            details="备份文件: backup_2024.db\n备份大小: 1.2GB\n耗时: 5分30秒",
        )
    )


path: scripts/send_message.py
content: #!/usr/bin/env python3
"""
企业微信消息发送工具 (WeChat Work Message Sender)

本模块提供向企业微信发送文本消息的功能，支持多种配置方式和消息格式。

配置优先级：命令行参数 > 环境变量 > .env 文件 > 默认值

依赖:
    pip install python-dotenv

作者微信公众号：XiaoqiangClub
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error
from typing import Optional

try:
    from dotenv import load_dotenv
except ImportError:
    raise ImportError(
        "缺少依赖: python-dotenv\n"
        "请运行: pip install python-dotenv\n"
        "或参考: https://xiaoqiangclub.blog.csdn.net/article/details/144614019"
    )

load_dotenv()


def get_config_value(
    key: str, default: Optional[str] = None, required: bool = False
) -> Optional[str]:
    """
    获取配置值，按优先级依次尝试：环境变量 -> .env 文件 -> 默认值

    Args:
        key: 配置键名（如 WECOM_CORP_ID）
        default: 默认值
        required: 是否为必需配置

    Returns:
        配置值字符串

    Raises:
        ValueError: 当 required=True 且无法获取有效配置时
    """
    value = os.environ.get(key) or default

    if required and (not value or value.startswith("your_")):
        raise ValueError(
            f"缺少必需配置: {key}\n"
            f"请在 .env 文件中配置或设置环境变量。\n"
            f"参考文档: https://xiaoqiangclub.blog.csdn.net/article/details/144614019"
        )

    return value


def get_access_token(corp_id: str, corp_secret: str) -> Optional[str]:
    """
    获取企业微信 Access Token

    Args:
        corp_id: 企业 ID
        corp_secret: 应用密钥

    Returns:
        成功返回 access_token，失败返回 None
    """
    try:
        token_url = (
            f"https://qyapi.weixin.qq.com/cgi-bin/gettoken"
            f"?corpid={corp_id}&corpsecret={corp_secret}"
        )
        with urllib.request.urlopen(token_url, timeout=10) as response:
            token_data = json.loads(response.read().decode("utf-8"))

        access_token = token_data.get("access_token")
        if not access_token:
            print(f"❌ 获取 AccessToken 失败: {token_data.get('errmsg')}")
            return None

        return access_token

    except urllib.error.URLError as e:
        print(f"❌ 网络请求失败: {e}")
        return None
    except Exception as e:
        print(f"❌ 获取 AccessToken 异常: {e}")
        return None


def send_wechat_message(
    message: str,
    sender: str = "",
    wecom_corp_id: Optional[str] = None,
    wecom_corp_secret: Optional[str] = None,
    wecom_agent_id: Optional[int] = None,
    touser: str = "@all",
    toparty: str = "",
    totag: str = "",
) -> bool:
    """
    发送企业微信消息

    Args:
        message: 消息内容（支持 emoji 和换行）
        sender: 发送来源标识，如 "📦 数据备份服务"
        wecom_corp_id: 企业微信 CorpID（优先使用 .env 配置）
        wecom_corp_secret: 企业微信密钥
        wecom_agent_id: 企业微信应用 AgentID
        touser: 接收消息的用户，多个用户用 | 分隔，@all 表示所有人
        toparty: 接收消息的部门 ID
        totag: 接收消息的标签 ID

    Returns:
        发送成功返回 True，失败返回 False

    Note:
        touser、toparty、totag 至少要有一个非空，否则消息无法送达
    """
    wecom_corp_id = get_config_value("WECOM_CORP_ID", wecom_corp_id, required=True)
    wecom_corp_secret = get_config_value(
        "WECOM_CORP_SECRET", wecom_corp_secret, required=True
    )
    wecom_agent_id = wecom_agent_id or int(get_config_value("WECOM_AGENT_ID", "0") or 0)

    if not wecom_agent_id:
        raise ValueError(
            "缺少必需配置: WECOM_AGENT_ID\n"
            "请在 .env 文件中配置企业微信应用 AgentID。\n"
            "参考文档: https://xiaoqiangclub.blog.csdn.net/article/details/144614019"
        )

    access_token = get_access_token(wecom_corp_id, wecom_corp_secret)
    if not access_token:
        return False

    try:
        send_url = (
            f"https://qyapi.weixin.qq.com/cgi-bin/message/send"
            f"?access_token={access_token}"
        )

        content = f"{sender}\n{message}" if sender else message

        data = {
            "touser": touser,
            "toparty": toparty,
            "totag": totag,
            "msgtype": "text",
            "agentid": wecom_agent_id,
            "text": {"content": content},
            "safe": 0,
        }

        json_data = json.dumps(data, ensure_ascii=False).encode("utf-8")
        req = urllib.request.Request(
            send_url,
            data=json_data,
            headers={"Content-Type": "application/json"},
            method="POST",
        )

        with urllib.request.urlopen(req, timeout=10) as response:
            result = json.loads(response.read().decode("utf-8"))

        if result.get("errcode") == 0:
            print("☑️ 消息发送成功")
            return True
        else:
            print(f"❌ 消息发送失败: {result.get('errmsg')}")
            return False

    except urllib.error.URLError as e:
        print(f"❌ 消息发送失败（网络错误）: {e}")
        return False
    except Exception as e:
        print(f"❌ 消息发送失败: {e}")
        return False


def main():
    """命令行入口函数"""
    parser = argparse.ArgumentParser(
        description="发送企业微信消息",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
配置说明:
  配置文件优先级: 命令行参数 > 环境变量 > .env 文件

获取配置帮助: https://xiaoqiangclub.blog.csdn.net/article/details/144614019

示例:
  python scripts/send_message.py "Hello World"
  python scripts/send_message.py "任务完成" -s "📦 备份服务"
  python scripts/send_message.py "告警" -t "zhangsan|lisi"
  python scripts/send_message.py "部门通知" -p "2"
        """,
    )

    parser.add_argument("message", nargs="?", help="消息内容（支持 emoji 和换行）")

    parser.add_argument(
        "-s",
        "--sender",
        default="",
        help="消息发送来源，如 '📦 数据备份服务'（默认使用 .env 中的配置）",
    )

    parser.add_argument(
        "-c", "--corp-id", help="企业微信 CorpID（默认使用 .env 中的配置）"
    )

    parser.add_argument(
        "-k", "--corp-secret", help="企业微信应用密钥（默认使用 .env 中的配置）"
    )

    parser.add_argument(
        "-a",
        "--agent-id",
        type=int,
        help="企业微信应用 AgentID（默认使用 .env 中的配置）",
    )

    parser.add_argument(
        "-t",
        "--touser",
        default=None,
        help="接收消息的用户账号，多个用 | 分隔（默认 @all）",
    )

    parser.add_argument("-p", "--toparty", default="", help="接收消息的部门 ID")

    parser.add_argument("-g", "--totag", default="", help="接收消息的标签 ID")

    args = parser.parse_args()

    if not args.message:
        parser.print_help()
        sys.exit(1)

    sender = args.sender or get_config_value("WECOM_SENDER", "")
    touser = args.touser or get_config_value("WECOM_TOUSER", "@all")

    success = send_wechat_message(
        message=args.message,
        sender=sender,
        wecom_corp_id=args.corp_id,
        wecom_corp_secret=args.corp_secret,
        wecom_agent_id=args.agent_id,
        touser=touser,
        toparty=args.toparty,
        totag=args.totag,
    )

    sys.exit(0 if success else 1)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)