redmine-dingtalk-notify

SKILL开发
开发 未标注权限 许可证不明确
安装这个技能

把 Redmine 7.x 创建/更新问题自动推送到钉钉群机器人,支持 @提及。覆盖创建、备注、状态变更、负责人变更四种通知模板;处理 Redmine webhook 安全校验和钉钉加签。场景:Redmine 与钉钉集成、Redmine→钉钉群通知、按花名册 username→display_name 映射实现群内 @。触发词:Redmine 钉钉通知、redmine_dingtalk、redmine 通知、redmine 集成、Redmine webhook。

一句话选型结论

按资料字段整理

redmine-dingtalk-notify是开发类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类开发 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_3a1c97e3/redmine-dingtalk-notify
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

开发
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_3a1c97e3仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791625125
正文体量12.5 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
写代码与改 bug

按需求补代码、定位并修掉报错。

读仓库与生成改动

让模型读懂项目结构,再给出可落地的改动。

跑测试与排查故障

按现象排查问题,补测试用例并复跑。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在开发场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
redmine-dingtalk-notify当前 未标注权限 未标注 未标注 未标注 有
技能审查员 浏览器控制 ClawHub 市场 877.9 万 OpenClaw 有
Vercel React 最佳实践 浏览器控制 GitHub 仓库 849.1 万 Codex、Claude、Cursor 有
GitHub 代码协作 联网访问 ClawHub 市场 763.3 万 OpenClaw 有
网页设计指南 联网访问 GitHub 仓库 668.6 万 Codex、Claude、Cursor 有
本体论 只读 ClawHub 市场 663.7 万 OpenClaw 有

SKILL.md 全文

12.5 KB
模型实际读到的说明书原文,来自技能仓库

redmine-dingtalk-notify

Overview

把 Redmine 7.x 实例上 issue 的创建/更新事件,转译为钉钉群机器人消息,支持按花名册 username→display_name 自动 @ 提及。本 skill 是功能契约而非具体栈实现:
- 核心逻辑由三个纯函数模块实现,框架无关 (scripts/parse_payload.py / load_users.py / send_dingtalk.py)
- 入口方式留给部署方自选:
- 想要 CLI(零 Web 框架,文件/stdin/watch 三种入口):用 scripts/cli_mode.py
- 想要 HTTP webhook 入口:挑任意 Web 框架挂上三个纯函数即可
- 想要消息队列入口:同理,只需把 payload 灌给核心函数
- 花名册数据源支持 5 种内置(xlsx / txt / inline / json / csv)+ 任意自定义;不在 skill 仓库里的源(db / ldap / api)通过替换实现接入
- 所有接入参数(实例地址、token、花名册源、钉钉 webhook、加签 secret)在首次运行时通过交互式问答补齐,后续写入 config.py(不拆 .env)

何时使用本 skill

  • 用户希望把 Redmine 问题变更同步到钉钉群机器人
  • 同一组"Redmine→钉钉"逻辑要复用到多个项目、多实例、多机器人
  • 需要按花名册 username → display_name 实现群内 @ 提及
  • 旧版 Jira→钉钉 工作流改造到 Redmine→钉钉

数据流

[上游事件源]
   |  (webhook POST / 文件 / stdin / MQ)
   v
[接收入口(部署方自由选择:任何 Web 框架 / CLI / MQ 消费者)]
   |
   v
parse_payload.parse(payload) ──> 标准事件 dict
   |
   v
load_users.load_roster_from_config(cfg) ──> {username: display_name} 字典
   ↓
load_users.get_display_name(roster, assignee) ──> @ 列表
   |
   v
send_dingtalk.render_issue_card(event, ats) ──> 卡片
   |
   v
send_dingtalk.send_markdown(webhook, secret, ...) ──> 钉钉 API
   |
   v
[日志 logs/{date}.log  +  重试 / 异常分支]

运行时引导:向用户询问的关键信息

skill 触发后,模型第一步先检查 config.py 是否齐全。缺失项必须通过 AskUserQuestion 一次性向用户索齐;补齐后先回显汇总让用户确认再写入 config.py。

必填参数清单(5 项 + 1 项花名册源)

参数 说明 形如
REDMINE_BASE_URL Redmine 实例地址(不要带尾部斜杠) https://redmine.example.com
REDMINE_API_TOKEN Redmine 个人 REST API token(账户→个人资料→API 密钥) 一串十六进制字符串,直接整段粘贴
DINGTALK_WEBHOOK_URL 钉钉机器人 webhook,含 query 中的 access_token https://oapi.dingtalk.com/robot/send?access_token=XXX
DINGTALK_WEBHOOK_SECRET 加签密钥(机器人开启"加签"时才有,否则留空) SEC...
USER_ROSTER_SOURCE 花名册数据源类型(决定下面要追问哪些子字段) xlsx / txt / inline / json / csv

花名册源对应要追问的子字段

