""" Backfill fixed JSONs to Feishu bitable """ import json, urllib.request APP_TOKEN = "CMHSbUUjka3TrUsaxxEc297ongf" CRED_FILE = "/root/.openclaw/credentials/xiaoyan/config.json" def get_token(): with open(CRED_FILE) as f: cfg = json.load(f) req = urllib.request.Request( "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", data=json.dumps({"app_id": cfg['apps'][0]['appId'], "app_secret": cfg['apps'][0]['appSecret']}).encode(), headers={"Content-Type": "application/json"}) return json.loads(urllib.request.urlopen(req).read())['tenant_access_token'] def api_call(url, method='GET', body=None): token = get_token() headers = {"Authorization": f"Bearer {token}"} data = json.dumps(body).encode() if body else None if data: headers["Content-Type"] = "application/json" req = urllib.request.Request(url, data=data, method=method, headers=headers) return json.loads(urllib.request.urlopen(req).read()) def update_record(table_id, record_id, fields): url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{table_id}/records/{record_id}" return api_call(url, 'PUT', {"fields": fields}) # Mapping of fixed JSONs to tables backfill = { "021901": "tblzTLNH7f13uWQN", "022301": "tblzTLNH7f13uWQN", "021301": "tblVmeDtBDKsAEfz", "021601": "tblVmeDtBDKsAEfz", "021801": "tblVmeDtBDKsAEfz", } for sid, table_id in backfill.items(): with open(f'/tmp/fixed_{sid}.json') as f: new_jd = f.read() try: json.loads(new_jd) except json.JSONDecodeError as e: print(f"❌ {sid}: fixed JSON still invalid: {e}") continue # Find record_id url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{table_id}/records?page_size=50" resp = api_call(url) for item in resp['data']['items']: if item['fields'].get('题目集合 ID', '') == sid: rid = item['record_id'] result = update_record(table_id, rid, {"jsonData": new_jd}) if result.get('code') == 0: # Verify v_url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{table_id}/records/{rid}" v_resp = api_call(v_url) v_jd = v_resp['data'].get('record', v_resp['data'].get('items',[{}])[0])['fields'].get('jsonData', '') try: json.loads(v_jd) print(f"✅ {sid}: backfilled + verified ({len(new_jd)} chars)") except: print(f"⚠️ {sid}: written but verify failed") else: print(f"❌ {sid}: API error - {result.get('msg')}") break else: print(f"⚠️ {sid}: record not found in table") # Also fix P5 032801 ability + P6 abilities print("\n=== P5 032801 ===") url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/tblDssVmhGzc3UKd/records?page_size=50" resp = api_call(url) for item in resp['data']['items']: if item['fields'].get('题目集合 ID', '') == '032801': rid = item['record_id'] jd = json.loads(item['fields']['jsonData']) first = jd.get('first', {}) if first.get('ability') == ['听觉抓取关键信息']: first['ability'] = ['显性事实理解|关键词识别'] new_jd = json.dumps(jd, ensure_ascii=False) result = update_record("tblDssVmhGzc3UKd", rid, {"jsonData": new_jd}) print(f" {'✅' if result.get('code')==0 else '❌'} ability: 听觉抓取关键信息 → 显性事实理解|关键词识别") else: print(f" ⏭️ ability already: {first.get('ability')}") print("\n=== P6 ===") url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/tbloiMcD0sBtGSTq/records?page_size=50" resp = api_call(url) for item in resp['data']['items']: sid = item['fields'].get('题目集合 ID', '') if '010199' in str(sid): continue jd = json.loads(item['fields']['jsonData']) rid = item['record_id'] qs = jd.get('questionSet', []) changed = False for q in qs: if not q.get('ability'): q['ability'] = ['显性事实理解|关键词识别'] changed = True if changed: new_jd = json.dumps(jd, ensure_ascii=False) result = update_record("tbloiMcD0sBtGSTq", rid, {"jsonData": new_jd}) print(f" {'✅' if result.get('code')==0 else '❌'} P6 {sid}: ability filled") print("\n✅ Backfill complete!")