fix: resolve real-machine QA findings across CLI, scripts and skill docs
Fix CLI command bugs surfaced by full real-machine QA: - aitable: make chart/dashboard share update --enabled a string flag so "--enabled false" disables instead of silently enabling (bool flag + space-syntax help example inverted the action); clarify chart update requires --config; make form get filter by view-id client-side so it returns a single form; drop inline // comments from chart JSON examples - chat: resolve conversation-info --user to openDingTalkId, register --id/--conversation-id/--chat aliases; cap list-all-conversations --limit at 100 and reject larger values instead of silent truncation; detect webhook errcode failures instead of wrapping them as success; remove duplicate group/members subcommand registration in help - contact: register --dept/--depts as the primary dept flags to match the RunE parsing (were only registered as --id/--ids) - sheet: emit clean JSON for media-upload and export under --format json, suppressing progress lines that leaked onto stdout - wiki: correct node create --type enum (drop unsupported asheet, add axls/able/appt/adraw/amind) - ding: default message list --type to ALL since the server rejects an empty type Fix helper scripts (mono and multi): - aitable import/export flag names and tableId length regex - mail search --limit, contact dept response keys and userInfo nesting - attendance_my_record whoami compatibility, calendar_schedule_meeting event id unwrapping, drive_tree_list recursion via fileId, report scripts migrated off deprecated report list/detail Sync skill docs (mono and multi) to real-machine behavior across all products: command indexes, flag names, enums, return-structure keys, and cross-product intent routing; annotate genuinely server-side limitations and the no-op global --jq/--fields flags.
This commit is contained in:
1 parent
238f4256d3
commit
a65d6f23ec
138 files changed
+7767
-1714
No files matched your search
@@ -2,9 +2,14 @@
|
||||
"""
|
||||
查看今天收到的日志列表及详情
|
||||
|
||||
基于 `dws report inbox list` + `dws report entry get`(旧的 report list / report detail
|
||||
已废弃)。inbox list 返回的 result[] 使用中文展示键:日期 / 标题 / 发送人 / 状态 / 钉钉链接;
|
||||
reportId 不在 result[] 里,只在 _internalDetailCommands[].command 中,按页与 result[] 同序对应。
|
||||
|
||||
用法:
|
||||
python report_received_today.py
|
||||
python report_received_today.py --days 3 # 最近 3 天
|
||||
python report_received_today.py --days 3 # 最近 3 天
|
||||
python report_received_today.py --detail # 额外拉取每条正文 (entry get)
|
||||
python report_received_today.py --dry-run
|
||||
"""
|
||||
|
||||
@@ -13,7 +18,7 @@ import json
|
||||
import subprocess
|
||||
import argparse
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Any, Optional
|
||||
from typing import List, Any, Optional, Tuple
|
||||
|
||||
|
||||
def run_dws(
|
||||
@@ -37,91 +42,118 @@ def run_dws(
|
||||
return None
|
||||
|
||||
|
||||
def to_iso(dt: datetime) -> str:
|
||||
return dt.strftime('%Y-%m-%dT%H:%M:%S+08:00')
|
||||
def iso_start(dt: datetime) -> str:
|
||||
return dt.strftime('%Y-%m-%dT00:00:00+08:00')
|
||||
|
||||
|
||||
def iso_end(dt: datetime) -> str:
|
||||
return dt.strftime('%Y-%m-%dT23:59:59+08:00')
|
||||
|
||||
|
||||
def report_id_from_command(cmd: str) -> str:
|
||||
parts = cmd.split()
|
||||
if '--report-id' in parts:
|
||||
i = parts.index('--report-id')
|
||||
if i + 1 < len(parts):
|
||||
return parts[i + 1]
|
||||
return ''
|
||||
|
||||
|
||||
def fetch_inbox(
|
||||
start: str, end: str, dry_run: bool,
|
||||
) -> List[Tuple[dict, str]]:
|
||||
"""按 cursor 翻页拉全 inbox;返回 (result_item, reportId) 列表。"""
|
||||
pairs: List[Tuple[dict, str]] = []
|
||||
cursor = 0
|
||||
while True:
|
||||
data = run_dws([
|
||||
'report', 'inbox', 'list',
|
||||
'--start', start,
|
||||
'--end', end,
|
||||
'--cursor', str(cursor),
|
||||
'--size', '20',
|
||||
'--format', 'json',
|
||||
], dry_run=dry_run)
|
||||
if dry_run or not isinstance(data, dict):
|
||||
return pairs
|
||||
items = data.get('result') or []
|
||||
cmds = data.get('_internalDetailCommands') or []
|
||||
for idx, item in enumerate(items):
|
||||
rid = ''
|
||||
if idx < len(cmds):
|
||||
rid = report_id_from_command(
|
||||
cmds[idx].get('command', '')
|
||||
)
|
||||
pairs.append((item, rid))
|
||||
if data.get('hasMore') and data.get('nextCursor') is not None:
|
||||
cursor = data['nextCursor']
|
||||
else:
|
||||
break
|
||||
return pairs
|
||||
|
||||
|
||||
def print_detail(rid: str) -> None:
|
||||
detail = run_dws([
|
||||
'report', 'entry', 'get',
|
||||
'--report-id', rid, '--format', 'json',
|
||||
])
|
||||
if not isinstance(detail, dict):
|
||||
return
|
||||
result = detail.get('result')
|
||||
if not isinstance(result, dict):
|
||||
return
|
||||
for c in (result.get('report_content') or [])[:3]:
|
||||
key = c.get('key', '')
|
||||
val = c.get('value', '')
|
||||
if key and val:
|
||||
print(f" {key}: {str(val).strip()[:60]}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='查看收到的日志'
|
||||
parser = argparse.ArgumentParser(description='查看收到的日志')
|
||||
parser.add_argument(
|
||||
'--days', type=int, default=1, help='查询天数 (默认 1,即今天)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--days', type=int, default=1, help='查询天数 (默认 1)'
|
||||
'--detail', action='store_true', help='额外拉取每条正文'
|
||||
)
|
||||
parser.add_argument('--dry-run', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
now = datetime.now()
|
||||
start = now - timedelta(days=args.days)
|
||||
start = start.replace(hour=0, minute=0, second=0)
|
||||
start_dt = now - timedelta(days=max(args.days - 1, 0))
|
||||
start = iso_start(start_dt)
|
||||
end = iso_end(now)
|
||||
|
||||
label = '今天' if args.days == 1 else f'最近 {args.days} 天'
|
||||
print(f'📓 查看{label}收到的日志...\n')
|
||||
|
||||
data = run_dws([
|
||||
'report', 'list',
|
||||
'--start', to_iso(start),
|
||||
'--end', to_iso(now),
|
||||
'--cursor', '0',
|
||||
'--size', '20',
|
||||
'--format', 'json',
|
||||
], dry_run=args.dry_run)
|
||||
print(f'查看{label}收到的日志...\n')
|
||||
|
||||
pairs = fetch_inbox(start, end, args.dry_run)
|
||||
if args.dry_run:
|
||||
return
|
||||
if not data:
|
||||
print('未查到日志')
|
||||
if not pairs:
|
||||
print(' 暂无收到的日志')
|
||||
return
|
||||
|
||||
if isinstance(data, list):
|
||||
reports = data
|
||||
elif isinstance(data, dict):
|
||||
inner = data.get('result', data)
|
||||
if isinstance(inner, dict):
|
||||
reports = inner.get('report_list',
|
||||
inner.get('reports', []))
|
||||
elif isinstance(inner, list):
|
||||
reports = inner
|
||||
else:
|
||||
reports = []
|
||||
else:
|
||||
reports = []
|
||||
if not reports:
|
||||
print(' ✅ 暂无收到的日志')
|
||||
return
|
||||
|
||||
print(f"📓 {label}日志 ({len(reports)} 条)")
|
||||
print(f"{label}日志 ({len(pairs)} 条)")
|
||||
print('=' * 50)
|
||||
|
||||
for r in reports:
|
||||
if not isinstance(r, dict):
|
||||
print(f"\n 📝 {r}")
|
||||
continue
|
||||
rid = r.get('reportId') or r.get('id', '')
|
||||
creator = r.get('creatorName') or r.get('creator', '未知')
|
||||
template = r.get('templateName') or r.get('template', '')
|
||||
create_time = r.get('createTime', '')
|
||||
if isinstance(create_time, (int, float)):
|
||||
create_time = datetime.fromtimestamp(
|
||||
create_time / 1000
|
||||
).strftime('%Y-%m-%d %H:%M')
|
||||
for item, rid in pairs:
|
||||
title = item.get('标题') or '日志'
|
||||
sender = item.get('发送人') or '未知'
|
||||
date = item.get('日期') or ''
|
||||
status = item.get('状态') or ''
|
||||
link = item.get('钉钉链接') or ''
|
||||
|
||||
print(f"\n 📝 {template or '日志'} - {creator}")
|
||||
print(f" 时间: {create_time}")
|
||||
print(f" ID: {rid}")
|
||||
print(f"\n {title} - {sender}")
|
||||
print(f" 时间: {date}")
|
||||
if status:
|
||||
print(f" 状态: {status}")
|
||||
if link:
|
||||
print(f" 链接: {link}")
|
||||
|
||||
if rid:
|
||||
detail = run_dws([
|
||||
'report', 'detail',
|
||||
'--report-id', rid, '--format', 'json',
|
||||
])
|
||||
if detail and isinstance(detail, dict):
|
||||
contents = detail.get('contents', [])
|
||||
for c in contents[:3]:
|
||||
key = c.get('key') or c.get('title', '')
|
||||
val = c.get('value') or c.get('content', '')
|
||||
if key and val:
|
||||
print(f" {key}: {str(val)[:60]}")
|
||||
if args.detail and rid:
|
||||
print_detail(rid)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in new issue
Block a user