源 必追问字段 可选字段
xlsx USER_ROSTER_XLSX(路径)、USER_ROSTER_SHEET(默认 Sheet1)、USER_ROSTER_USERNAME_COL、USER_ROSTER_DISPLAYNAME_COL -
txt USER_ROSTER_TXT(路径) USER_ROSTER_TXT_DELIM、USER_ROSTER_TXT_COMMENT、USER_ROSTER_TXT_HAS_HEADER
inline USER_ROSTER_INLINE(JSON/Python 字面量字典) -
json USER_ROSTER_JSON(路径) -
csv USER_ROSTER_CSV(路径) USER_ROSTER_CSV_DELIM、USER_ROSTER_HAS_HEADER

可选参数(其它)

参数 说明 默认
REDMINE_WEBHOOK_SECRET webhook 签名校验密钥 留空不校验
DINGTALK_AT_TYPE @ 策略:all / mobiles / user_ids / assignee assignee
DINGTALK_AT_MOBILES 当 AT_TYPE=mobiles 时的逗号分隔手机号列表 ""
DINGTALK_AT_USER_IDS 当 AT_TYPE=user_ids 时的逗号分隔 user_id 列表 ""
RETRY_TIMES 推送失败重试次数 3

> 注:故意不包含 Web 框架/监听端口/内网穿透等"部署层"参数——这些由部署方在外部决定。

花名册数据源(5 种内置 + 自定义)

内置 source 矩阵

源 适用场景 字段依赖 第三方依赖
xlsx 部门/项目维护的 Excel USER_ROSTER_XLSX / SHEET / USERNAME_COL / DISPLAYNAME_COL openpyxl
txt 几行字、纯文本维护;轻量;可手写 USER_ROSTER_TXT;自动嗅探 = / | / TAB / , 分隔 无
inline 就几个固定人员,直接写在 config 里 USER_ROSTER_INLINE(JSON/Python 字面量字典) 无
json 已有 JSON 数据源,如其它系统导出 USER_ROSTER_JSON 无(用内置 json)
csv 业务侧系统已经按 CSV 维护 USER_ROSTER_CSV / CSV_DELIM / HAS_HEADER / 列名 无(用内置 csv)

自定义 source(非内置)

如果你想要 db(SQL) / ldap(公司 AD) / api(钉钉通讯录) 这些重依赖的源,有两种做法:

做法 A(替换整个模块) —— scripts/load_users.py 是个 framework-agnostic 模块,保持 load_roster_from_config(cfg) -> Dict[str, str] 签名不变,你可以直接 fork 一份改实现。skill 的其他脚本不用动。

做法 B(保留本 skill,自挂额外模块) —— 在 skill 目录外自己写 my_roster.py,在 cli_mode.py 启动前 monkey-patch load_users.load_roster_from_config 指向自己的实现。

不推荐:把 db 客户端/ldappool/requests 推到 skill 仓库里 —— 那是你的部署方环境,不该污染通用 skill。

txt 源的行格式示例

每行一条 username / display_name 记录。空行 / # 开头为注释。分隔符自动嗅探,或 USER_ROSTER_TXT_DELIM 显式指定:

# 注释行,会被忽略
alice = Alice
bob | Bob 王
carol<TAB>Carol 张
dave,Dave
eric     Eric 林        # 任意空白(空格/多空格)也支持

实现与扩展点

本 skill 提供的实现

路径 作用 框架依赖
scripts/parse_payload.py Redmine webhook payload 标准化 无
scripts/load_users.py 花名册读取(5 种 source 派发) + username → display_name 仅 xlsx 模式需 openpyxl
scripts/send_dingtalk.py 钉钉 Markdown/Text 渲染 + 加签 + POST requests
scripts/cli_mode.py 命令行入口(stdin / 文件 / watch 三种) 无 Web 框架

扩展点(常见替换)

替换目标 原实现 替换做法
HTTP 框架 暂时未内置(CLI 模式无 web) 用任意框架(如 Flask、FastAPI、aiohttp、Bottle),app.post("/webhook") 中调用 parse_payload.parse → load_users.get_display_name → send_dingtalk.send_markdown
HTTP 客户端 requests 替换为 httpx / urllib / aiohttp,只需保持 send_markdown(webhook, secret, ...) 签名不变
Excel 库 openpyxl(仅 xlsx 源需要) 替换为 pandas / pyexcel,保持 _from_xlsx 函数签名不变
花名册源类型 xlsx / txt / inline / json / csv 见上面"花名册数据源(5 种内置 + 自定义)"章节
消息类型 Markdown 卡片 替换为 ActionCard / LinkCard / FeedCard,改 send_dingtalk.py 中的 render_issue_card,签名向后兼容
推送频率 实时 加队列(RabbitMQ / Kafka / Redis Streams),消费侧调用同一核心函数
加签算法 钉钉官方 HmacSHA256 + base64 不变(公开协议)

三个纯函数签名(扩展点主参考)

from parse_payload import parse                                # payload -> event dict
from load_users import load_roster_from_config, get_display_name  # cfg -> dict, lookup -> display_name
from send_dingtalk import send_markdown, render_issue_card, DingTalkError

