#!/usr/bin/env python3 """Task 1: Fix all structured empty seconds → "second": {} Task 2: Add 图片描述 to 021601, 021801, 022001""" import requests, json, time APP_TOKEN = "CMHSbUUjka3TrUsaxxEc297ongf" APP_ID = "cli_a931175d41799cc7" APP_SECRET = "Iw2vEfbjT6GtV0GhbxbZqfQ4nAPtbR14" def get_token(): r = requests.post("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", json={"app_id": APP_ID, "app_secret": APP_SECRET}, timeout=10) return r.json()["tenant_access_token"] token = get_token() # List all tables in the bitable r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables", headers={"Authorization": f"Bearer {token}"}, timeout=15) tables = r.json().get("data", {}).get("items", []) print(f"共 {len(tables)} 个表\n") # ====== Task 1: Scan all tables for structured empty second blocks ====== fixes_second = [] # (table_id, table_name, qsid, rid) for t in tables: tid = t["table_id"] tname = t["name"] r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{tid}/records?page_size=200", headers={"Authorization": f"Bearer {token}"}, timeout=15) items = r.json().get("data", {}).get("items", []) for it in items: f = it["fields"] qsid = f.get("题目集合 ID", "") or "" jd_raw = f.get("jsonData", "") if not jd_raw: continue try: jd = json.loads(jd_raw) if isinstance(jd_raw, str) else jd_raw except: continue second = jd.get("second", None) if not second or not isinstance(second, dict): continue # Check if structured empty: has type/questionSetID but empty questionSet qs = second.get("questionSet", None) if qs is not None and isinstance(qs, list) and len(qs) == 0: # Has structure but no content → fix to {} fixes_second.append((tid, tname, qsid, it["record_id"], second)) print(f"=== Task 1: 修复结构化空 second → {{}} ===") print(f"发现 {len(fixes_second)} 条需要修复\n") for tid, tname, qsid, rid, old_second in fixes_second: # Fetch fresh record to get current jsonData r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{tid}/records/{rid}", headers={"Authorization": f"Bearer {token}"}, timeout=10) rec = r.json()["data"]["record"] jd = json.loads(rec["fields"]["jsonData"]) # Before old_type = jd["second"].get("type", "?") # Replace with empty object jd["second"] = {} new_jd = json.dumps(jd, ensure_ascii=False) r = requests.put( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{tid}/records/{rid}", headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, json={"fields": {"jsonData": new_jd}}, timeout=15) code = r.json().get("code") print(f" {'✅' if code==0 else '❌'} [{tname}] {qsid}: second({old_type}) → {{}}") time.sleep(0.3) # ====== Task 2: Add 图片描述 to 021601, 021801, 022001 ====== print(f"\n=== Task 2: 补充图片描述 ===") pic_map = { "021601": '[1-组图]:{"prompt_2":"黑白线条图:一个孩子在公园里焦急地四处张望,似乎在寻找丢失的玩具,背景有秋千、滑梯和大树,远处是公园的出口","prompt_3":"黑白线条图:一个小男孩正在爬滑梯的顶部,一个较大的孩子站在下面焦急地伸手示意他下来,表情紧张","prompt_4":"黑白线条图:公园入口处可以看到周围的商店、图书馆和警察亭,一位公园工作人员站在指示牌旁微笑着指路"}', "021801": '[1-组图]:{"prompt_2":"黑白线条图:一个孩子躺在床上盖着被子,额头上放着湿毛巾,他的朋友坐在床边端来一杯水,床头柜上放着药瓶","prompt_3":"黑白线条图:两个同学坐在教室的课桌前,一个正在耐心地指着作业本给另一个讲解题目,旁边放着课本和铅笔","prompt_4":"黑白线条图:两个孩子并肩坐在草地上,一个孩子指着远方天空中的热气球,脸上带着鼓励和期待的表情","prompt_5":"黑白线条图:教室里,一个孩子帮忙扶住同学够高处的书本,另一个孩子在帮老师整理教具,气氛温馨互助"}', "022001": '[1-组图]:{"prompt_2":"黑白线条图:学校走廊里,一个孩子脸上带着担忧的表情蹲在墙角,另一个孩子走过来蹲下身关切地询问","prompt_3":"黑白线条图:一位爷爷坐在沙发上拉着孩子的手认真地说话,表情温和而坚定,孩子脸上露出理解的神情","prompt_4":"黑白线条图:教室里,一个孩子站在讲台上自信地展示自己的画作,台下的同学们都在热烈鼓掌,孩子脸上带着自豪的笑容","prompt_5":"黑白线条图:书房里,一位家长蹲在孩子面前轻声解释着笔记本上的内容,墙上贴着学习计划表和各种鼓励标语"}', } # Speaking-P2 table SP2_TABLE = "tblGoWYBmVI0IrvQ" r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{SP2_TABLE}/records?page_size=200", headers={"Authorization": f"Bearer {token}"}, timeout=15) for it in r.json()["data"]["items"]: qsid = it["fields"].get("题目集合 ID", "") if qsid not in pic_map: continue rid = it["record_id"] r = requests.put( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{SP2_TABLE}/records/{rid}", headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, json={"fields": {"图片描述": pic_map[qsid]}}, timeout=15) code = r.json().get("code") print(f" {'✅' if code==0 else '❌'} {qsid}: 图片描述已写入") # ====== Verify ====== print(f"\n=== 验证 ===") # Spot-check one from each table for tid, tname, qsid, rid, _ in fixes_second[:3]: # first 3 r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{tid}/records/{rid}", headers={"Authorization": f"Bearer {token}"}, timeout=10) jd = json.loads(r.json()["data"]["record"]["fields"]["jsonData"]) second = jd.get("second", None) status = "✅ {}" if second == {} else f"❌ {json.dumps(second, ensure_ascii=False)[:50]}" print(f" [{tname}] {qsid}: second={status}") # Verify pic for qsid in pic_map: r = requests.get(f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{SP2_TABLE}/records?page_size=200", headers={"Authorization": f"Bearer {token}"}, timeout=15) for it in r.json()["data"]["items"]: if it["fields"].get("题目集合 ID") == qsid: pic = it["fields"].get("图片描述", "") print(f" {qsid}: 图片描述={'✅' if pic else '❌空'}") break time.sleep(0.2) print("\n全部完成")