新增 `dws skill setup` 交互式安装命令,支持单产品(mono)和多产品(multi,标记为试验版)两种 skill 布局,并与开源 dws v1.0.30 命令对齐。 主要变更: - 骨架:skills/ 拆为 skills/mono/ 和 skills/multi/(29 个产品 skill),git rename 保留历史 - 命令:新增 `skill setup` cobra 子命令,支持 --mode、--target、--source、--yes,huh 交互 - multi 模式支持 -s/--skill、-x/--exclude 按产品选择 - 覆盖全部 14 个 agent home 目录(与 install.sh 一致) - 发布:install.sh / install.ps1 / post-goreleaser.sh 改读 skills/mono;dws-skills.zip 同时包含 mono 和 multi 内容;~/.dws 本地缓存 - 内容对齐:删除 8 个仅内部使用的产品 skill、dingtalk-a2a;修正 mono/multi 共 15+ 处命令引用以匹配 OSS dws v1.0.30;chat skill 从 dws-wukong 回移更新 - 漂移清理:物理删除 skill 文档中 OSS 未暴露的命令,true-fail 命令转为 caveat;--help diff 100% 覆盖审计 - 测试:新增 Layer A 静态命令调度验证 + Layer B 端到端 mock 调度验证 - 同步 main:drive 9 个命令同步到 mono/multi skill
88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
从 dt_media_upload 返回的 URL 中提取 mediaId。
|
||
|
||
用法:
|
||
python extract_media_id.py <url>
|
||
python extract_media_id.py "https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw_960_1280.png"
|
||
# 输出: @lQLPD4JNnliqBq3NBQDNA8Cw
|
||
|
||
依赖: 无(纯 Python 标准库)
|
||
|
||
典型工作流(发送图片/语音/视频消息):
|
||
# 1. 用 dt_media_upload 上传文件,获得 URL
|
||
# 2. 用本脚本从 URL 提取 mediaId
|
||
python extract_media_id.py "<dt_media_upload 返回的 URL>"
|
||
# 输出: @lQLPxxx(直接用于 --media-id 或 --pic-url 参数)
|
||
"""
|
||
|
||
import argparse
|
||
import re
|
||
import sys
|
||
from urllib.parse import urlparse
|
||
|
||
|
||
def extract_media_id(url: str) -> str:
|
||
"""从 dt_media_upload 返回的 URL 中提取 mediaId。
|
||
|
||
支持的 URL 格式示例:
|
||
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw_960_1280.png
|
||
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw.png
|
||
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw
|
||
|
||
提取规则:
|
||
1. 取 URL 路径中 /media/ 之后的部分
|
||
2. 去除尾部的 _数字_数字.扩展名 后缀(如 _960_1280.png)
|
||
3. 如果没有尺寸后缀,去除尾部的 .扩展名
|
||
4. 加上 @ 前缀
|
||
|
||
返回: @lQLPD4JNnliqBq3NBQDNA8Cw
|
||
"""
|
||
url = url.strip()
|
||
|
||
# 提取路径部分
|
||
parsed = urlparse(url)
|
||
path = parsed.path # e.g. /media/lQLPxxx_960_1280.png
|
||
|
||
# 取 /media/ 之后的部分
|
||
media_prefix = "/media/"
|
||
idx = path.find(media_prefix)
|
||
if idx == -1:
|
||
print(f"错误:URL 中未找到 /media/ 路径: {url}", file=sys.stderr)
|
||
sys.exit(1)
|
||
raw = path[idx + len(media_prefix):] # e.g. lQLPxxx_960_1280.png
|
||
|
||
if not raw:
|
||
print(f"错误:/media/ 后无内容: {url}", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
# 尝试去除 _数字_数字.扩展名 后缀(如 _960_1280.png)
|
||
match = re.match(r'^(.+?)(_\d+_\d+\.\w+)$', raw)
|
||
if match:
|
||
media_id = match.group(1)
|
||
else:
|
||
# 没有尺寸后缀,尝试去除 .扩展名
|
||
match2 = re.match(r'^(.+)\.\w+$', raw)
|
||
if match2:
|
||
media_id = match2.group(1)
|
||
else:
|
||
# 无后缀,直接使用
|
||
media_id = raw
|
||
|
||
return f"@{media_id}"
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(
|
||
description="从 dt_media_upload 返回的 URL 中提取 mediaId"
|
||
)
|
||
parser.add_argument("url", help="dt_media_upload 返回的文件 URL")
|
||
args = parser.parse_args()
|
||
|
||
media_id = extract_media_id(args.url)
|
||
print(media_id)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|