# 任意外部驱动代码的标准流程:
roster = load_roster_from_config(cfg)           # 1. 按 cfg["USER_ROSTER_SOURCE"] 派发数据源
event  = parse(raw_payload)                      # 2. 解析
card   = render_issue_card(event, at_names)     # 3. 渲染卡片(at_names 由 get_display_name 拼)
resp   = send_markdown(webhook, secret, card["title"], card["markdown"], ...)  # 4. 推

部署步骤(不绑任何具体栈)

0. 安装依赖

场景 依赖
仅 CLI 模式 + xlsx 花名册 pip install requests openpyxl
仅 CLI 模式 + 其他花名册源(txt/json/csv/inline) pip install requests
还要用 HTTP 入口 上述 + 你选的框架(如 pip install fastapi uvicorn)

1. 配置写入 config.py

  • 模型通过 AskUserQuestion 一次性问齐 5 项核心必填 + USER_ROSTER_SOURCE 选择的对应子项
  • 回显汇总后写入 config.py(敏感字段全部经此文件,不出现于源码)

2. 入口选择(三种)

入口 命令 / 接入方式
CLI 一次性 echo '{...}' \| python -m scripts.cli_mode
CLI 文件 python -m scripts.cli_mode payload.json
CLI watch python -m scripts.cli_mode --watch /path/to/inbox/
HTTP webhook(自选框架) 任意框架;示例骨架参见下文"5. HTTP 入口骨架"

3. 让 Redmine 能访问到入口

  • 入口必须能从公网访问,具体暴露方式由部署方决定(nat 映射 / 反向代理 / 内网穿透工具皆可;不限制具体技术)

4. 在 Redmine 项目 → 配置 → webhook

  • 新建一条 webhook,URL 对应步骤 2 选择的入口,推送内容选 JSON 完整包

5. HTTP 入口骨架(任选其一作为参考)

FastAPI 例子(非 skill 内置代码,部署方自写):

from fastapi import FastAPI, Request
from scripts.parse_payload import parse
from scripts.load_users import load_roster_from_config, get_display_name
from scripts.send_dingtalk import send_markdown, render_issue_card

app = FastAPI()
CONFIG = {...}   # 你的配置 dict,字段与 config.py.example 对应

@app.post("/redmine/webhook")
async def handle(req: Request):
    payload = await req.json()
    event = parse(payload)
    roster = load_roster_from_config(CONFIG)
    # ... 写发送逻辑(可复用 cli_mode 里的 handle_payload 函数)
    return {"ok": True}

> 不同框架的骨架差异只在 app.post(...) 这一段;核心三步(load_roster_from_config → parse → roster lookup → send_markdown)保持不变。

失败与重试

  • 网络错误 / 钉钉返回非 0 错误码 → 触发重试
  • 最多 RETRY_TIMES 次,指数退避 1s / 2s / 4s
  • 仍失败 → 写入 logs/{YYYY-MM-DD}.log,本条事件结束(不影响后续事件)

安全注意

  • config.py 内含敏感 token,不要提交到 Git;.gitignore 中加 **/config.py 与 logs/
  • 日志文件自动脱敏:access_token、SEC...、API token 仅留前 4 + *** + 后 4
  • 加签 secret 不进日志

字段说明

  • Redmine webhook payload 结构与字段差异,见 references/redmine-payload.md
  • 配置项完整列表与默认值,见 config.py.example

变更与维护

  • 修改本 skill 后,用 package_skill.py 重新打包
  • 修改脚本后,在本文件底部记录 changelog

Changelog

v0.1.2

  • 修复: scripts/cli_mode.py 启动引导文本只 print 了三步补齐方式、没列出 5 项必填字段。原因是 from config_example import INTERVIEW_QUESTIONS 找不到文件而静默吞掉。改为用 exec() 加载 config.py.example 到临时 module,从 INTERVIEW_QUESTIONS_BASE 拉字段列表输出。验证:无 config.py 时 cli_mode 启动会列出 5 项基础字段 + 提示 USER_ROSTER_SOURCE 选定后追问子项

v0.1.1

  • 修复: _from_txt 增加空白分隔嗅探(常见于手写 txt 文件如 alice Alice)
  • 修复: package_skill.py 把 logs/ 误打进 zip 的问题——删除 logs/ + 新增 .gitignore
  • 文档: SKILL.md 的 txt 示例增加 eric Eric 林 行,明示支持空白分隔
  • 验证: 在完全隔离的虚拟用户环境(.workbuddy/skills-test/ + acme-corp 团队配置 + txt 花名册源)端到端跑通,卡片 @Lily Chen 张 命中

v0.1.0

  • 初版骨架
  • scripts/parse_payload.py / load_users.py / send_dingtalk.py / cli_mode.py
  • 5 种花名册数据源派发:xlsx / txt / inline / json / csv
  • SKILL.md frontmatter + 工作流 + 引导问答 + 实现与扩展点

常见问题

5 问
答案由本站依据条目字段整理
redmine-dingtalk-notify怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_3a1c97e3/redmine-dingtalk-notify。安装方式为未标注。装完刷新技能列表或重开客户端。

redmine-dingtalk-notify支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

redmine-dingtalk-notify权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

redmine-dingtalk-notify收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

redmine-dingtalk-notify用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。