From 0f8fad911fa1e8887268912a6c0cb515ba130224 Mon Sep 17 00:00:00 2001 From: karuo Date: Thu, 12 Mar 2026 23:58:32 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20=E5=8D=A1=E8=8B=A5AI=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=202026-03-12=2023:58=20|=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=9A=E6=B0=B4=E6=A1=A5=E5=B9=B3=E5=8F=B0=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E3=80=81=E8=BF=90=E8=90=A5=E4=B8=AD=E6=9E=A2=E3=80=81=E8=BF=90?= =?UTF-8?q?=E8=90=A5=E4=B8=AD=E6=9E=A2=E5=B7=A5=E4=BD=9C=E5=8F=B0=20|=20?= =?UTF-8?q?=E6=8E=92=E9=99=A4=20>20MB:=2011=20=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../飞书管理/参考资料/飞书JSON格式全手册.md | 78 ++++++++-- .../水桥_平台对接/飞书管理/飞书JSON格式_SKILL.md | 46 +++++- 运营中枢/scripts/receivesms_find_recent_5.py | 133 ++++++++++++++++++ 运营中枢/工作台/gitea_push_log.md | 1 + 运营中枢/工作台/代码管理.md | 1 + 5 files changed, 237 insertions(+), 22 deletions(-) create mode 100644 运营中枢/scripts/receivesms_find_recent_5.py diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/飞书JSON格式全手册.md b/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/飞书JSON格式全手册.md index 095c98fa..35eb45a5 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/飞书JSON格式全手册.md +++ b/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/飞书JSON格式全手册.md @@ -1,8 +1,9 @@ # 飞书 JSON 格式全手册 > 基于项目 52 个 `.feishu.json` 实际文件 + 6 个脚本验证 + 飞书开放平台官方文档。 -> **版本:2.0** | **更新:2026-03-12** -> 来源:卡若AI 水桥 · 飞书管理 +> **版本:2.1** | **更新:2026-02-22** +> 来源:卡若AI 水桥 · 飞书管理 +> v2.1 新增:表格列宽自动适配 API、表格分割行 2+ 破折号兼容、code/callout 降级保底 --- @@ -125,6 +126,15 @@ python3 脚本/feishu_token_cli.py set-march-token <新token> > **原因**:bullet(12) 和 file(12) 可能存在 API 版本差异。当前生产代码中 block_type 12 = file,用于图片/文件上传,已验证稳定。列表统一用 text(2) + 前缀实现,确保兼容性。 +### 2.5 脚本写入行为(v2.1 更新) + +**sanitize_blocks 清洗**:写入前自动过滤: +- 空 text(2) 块 +- 空 code(14) 块(elements 内容为空或空白) +- 空 callout(19) 块 + +**code/callout 降级保底**:`code(14)` 或 `callout(19)` 写入飞书 API 失败时,脚本自动将其内容降级为 `text(2)` 正文块写入,内容不丢失。 + --- ## 三、各 Block 类型详细 JSON 格式 @@ -220,20 +230,17 @@ python3 脚本/feishu_token_cli.py set-march-token <新token> } ``` -**language 枚举值**: +**language 枚举值(脚本实测稳定值)**: | 值 | 语言 | 值 | 语言 | |:---|:---|:---|:---| -| 1 | PlainText(流程图/ASCII 用此) | 2 | Python | -| 3 | JavaScript | 4 | Java | -| 5 | Go | 6 | Shell/Bash | -| 7 | TypeScript | 8 | SQL | -| 9 | C++ | 10 | C | -| 11 | Ruby | 12 | Rust | -| 13 | Swift | 14 | Kotlin | -| 15 | PHP | 16 | CSS | -| 17 | HTML | 18 | Markdown | -| 19 | JSON | 20 | YAML | +| 1 | PlainText(流程图/ASCII 推荐) | 2 | Python | +| 3 | JavaScript / TypeScript | 6 | Shell / Bash | +| 8 | SQL | 9 | JSON | +| 11 | HTML / XML | 16 | Go | +| 22 | Rust | — | — | + +> `md_to_feishu_json.py` 的 `LANG_MAP` 使用上表值,已验证可正确渲染。飞书 API 官方文档的枚举编号与实测值存在出入,以脚本 `LANG_MAP` 为准。 --- @@ -374,6 +381,42 @@ grid_block = {"block_type": 24, "grid": {"column_size": 2}} > 创建空表格,最大 9×9。创建后通过电子表格 API 写入单元格内容。 > **限制**:不能在创建时直接带内容。 +**写入单元格**: + +``` +PUT /sheets/v2/spreadsheets/{spreadsheet_token}/values +Body: {"valueRange": {"range": "sheet1!A1:D5", "values": [[...], ...]}} +``` + +**列宽自动适配(v2.1 新增,强制在写完数据后执行)**: + +``` +PUT /sheets/v2/spreadsheets/{spreadsheet_token}/dimension_range +Body: +{ + "dimension": { + "sheetId": "", + "majorDimension": "COLUMNS", + "startIndex": 0, + "endIndex": 1 + }, + "dimensionProperties": {"pixelSize": 200} +} +``` + +- 对每一列循环调用,pixelSize 按内容自动计算:中文 ≈ 20px/字、ASCII ≈ 9px/字 + 24px 内边距。 +- 最小 80px,最大 400px。 +- `feishu_publish_blocks_with_images.py` 中 `_auto_resize_sheet_columns()` 已封装此逻辑,写完单元格自动触发。 + +**Markdown 表格分割行兼容(v2.1 修复)**: + +支持 2+ 破折号的分割行,不再要求最少 3 个: + +``` +|:--|:---| ✅ 有效(2 个破折号) +|:---|:---| ✅ 有效(3 个破折号) +``` + --- ### 3.11 表格块(block_type: 31,⚠️ 限制) @@ -560,6 +603,7 @@ Markdown 表格 | **上传图片/文件** | POST | `drive/v1/medias/upload_all` | | 创建多维表格 | POST | `bitable/v1/apps` | | 写入电子表格单元格 | PUT | `sheets/v2/spreadsheets/{token}/values` | +| **设置列宽** | PUT | `sheets/v2/spreadsheets/{token}/dimension_range` | **追加子块请求体**: ```json @@ -594,8 +638,12 @@ Markdown 表格 | 块数 > 50 写入失败 | 单次限制 50 块 | 分批写入,每批 ≤ 50 | | sheet 超 9×9 报错 | 电子表格创建上限 | 改用 TSV 正文(2) 回退 | | 写入串月 | wiki_token 路由错误 | 写前校验文档标题含目标月份 | +| 表格列太窄挤压 | 默认列宽约 72px | 写完数据后调用 `PUT dimension_range` 或用 `_auto_resize_sheet_columns()` | +| 表格未识别(显示 `|文字|`) | 分割行破折号不足 3 个(`:--`) | 脚本 v2.1 已修复,现接受 2+ 破折号 | +| code(14)/callout(19) 写入失败 | API 1770001 | 脚本自动降级为 text(2) 正文块,内容保留 | --- -**版本**:2.0 | **整理**:卡若AI 水桥 | **更新**:2026-03-12 -**数据来源**:52 个 `.feishu.json` + 6 个脚本 + 飞书开放平台 API 文档 +**版本**:2.1 | **整理**:卡若AI 水桥 | **更新**:2026-02-22 +**数据来源**:52 个 `.feishu.json` + 6 个脚本 + 飞书开放平台 API 文档 +**v2.1 变更**:表格分割行接受 2+ 破折号;新增列宽自适应 `dimension_range` API;sanitize_blocks 扩展支持 code/callout;code/callout 写入失败自动降级为 text。 diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/飞书JSON格式_SKILL.md b/02_卡人(水)/水桥_平台对接/飞书管理/飞书JSON格式_SKILL.md index 7d25ecf3..a025a476 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/飞书JSON格式_SKILL.md +++ b/02_卡人(水)/水桥_平台对接/飞书管理/飞书JSON格式_SKILL.md @@ -1,11 +1,11 @@ --- name: 飞书JSON格式 -description: 飞书文档 JSON 格式速查、编写、上传与翻译;各 block_type 格式写法、Markdown 转换对照、标准操作流程一站式参考 -triggers: 飞书json、飞书json格式、飞书block、飞书块格式、飞书文档格式、json上传飞书、飞书格式怎么写、block_type、飞书块类型、飞书写入格式、飞书上传json、飞书文档block、飞书高亮块、飞书代码块、飞书待办块、飞书标题块、飞书分割线、飞书callout、飞书多维表格json、飞书列表、飞书表格、飞书分栏、更新飞书JSON格式 +description: 飞书文档 JSON 格式速查、编写、上传与翻译;各 block_type 格式写法、Markdown 转换对照、表格列宽自适应、脚本 SOP 一站式参考 +triggers: 飞书json、飞书json格式、飞书block、飞书块格式、飞书文档格式、json上传飞书、飞书格式怎么写、block_type、飞书块类型、飞书写入格式、飞书上传json、飞书文档block、飞书高亮块、飞书代码块、飞书待办块、飞书标题块、飞书分割线、飞书callout、飞书多维表格json、飞书列表、飞书表格、飞书分栏、更新飞书JSON格式、飞书列宽、表格列宽 owner: 水桥 group: 水 -version: "2.0" -updated: "2026-03-12" +version: "2.1" +updated: "2026-02-22" --- # 飞书 JSON 格式 Skill @@ -176,7 +176,15 @@ Markdown 表格 }} ``` -**language**:1=纯文本 2=Python 3=JS 4=Java 5=Go 6=Shell 7=TypeScript 8=SQL 19=JSON 20=YAML +**language(脚本实测值,与 md_to_feishu_json.py LANG_MAP 对应)**: + +| 值 | 语言 | 值 | 语言 | +|:--|:--|:--|:--| +| 1 | PlainText / 流程图 / ASCII | 2 | Python | +| 3 | JavaScript / TypeScript | 6 | Shell / Bash | +| 8 | SQL | 9 | JSON | +| 11 | HTML / XML | 16 | Go | +| 22 | Rust | — | — | ### 5. 待办(block_type: 17) @@ -221,7 +229,28 @@ POST drive/v1/medias/upload_all (form-data: file_name, parent_type=docx_image, {"block_type": 30, "sheet": {"row_size": 5, "column_size": 4}} ``` -> 最大 9×9,创建后通过 sheets API 写入单元格 +> 最大 9×9,创建后通过 sheets API 写入单元格。 + +**表格列宽自动适配(强制执行,写完数据后立刻调用)**: + +```bash +PUT /sheets/v2/spreadsheets/{spreadsheet_token}/dimension_range +``` + +```json +{ + "dimension": { + "sheetId": "", + "majorDimension": "COLUMNS", + "startIndex": 0, + "endIndex": 1 + }, + "dimensionProperties": {"pixelSize": 200} +} +``` + +- 中文字符 ≈ 20px/字,ASCII ≈ 9px/字,加 24px 内边距;最小 80px,最大 400px。 +- 脚本 `feishu_publish_blocks_with_images.py` 的 `_auto_resize_sheet_columns()` 自动完成此步骤,无需手动调用。 ### 10. 多维表格(block_type: 43) @@ -257,7 +286,7 @@ POST drive/v1/medias/upload_all (form-data: file_name, parent_type=docx_image, | `1. 有序` | 2 | `1)` 前缀 | 正文块模拟 | | `- [ ]` | 17 | done=false | | | `- [x]` | 17 | done=true | | -| 表格 ≤9×9 | 30 | sheet | | +| 表格 ≤9×9 | 30 | sheet | 分割行接受 2+ 破折号(`:--` `:---`) | | 表格 >9×9 | 2 | TSV 正文 | 保底方案 | --- @@ -287,6 +316,7 @@ POST drive/v1/medias/upload_all (form-data: file_name, parent_type=docx_image, | 创建 Wiki 子节点 | POST | `wiki/v2/spaces/{space_id}/nodes` | | 创建多维表格 | POST | `bitable/v1/apps` | | 写入表格单元格 | PUT | `sheets/v2/spreadsheets/{token}/values` | +| **设置列宽** | PUT | `sheets/v2/spreadsheets/{token}/dimension_range` | **追加子块请求体**:`{"children": [块1, 块2, ...], "index": 0}` > `index: 0` = 最前,不传 = 末尾。**单次 ≤ 50 块** @@ -304,6 +334,8 @@ POST drive/v1/medias/upload_all (form-data: file_name, parent_type=docx_image, | 多维表格权限不足 | 未开通 bitable:app | `python3 脚本/feishu_force_reauth.py` | | 块数 > 50 | 单次写入上限 | 分批,每批 ≤ 50 | | sheet >9×9 | 电子表格上限 | 改用 TSV 正文(2) 回退 | +| 表格列挤压 | sheet 默认列宽约 72px | `_auto_resize_sheet_columns()` 写完后自动调用 `PUT dimension_range` | +| code/callout 写入失败 | 1770001 | 脚本自动降级为 text(2) 正文块,内容不丢失 | --- diff --git a/运营中枢/scripts/receivesms_find_recent_5.py b/运营中枢/scripts/receivesms_find_recent_5.py new file mode 100644 index 00000000..c36786b6 --- /dev/null +++ b/运营中枢/scripts/receivesms_find_recent_5.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +从 receivesms.co 多国家(美/加/英)拉取号码,筛出「最近有短信活动且收件页可正常打开」的 5 个, +并做可用性校验(能打开收件页、页面含短信结构)。 +""" +import re +import time +import urllib.request + +BASE = "https://www.receivesms.co" + +# (国家名, 列表页URL, 收件页路径前缀, 列表正则:含 group(1)=id, group(2)=号码) +CONFIGS = [ + ("US", BASE + "/us-phone-numbers/us/", "us-phone-number", + re.compile(r'href="/us-phone-number/(\d+)/"[^>]*>.*?(\+1[\d\s\-]+)', re.DOTALL)), + ("CA", BASE + "/canadian-phone-numbers/ca/", "ca-phone-number", + re.compile(r'href="/ca-phone-number/(\d+)/"[^>]*>.*?(\+1[\d\s\-]+)', re.DOTALL)), + ("GB", BASE + "/british-phone-numbers/gb/", "gb-phone-number", + re.compile(r'href="/gb-phone-number/(\d+)/"[^>]*>.*?(\+44[\d\s]+)', re.DOTALL)), +] + + +def fetch(url): + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"}) + with urllib.request.urlopen(req, timeout=25) as r: + return r.read().decode("utf-8", errors="replace") + + +def parse_list(html, regex): + pairs = [] + for m in regex.finditer(html): + mid, num = m.group(1), m.group(2).replace(" ", "").replace("-", "").strip() + if num.startswith("+"): + pairs.append((mid, num)) + return pairs + + +def is_recent(activity_text): + """是否算近期(24 小时内):seconds/minutes/hours ago 且 ≤24。""" + if not activity_text: + return False + t = activity_text.strip().lower() + if "second" in t and "ago" in t: + return True + if "minute" in t and "ago" in t: + return True + if "hour" in t and "ago" in t: + m = re.search(r"(\d+)\s*hour", t) + if m: + return int(m.group(1)) <= 24 + return True # "1 hour ago" + if "day" in t and "ago" in t: + m = re.search(r"(\d+)\s*day", t) + if m and int(m.group(1)) <= 1: + return True + return False + + +def inbox_usable(html): + """收件页是否包含短信结构(可正常收码)。""" + return 'class="entry-body"' in html and 'class="sms"' in html + + +def main(): + print("正在从 receivesms.co 多国家拉取号码并校验…", flush=True) + seen = set() + results = [] + # 先尽量找 24h 内有活动的 + for country, list_url, path_prefix, regex in CONFIGS: + if len(results) >= 5: + break + try: + html = fetch(list_url) + pairs = parse_list(html, regex) + except Exception as e: + print(f" {country} 列表失败: {e}", flush=True) + continue + for mid, num in list(pairs)[:12]: + if len(results) >= 5: + break + if num in seen: + continue + url = f"{BASE}/{path_prefix}/{mid}/" + try: + page = fetch(url) + except Exception: + time.sleep(0.3) + continue + if not inbox_usable(page): + time.sleep(0.25) + continue + m = re.search(r"Last activity:\s*([^<]+)<", page) + last = m.group(1).strip() if m else "" + if is_recent(last): + seen.add(num) + results.append((country, num, last, url)) + print(f" [{len(results)}/5] {country} {num} Last: {last}", flush=True) + time.sleep(0.35) + # 不足 5 个则补足:任意收件页可用的号 + for country, list_url, path_prefix, regex in CONFIGS: + if len(results) >= 5: + break + try: + html = fetch(list_url) + pairs = parse_list(html, regex) + except Exception: + continue + for mid, num in list(pairs)[:20]: + if len(results) >= 5: + break + if num in seen: + continue + url = f"{BASE}/{path_prefix}/{mid}/" + try: + page = fetch(url) + except Exception: + continue + if not inbox_usable(page): + continue + m = re.search(r"Last activity:\s*([^<]+)<", page) + last = (m.group(1).strip() if m else "N/A") + seen.add(num) + results.append((country, num, last, url)) + print(f" [{len(results)}/5] {country} {num} Last: {last}", flush=True) + time.sleep(0.3) + print("\n--- 可用 5 个号码(已测收件页可打开)---") + for country, num, last, url in results[:5]: + print(f"{country}\t{num}\t{last}\t{url}") + print("\n使用:打开对应 URL 即可查看/刷新该号码收到的短信。") + +if __name__ == "__main__": + main() diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index cc00e232..b1bb8066 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -318,3 +318,4 @@ | 2026-03-12 23:20:58 | 🔄 卡若AI 同步 2026-03-12 23:20 | 更新:Cursor规则、水桥平台对接、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 | | 2026-03-12 23:23:58 | 🔄 卡若AI 同步 2026-03-12 23:23 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 11 个 | | 2026-03-12 23:41:41 | 🔄 卡若AI 同步 2026-03-12 23:41 | 更新:水桥平台对接、总索引与入口、运营中枢、运营中枢工作台 | 排除 >20MB: 11 个 | +| 2026-03-12 23:48:18 | 🔄 卡若AI 同步 2026-03-12 23:48 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index 246e84f9..045adc45 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -321,3 +321,4 @@ | 2026-03-12 23:20:58 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-12 23:20 | 更新:Cursor规则、水桥平台对接、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-12 23:23:58 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-12 23:23 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-12 23:41:41 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-12 23:41 | 更新:水桥平台对接、总索引与入口、运营中枢、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | +| 2026-03-12 23:48:18 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-12 23:48 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |