
Dingtalk Ai Table
- 596 installs
- 97 repo stars
- Updated June 26, 2026
- breath57/dingtalk-skills
dingtalk-ai-table is an agent skill that reads, writes, and updates structured tables in DingTalk for developers who need AI-driven automation against DingTalk workplace data.
About
dingtalk-ai-table is a breath57/dingtalk-skills agent integration listed on skills.sh with 513 installs that lets coding agents interact with DingTalk AI Tables. Agents can read rows, write new records, and update existing structured table data inside DingTalk workflows without bespoke API clients for every automation script. Developers reach for dingtalk-ai-table when building internal bots, approval flows, or ops automations that must sync with DingTalk spreadsheets used by teams in China-centric enterprise chat environments. The skill targets agent-tooling scenarios where table state is the system of record for lightweight business processes.
- Agent skill that connects Claude, Cursor and other LLMs directly to DingTalk AI tables
- Supports reading table data, creating records, and updating cells via natural language
- Exposes structured data operations as MCP-compatible tools
- 513 developers have installed this integration
- Designed for Chinese enterprise collaboration environments using DingTalk
Dingtalk Ai Table by the numbers
- 596 all-time installs (skills.sh)
- Ranked #1,595 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/breath57/dingtalk-skills --skill dingtalk-ai-tableAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 596 |
|---|---|
| repo stars | ★ 97 |
| Last updated | June 26, 2026 |
| Repository | breath57/dingtalk-skills ↗ |
How do agents read and write DingTalk AI tables?
Let their AI coding agent read from, write to, and update structured tables inside DingTalk for automated workflows.
Who is it for?
Developers building agent automations that must sync operational data with DingTalk AI Tables in enterprise chat environments.
Skip if: Teams outside DingTalk ecosystems, heavy relational database migrations, or products with no DingTalk workplace dependency.
When should I use this skill?
A developer asks an agent to read, write, or update structured DingTalk AI Table records in an automated workflow.
What you get
Agent-driven DingTalk AI Table reads, inserts, and row updates inside DingTalk automated workflows.
- Table row reads
- Table row writes
- Automated table updates
By the numbers
- 513 installs per skills.sh listing in readme excerpt
- skills.sh rank 9370 for dingtalk-ai-table slug
Files
钉钉 AI 表格技能
负责钉钉 AI 表格(.able 格式多维表格)的所有操作。本文件为策略指南,仅包含决策逻辑和工作流程。完整 API 请求格式见文末「references/api.md 查阅索引」。
核心概念
- AI 表格(
.able文件):多维表格,使用 Notable API(/v1.0/notable),不是普通电子表格 - base_id:AI 表格文件的 nodeId,从分享链接
https://alidocs.dingtalk.com/i/nodes/<base_id>提取 - 工作表(Sheet):表格内的单张表,包含字段和记录
- 字段(Field):列定义,有名称和类型(
text、number、date) - 记录(Record):数据行,
fields中用字段名称(非 ID)作键 - operatorId:所有接口必须的 unionId 参数,通过
dt_helper.sh --to-unionid自动转换
工作流程(每次执行前)
1. 先识别本次任务类型 → 例如:列工作表、创建字段、查询记录、更新记录、删除记录 2. 按本次任务校验所需配置 → 通过 bash scripts/dt_helper.sh --get KEY 读取;仅校验本任务必须项 3. 仅收集缺失配置 → 若缺少某项,一次性询问用户所有缺失值,用 bash scripts/dt_helper.sh --set KEY=VALUE 写入 4. 获取 Token / operatorId → 直接调用 bash scripts/dt_helper.sh,token 获取与缓存细节无需关心 5. 执行操作 → 凡是包含变量替换、管道或多行逻辑的命令,写入 /tmp/<task>.sh 再 bash /tmp/<task>.sh 执行。不要把多行命令直接粘到终端里(终端工具会截断),也不要用 <<'EOF' 语法(heredoc 在工具中同样会被截断导致变量丢失)
按任务校验配置(必须先做)
- 所有任务通用必需:
DINGTALK_APP_KEY、DINGTALK_APP_SECRET、DINGTALK_MY_USER_ID - 涉及任何 AI 表格 API 调用:必须有
DINGTALK_MY_OPERATOR_ID(若缺失,先用bash scripts/dt_helper.sh --to-unionid自动转换并写回) - 工作表/字段/记录相关操作:必须有
DINGTALK_AI_TABLE_BASE_ID(若缺失,要求用户提供 AI 表格链接并提取/nodes/<base_id>)
规则:未通过“本次任务配置校验”前,不得进入 API 调用步骤。
凭证禁止在输出中完整打印,确认时仅显示前 4 位 + ****所需配置
| 配置键 | 必填 | 说明 | 如何获取 |
|---|---|---|---|
DINGTALK_APP_KEY | ✅ | 应用 AppKey | 钉钉开放平台 → 应用管理 → 凭证信息 |
DINGTALK_APP_SECRET | ✅ | 应用 AppSecret | 同上 |
DINGTALK_MY_USER_ID | ✅ | 当前用户的企业员工 ID(userId) | 管理后台 → 通讯录 → 成员管理 → 点击姓名查看 |
DINGTALK_MY_OPERATOR_ID | ✅ | 当前用户的 unionId(operatorId) | 首次由 bash scripts/dt_helper.sh --to-unionid 自动转换并写入 |
DINGTALK_AI_TABLE_BASE_ID | ✅ | AI 表格的 nodeId | 从 AI 表格分享链接 /nodes/<id> 提取 |
身份标识说明
| 标识 | 说明 |
|---|---|
userId(= staffId) | 企业内部员工 ID,可通过管理后台 -> 通讯录 -> 成员管理 -> 点击姓名查看 |
unionId | 跨企业/跨应用唯一标识,可通过 bash scripts/dt_helper.sh --to-unionid <userid> 获取 |
执行脚本模板
#!/bin/bash
set -e
HELPER="./scripts/dt_helper.sh"
NEW_TOKEN=$(bash "$HELPER" --token)
OPERATOR_ID=$(bash "$HELPER" --get DINGTALK_MY_OPERATOR_ID)
BASE_ID=$(bash "$HELPER" --get DINGTALK_AI_TABLE_BASE_ID)
# 在此追加具体 API 调用,例如列出工作表:
SHEETS=$(curl -s -X GET "https://api.dingtalk.com/v1.0/notable/bases/${BASE_ID}/sheets?operatorId=${OPERATOR_ID}" \
-H "x-acs-dingtalk-access-token: $NEW_TOKEN")
echo "工作表列表: $SHEETS"Token 失效处理:dt_helper 仅按时间缓存,无法感知 token 被提前吊销。若 API 返回 401(token 无效/过期),用 --nocache 跳过缓存强制重新获取:```bash
NEW_TOKEN=$(bash "$HELPER" --token --nocache)
```
references/api.md 查阅索引
确定好要做什么之后,用以下命令从 references/api.md 中提取对应章节的完整 API 细节(请求格式、参数说明、返回值示例):
grep -A 20 "^## 1. 列出工作表" references/api.md
grep -A 15 "^## 2. 查询单个工作表" references/api.md
grep -A 30 "^## 3. 创建工作表" references/api.md
grep -A 15 "^## 4. 删除工作表" references/api.md
grep -A 25 "^## 5. 列出字段" references/api.md
grep -A 28 "^## 6. 创建字段" references/api.md
grep -A 15 "^## 7. 更新字段" references/api.md
grep -A 15 "^## 8. 删除字段" references/api.md
grep -A 25 "^## 9. 新增记录" references/api.md
grep -A 40 "^## 10. 查询记录列表" references/api.md
grep -A 18 "^## 11. 更新记录" references/api.md
grep -A 15 "^## 12. 删除记录" references/api.md
grep -A 10 "^## 错误码" references/api.md
grep -A 6 "^## 所需应用权限" references/api.mddingtalk-ai-table API 参考
所有接口均已验证可用。钉钉 AI 表格(.able 文件)使用 Notable API,与普通电子表格 API 完全不同。NEW_TOKEN= 新版 token(api.dingtalk.com用),获取方式bash scripts/dt_helper.sh --token
OPERATOR_ID= 用户 unionId,获取方式bash scripts/dt_helper.sh --get DINGTALK_MY_OPERATOR_ID
{base_id}= AI 表格文件的 nodeId(从分享链接/nodes/<nodeId>提取)
---
1. 列出工作表
GET https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}无请求体。
响应:
{
"value": [
{ "id": "HAcL4SD", "name": "项目" },
{ "id": "nr2iEiW", "name": "任务" }
]
}---
2. 查询单个工作表
GET https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}无请求体。
响应:
{ "id": "HAcL4SD", "name": "项目" }---
3. 创建工作表
POST https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{
"name": "新工作表",
"fields": [
{ "name": "标题", "type": "text" },
{ "name": "数量", "type": "number" }
]
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | ✅ | 工作表名称 |
fields | array | ❌ | 初始字段定义,省略则创建空工作表 |
响应:
{ "id": "zHTWNlh", "name": "新工作表" }---
4. 删除工作表
DELETE https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}无请求体。
响应:{ "success": true }
⚠️ 不可恢复,执行前需用户确认。
---
5. 列出字段
GET https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/fields?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}无请求体。
响应:
{
"value": [
{ "id": "6mNRNHb", "name": "标题", "type": "text" },
{ "id": "BDGLCo2", "name": "截止日期", "type": "date", "property": { "formatter": "YYYY-MM-DD" } },
{ "id": "mr8APlG", "name": "数量", "type": "number", "property": { "formatter": "INT" } }
]
}---
6. 创建字段
POST https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/fields?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{
"name": "字段名称",
"type": "number"
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | ✅ | 字段名称 |
type | string | ✅ | 字段类型:text(文本)、number(数字)、date(日期) |
响应:
{
"id": "mr8APlG",
"name": "字段名称",
"type": "number",
"property": { "formatter": "INT" }
}---
7. 更新字段
PUT https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/fields/{field_id}?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{ "name": "新字段名称" }响应:{ "id": "fieldId" }
仅返回 id,通过重新查询字段列表确认名称已变更。
---
8. 删除字段
DELETE https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/fields/{field_id}?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}无请求体。
响应:{ "success": true }
⚠️ 删除字段会同时删除该列所有数据,执行前需用户确认。
---
9. 新增记录
POST https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/records?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{
"records": [
{ "fields": { "标题": "任务一", "数量": 3 } },
{ "fields": { "标题": "任务二", "数量": 5 } }
]
}fields 中使用字段名称(非 ID)作为键。先用「5. 列出字段」确认现有字段名。响应:
{
"value": [
{ "id": "RNXU1Vm2L2" },
{ "id": "LK0kdIxCQU" }
]
}---
10. 查询记录列表
POST https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/records/list?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{
"maxResults": 20,
"nextToken": ""
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
maxResults | int | ❌ | 每页数量,默认 20 |
nextToken | string | ❌ | 分页令牌,首次为空 |
响应:
{
"records": [
{
"id": "RNXU1Vm2L2",
"fields": { "标题": "任务一", "数量": 3 },
"createdTime": 1772723541439,
"createdBy": { "unionId": "xxx" },
"lastModifiedTime": 1772723541439,
"lastModifiedBy": { "unionId": "xxx" }
}
],
"hasMore": false,
"nextToken": ""
}翻页:hasMore=true时,将nextToken传入下次请求继续获取。
---
11. 更新记录
PUT https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/records?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{
"records": [
{ "id": "RNXU1Vm2L2", "fields": { "标题": "新标题" } }
]
}只传需要修改的字段,未传字段保持不变。
响应:{ "value": [{ "id": "RNXU1Vm2L2" }] }
---
12. 删除记录
POST https://api.dingtalk.com/v1.0/notable/bases/{base_id}/sheets/{sheet_id}/records/delete?operatorId={OPERATOR_ID}
Header: x-acs-dingtalk-access-token: {NEW_TOKEN}请求体:
{ "recordIds": ["RNXU1Vm2L2", "LK0kdIxCQU"] }响应:{ "success": true }
---
错误码
| code | 说明 | 处理建议 |
|---|---|---|
invalidRequest.document.notFound | base_id 无效或无访问权限 | 确认 AI 表格 nodeId 正确,且 operatorId 对应用户有权限 |
Forbidden.AccessDenied | 应用未开通所需权限 | 在开发者后台开通 Notable 相关权限 |
InvalidParameter | 请求参数格式有误 | 检查 fields key 是字段名称而非 ID |
429 TooManyRequests | 触发限流 | 等待 1s 后重试 |
---
所需应用权限
| 权限名称 | 说明 |
|---|---|
Document.Notable.Read | 读取 AI 表格数据 |
Document.Notable.Write | 写入 / 修改 AI 表格数据 |
#!/bin/bash
# =============================================================================
# dt_helper.sh — 钉钉开放平台辅助工具
# 路径: scripts/common/dt_helper.sh
# 用法: bash scripts/common/dt_helper.sh <命令> [参数]
# =============================================================================
set -e
CONFIG="${DINGTALK_CONFIG:-$HOME/.dingtalk-skills/config}"
# ─────────────────────────────────────────────────────────────────────────────
# 帮助信息
# ─────────────────────────────────────────────────────────────────────────────
show_help() {
cat <<'EOF'
钉钉开放平台辅助工具 (dt_helper.sh)
用法: bash scripts/common/dt_helper.sh <命令> [参数]
Token 管理(两种 token 互不兼容,按域名区分):
--token [--nocache] 获取新版 accessToken(用于 api.dingtalk.com 域名的所有接口)
适用:待办、文档、AI 表格等 api.dingtalk.com 域名下所有版本的接口
请求头:x-acs-dingtalk-access-token: <token>
有缓存且未过期则直接返回,否则自动刷新并缓存
--nocache:跳过缓存,强制重新获取(token 被提前吊销时使用)
--token-info 查看新版 token 缓存状态(是否有效、剩余有效秒数)
--clear-token 清除缓存的新版 token(下次 --token 时强制重新获取)
--old-token [--nocache]
获取旧版 access_token(用于 oapi.dingtalk.com 域名的所有接口)
适用:群消息/工作通知/userId↔unionId 转换等 oapi.dingtalk.com 接口
不适用:api.dingtalk.com 接口(如待办、文档、AI表格)
⚠️ 新旧两种 token 互不兼容,混用会导致 401/403
--nocache:跳过缓存,强制重新获取(token 被提前吊销时使用)
身份转换:
--to-unionid [userId] 将 userId 转换为 unionId
不传参数:转换配置中的 DINGTALK_MY_USER_ID(操作者自身),
结果首次自动写入 DINGTALK_MY_OPERATOR_ID
传入参数:动态转换指定 userId,仅返回结果,不写入配置
--to-userid [unionId] 将 unionId 反向转换为 userId(需传入参数)
配置管理:
--config 查看 ~/.dingtalk-skills/config 中的所有配置项(敏感项脱敏显示)
--get KEY [KEY...] 获取一个或多个配置项的值(敏感项脱敏显示)
--set KEY=VALUE 将配置项持久化写入配置文件(已存在则更新,不存在则追加,目录自动创建)
帮助:
--help, -h 显示此帮助信息
环境变量:
DINGTALK_CONFIG 覆盖默认配置文件路径(默认 ~/.dingtalk-skills/config)
配置文件:
~/.dingtalk-skills/config key=value 格式,存储以下键:
DINGTALK_APP_KEY 应用 Client ID(AppKey)
DINGTALK_APP_SECRET 应用 Client Secret(AppSecret)
DINGTALK_MY_USER_ID 企业员工 ID(userId,管理后台通讯录可查)
DINGTALK_MY_OPERATOR_ID 操作者 unionId(由 --to-unionid 自动生成)
DINGTALK_ACCESS_TOKEN 新版 token 缓存
DINGTALK_TOKEN_EXPIRY 新版 token 过期时间戳(Unix 秒)
DINGTALK_OLD_TOKEN 旧版 token 缓存
DINGTALK_OLD_TOKEN_EXPIRY 旧版 token 过期时间戳(Unix 秒)
EOF
}
# ─────────────────────────────────────────────────────────────────────────────
# 工具函数
# ─────────────────────────────────────────────────────────────────────────────
# 从配置文件读取指定键的值
cfg_get() {
local key="$1"
grep "^${key}=" "$CONFIG" 2>/dev/null | head -1 | cut -d= -f2-
}
# 写入或更新配置文件中的键值
cfg_set() {
local key="$1"
local value="$2"
mkdir -p "$(dirname "$CONFIG")"
touch "$CONFIG"
if grep -q "^${key}=" "$CONFIG" 2>/dev/null; then
sed -i "s|^${key}=.*|${key}=${value}|" "$CONFIG"
else
echo "${key}=${value}" >> "$CONFIG"
fi
}
# 从配置文件删除指定键
cfg_del() {
local key="$1"
sed -i "/^${key}=/d" "$CONFIG" 2>/dev/null || true
}
# 确保必须的配置项存在,否则报错退出
require_cfg() {
local key="$1"
local val
val=$(cfg_get "$key")
if [ -z "$val" ]; then
echo "❌ 缺少配置项 ${key},请先运行: bash scripts/common/dt_helper.sh --set ${key}=<值>" >&2
exit 1
fi
echo "$val"
}
# ─────────────────────────────────────────────────────────────────────────────
# Token 管理
# ─────────────────────────────────────────────────────────────────────────────
cmd_token() {
local force="${1:-}" app_key app_secret cached expiry now resp token expire_in
app_key=$(require_cfg DINGTALK_APP_KEY)
app_secret=$(require_cfg DINGTALK_APP_SECRET)
now=$(date +%s)
if [ "$force" != "--nocache" ]; then
cached=$(cfg_get DINGTALK_ACCESS_TOKEN)
expiry=$(cfg_get DINGTALK_TOKEN_EXPIRY)
if [ -n "$cached" ] && [ -n "$expiry" ] && [ "$now" -lt "$expiry" ]; then
echo "$cached"
return 0
fi
fi
# 过期或无缓存,重新获取
resp=$(curl -s -X POST "https://api.dingtalk.com/v1.0/oauth2/accessToken" \
-H "Content-Type: application/json" \
-d "{\"appKey\":\"${app_key}\",\"appSecret\":\"${app_secret}\"}")
token=$(echo "$resp" | grep -o '"accessToken":"[^"]*"' | cut -d'"' -f4)
expire_in=$(echo "$resp" | grep -o '"expireIn":[0-9]*' | cut -d: -f2)
if [ -z "$token" ]; then
echo "❌ 获取 token 失败: $resp" >&2
exit 1
fi
cfg_set DINGTALK_ACCESS_TOKEN "$token"
cfg_set DINGTALK_TOKEN_EXPIRY "$((now + expire_in - 200))"
echo "$token"
}
cmd_token_info() {
local cached expiry now remaining
cached=$(cfg_get DINGTALK_ACCESS_TOKEN)
expiry=$(cfg_get DINGTALK_TOKEN_EXPIRY)
now=$(date +%s)
if [ -z "$cached" ]; then
echo "状态: 无缓存(从未获取或已清除)"
return 0
fi
if [ -z "$expiry" ] || [ "$now" -ge "$expiry" ]; then
echo "状态: 已过期"
echo "Token: ${cached:0:20}..."
else
remaining=$((expiry - now))
echo "状态: 有效"
echo "Token: ${cached:0:20}..."
echo "剩余: ${remaining} 秒(约 $((remaining / 60)) 分钟)"
fi
}
cmd_clear_token() {
cfg_del DINGTALK_ACCESS_TOKEN
cfg_del DINGTALK_TOKEN_EXPIRY
echo "✅ 新版 Token 缓存已清除"
}
cmd_old_token() {
# 旧版 access_token,用于所有 oapi.dingtalk.com 接口:
# - 群消息、工作通知、互动卡片(dingtalk-message)
# - userId ↔ unionId 转换
# ⚠️ 不可用于 api.dingtalk.com 接口(待办、文档、AI表格等)
local force="${1:-}" app_key app_secret resp token cached expiry now
app_key=$(require_cfg DINGTALK_APP_KEY)
app_secret=$(require_cfg DINGTALK_APP_SECRET)
now=$(date +%s)
if [ "$force" != "--nocache" ]; then
cached=$(cfg_get DINGTALK_OLD_TOKEN)
expiry=$(cfg_get DINGTALK_OLD_TOKEN_EXPIRY)
if [ -n "$cached" ] && [ -n "$expiry" ] && [ "$now" -lt "$expiry" ]; then
echo "$cached"
return 0
fi
fi
resp=$(curl -s "https://oapi.dingtalk.com/gettoken?appkey=${app_key}&appsecret=${app_secret}")
token=$(echo "$resp" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
expires_in=$(echo "$resp" | grep -o '"expires_in":[0-9]*' | cut -d: -f2)
if [ -z "$token" ]; then
echo "❌ 获取旧版 token 失败: $resp" >&2
exit 1
fi
cfg_set DINGTALK_OLD_TOKEN "$token"
cfg_set DINGTALK_OLD_TOKEN_EXPIRY "$((now + expires_in - 200))"
echo "$token"
}
# ─────────────────────────────────────────────────────────────────────────────
# 身份转换
# ─────────────────────────────────────────────────────────────────────────────
cmd_to_unionid() {
local user_id="$1"
local is_self=false
local old_token resp union_id
# 未传参 → 使用配置中的操作者自身 userId,转换结果写入配置
if [ -z "$user_id" ]; then
user_id=$(require_cfg DINGTALK_MY_USER_ID)
is_self=true
fi
old_token=$(cmd_old_token)
resp=$(curl -s -X POST \
"https://oapi.dingtalk.com/topapi/v2/user/get?access_token=${old_token}" \
-H "Content-Type: application/json" \
-d "{\"userid\":\"${user_id}\"}")
# 注意:使用无下划线的 unionid 字段(有下划线的 union_id 可能为空)
union_id=$(echo "$resp" | grep -o '"unionid":"[^"]*"' | head -1 | cut -d'"' -f4)
if [ -z "$union_id" ]; then
echo "❌ userId→unionId 转换失败: $resp" >&2
exit 1
fi
# 仅当转换的是操作者自身时,才写入配置(动态转换他人 userId 不写入)
if "$is_self" && [ -z "$(cfg_get DINGTALK_MY_OPERATOR_ID)" ]; then
cfg_set DINGTALK_MY_OPERATOR_ID "$union_id"
echo "✅ 自身 unionId 已写入配置 DINGTALK_MY_OPERATOR_ID" >&2
fi
echo "$union_id"
}
cmd_to_userid() {
local union_id="$1"
local old_token resp user_id
if [ -z "$union_id" ]; then
echo "❌ 请提供 unionId 参数" >&2
exit 1
fi
old_token=$(cmd_old_token)
resp=$(curl -s -X POST \
"https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token=${old_token}" \
-H "Content-Type: application/json" \
-d "{\"unionid\":\"${union_id}\"}")
user_id=$(echo "$resp" | grep -o '"userid":"[^"]*"' | head -1 | cut -d'"' -f4)
if [ -z "$user_id" ]; then
echo "❌ unionId→userId 转换失败: $resp" >&2
exit 1
fi
echo "$user_id"
}
# ─────────────────────────────────────────────────────────────────────────────
# 配置管理
# ─────────────────────────────────────────────────────────────────────────────
cmd_config() {
if [ ! -f "$CONFIG" ]; then
echo "配置文件不存在: $CONFIG"
echo "使用 --set KEY=VALUE 写入配置项"
return 0
fi
echo "配置文件: $CONFIG"
echo "─────────────────────────────────"
# 脱敏显示 SECRET 和 TOKEN
while IFS= read -r line; do
key="${line%%=*}"
val="${line#*=}"
case "$key" in
DINGTALK_APP_SECRET|DINGTALK_ACCESS_TOKEN|DINGTALK_OLD_TOKEN)
echo "${key}=${val:0:6}***(已脱敏)"
;;
*)
echo "$line"
;;
esac
done < "$CONFIG"
}
cmd_get() {
if [ $# -eq 0 ]; then
echo "❌ 请提供至少一个键名,用法: --get KEY [KEY2 ...]" >&2
exit 1
fi
for key in "$@"; do
val=$(cfg_get "$key")
if [ -z "$val" ]; then
echo "${key}=(未设置)"
else
case "$key" in
DINGTALK_APP_SECRET|DINGTALK_ACCESS_TOKEN|DINGTALK_OLD_TOKEN)
echo "${key}=${val:0:6}***(脱敏)"
;;
*)
echo "${key}=${val}"
;;
esac
fi
done
}
cmd_set() {
local kv="$1"
if [ -z "$kv" ] || [[ "$kv" != *"="* ]]; then
echo "❌ 格式错误,用法: --set KEY=VALUE" >&2
exit 1
fi
local key="${kv%%=*}"
local value="${kv#*=}"
cfg_set "$key" "$value"
echo "✅ 已设置 ${key}"
}
# ─────────────────────────────────────────────────────────────────────────────
# 入口:解析命令
# ─────────────────────────────────────────────────────────────────────────────
CMD="${1:-}"
case "$CMD" in
--help|-h|"")
show_help
;;
--token)
cmd_token "${2:-}"
;;
--token-info)
cmd_token_info
;;
--clear-token)
cmd_clear_token
;;
--old-token)
cmd_old_token "${2:-}"
;;
--to-unionid)
cmd_to_unionid "${2:-}"
;;
--to-userid)
cmd_to_userid "${2:-}"
;;
--config)
cmd_config
;;
--get)
shift
cmd_get "$@"
;;
--set)
cmd_set "${2:-}"
;;
*)
echo "❌ 未知命令: $CMD" >&2
echo "运行 --help 查看用法" >&2
exit 1
;;
esac
Related skills
FAQ
What can dingtalk-ai-table do?
dingtalk-ai-table lets an AI coding agent read from, write to, and update structured tables inside DingTalk. That supports automated workflows where table rows hold operational or approval data.
How popular is dingtalk-ai-table on skills.sh?
dingtalk-ai-table shows 513 installs on skills.sh from breath57/dingtalk-skills. The skill targets agent-driven DingTalk AI Table automation for workplace data sync.