#!/usr/bin/env python3 """reading_matchInfo 021301-021801 (6套), L2 B级 3-5词短句通知""" import json, requests, time CRED = "/root/.openclaw/credentials/xiaoyan/config.json" TOKEN_APP = "CMHSbUUjka3TrUsaxxEc297ongf" TBL = "tblCgfYDnnqwLfgH" AB = ["标识与通知理解|标识 & 通知"] with open(CRED) as f: cred = json.load(f) aid = cred["apps"][0]["appId"] asecret = cred["apps"][0]["appSecret"] def get_token(): r = requests.post("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", json={"app_id": aid, "app_secret": asecret}) return r.json()["tenant_access_token"] # ==================== QUESTION DATA ==================== # Each entry: (questionImage, question, [options], [answer_index], explanation) # Format: image text is 3-5 word real notice/sign I = lambda img, q, opts, ans, exp: { "questionImage": img, "question": q, "options": opts, "answer": ans, "explanation": exp } DATA = { "021301": { "first": [ I("021301-00.png","What does this poster say?", ["The singer is here","The actor is on stage","The dancer is late"],[1], "海报上写着 The ACTOR is on stage,演员在舞台上。"), I("021301-01.png","What does the man have?", ["White hair","Black beard","Red hat"],[1], "通缉令上写着 Man with black BEARD,男子有黑胡子。"), I("021301-02.png","What does the label say?", ["The pictures are the same","The pictures are different","The pictures are old"],[1], "标签上写着 These pictures are DIFFERENT,两幅画不一样。"), I("021301-03.png","What was Lily today?", ["Brave","Sad","Tired"],[0], "奖状上写着 Lily was very BRAVE today,Lily 今天很勇敢。"), I("021301-04.png","Who just moved in?", ["A new teacher","A new neighbour","A new student"],[1], "卡片上写着 A new NEIGHBOUR moved in,新邻居搬来了。"), ], "second": [ I("021301-05.png","What time is dinner?", ["At five","At six","At seven"],[1], "便条上写着 DINNER at six tonight,晚饭六点吃。"), I("021301-06.png","What is Mum doing?", ["Sleeping","Cooking","Reading"],[1], "门牌上写着 Mum is COOKING right now,妈妈在做饭。"), I("021301-07.png","What kind of exit is this?", ["Fire exit","Park exit","Shop exit"],[0], "标志上写着 FIRE exit this way,这是消防出口。"), I("021301-08.png","What is on show Friday?", ["A family album","A film","A play"],[0], "海报上写着 Family ALBUM on show Friday,周五展示家庭相册。"), I("021301-09.png","What does this note ask?", ["Read my diary","Do not read my diary","Buy a new diary"],[1], "便条上写着 Do not read my DIARY,不要看我的日记。"), ], "desc": """1. 图片材料文本: The ACTOR is on stage. 图片材料文本: Man with black BEARD wanted. 图片材料文本: These pictures are DIFFERENT. 图片材料文本: Lily was very BRAVE today. 图片材料文本: A new NEIGHBOUR moved in. 2. 图片材料文本: DINNER at six tonight. 图片材料文本: Mum is COOKING right now. 图片材料文本: FIRE exit this way → 图片材料文本: Family ALBUM on show Friday. 图片材料文本: Do not read my DIARY.""", }, "021401": { "first": [ I("021401-00.png","What should you plan?", ["Your weekend","Your lesson","Your dinner"],[0], "便签上写着 PLAN your weekend now,现在就计划周末吧。"), I("021401-01.png","How fast is the bike repair?", ["In one day","In one hour","In one week"],[1], "店招牌上写着 Bike REPAIR in one hour,一小时修好自行车。"), I("021401-02.png","Where is today's newspaper?", ["On the shelf","On the desk","In the bag"],[1], "图书馆标牌上写着 Today's NEWSPAPER on the desk,报纸在桌上。"), I("021401-03.png","What is lost?", ["A blue backpack","A red pen","A white book"],[0], "失物招领上写着 Lost: Blue BACKPACK in Room 3,蓝色背包丢了。"), I("021401-04.png","What should you do on the bus?", ["Stand up","Give your seat to old people","Sing songs"],[1], "公交标牌上写着 Give your SEAT to old people,给老人让座。"), ], "second": [ I("021401-05.png","When is the garden open?", ["In the morning","After class","At lunch"],[1], "公告上写着 School GARDEN open after class,花园放学后开放。"), I("021401-06.png","What fruit is on sale?", ["Apple","Banana","Melon"],[2], "市场标牌上写着 Sweet MELON for sale today,今天甜瓜热卖。"), I("021401-07.png","What does this lake sign say?", ["Drink lake water","Do not drink lake water","Swim in the lake"],[1], "警示牌上写着 Do not drink lake WATER,不要喝湖水。"), I("021401-08.png","When should you plant a tree?", ["On Monday","On Friday","On Sunday"],[1], "公告上写着 PLANT a tree on Friday,周五植树。"), I("021401-09.png","What starts next week?", ["Summer camp","Winter camp","Spring class"],[0], "校园通知上写着 SUMMER camp starts next week,夏令营下周开始。"), ], "desc": """1. 图片材料文本: PLAN your weekend now. 图片材料文本: Bike REPAIR in one hour. 图片材料文本: Today's NEWSPAPER on the desk. 图片材料文本: Lost: Blue BACKPACK in Room 3. 图片材料文本: Give your SEAT to old people. 2. 图片材料文本: School GARDEN open after class. 图片材料文本: Sweet MELON for sale today. 图片材料文本: Do not drink lake WATER. 图片材料文本: PLANT a tree on Friday. 图片材料文本: SUMMER camp starts next week.""", }, "021501": { "first": [ I("021501-00.png","Where should visitors sign in?", ["At the gate","At the office","At the shop"],[1], "校门标识上写着 VISITORs sign in at the office,访客去办公室签到。"), I("021501-01.png","What kind of party is it?", ["Birthday party","School party","Garden party"],[0], "横幅上写着 WELCOME to the birthday party,生日派对欢迎你。"), I("021501-02.png","Whose party are you invited to?", ["Lily's","Tom's","Mum's"],[1], "邀请函上写着 You are INVITEd to Tom's party,你被邀请参加Tom的派对。"), I("021501-03.png","What can you do here?", ["Sleep","Laugh","Cry"],[1], "海报上写着 Come and LAUGH with us,来和我们一起大笑。"), I("021501-04.png","What time does breakfast end?", ["At 7 a.m.","At 8 a.m.","At 9 a.m."],[2], "酒店通知上写着 GUESTs: breakfast 7 to 9 a.m.,早餐9点结束。"), ], "second": [ I("021501-05.png","What should you check for?", ["Mistakes","Stars","Pictures"],[0], "作业提醒上写着 Check for MISTAKEs first,先检查有没有错误。"), I("021501-06.png","What should you read carefully?", ["The story","The instruction","The picture"],[1], "考试通知上写着 Read the INSTRUCTION carefully,仔细读说明。"), I("021501-07.png","What must you give if late?", ["A reason","A gift","A book"],[0], "办公室告知上写着 Give a REASON if late,迟到要说明原因。"), I("021501-08.png","Where must you not bring drinks?", ["Near the library","Near technology room","Near the garden"],[1], "电脑室标识上写着 No drinks near TECHNOLOGY room,科技室附近不准带饮料。"), I("021501-09.png","Where should you wash your brush?", ["At home","Here","Outside"],[1], "美术室标识上写着 Wash your paint BRUSH here,在这里洗画笔。"), ], "desc": """1. 图片材料文本: VISITORs sign in at the office. 图片材料文本: WELCOME to the birthday party! 图片材料文本: You are INVITEd to Tom's party. 图片材料文本: Come and LAUGH with us! 图片材料文本: GUESTs: breakfast 7 to 9 a.m. 2. 图片材料文本: Check for MISTAKEs first. 图片材料文本: Read the INSTRUCTION carefully. 图片材料文本: Give a REASON if late. 图片材料文本: No drinks near TECHNOLOGY room. 图片材料文本: Wash your paint BRUSH here.""", }, "021601": { "first": [ I("021601-00.png","What is the new record in?", ["Run","Jump","Swim"],[1], "体育公告上写着 New school RECORD in jump,跳高破了新纪录。"), I("021601-01.png","What is the big event?", ["Sports day","Exam day","Book day"],[0], "公告上写着 Sports day — a big EVENT,运动会是件大事。"), I("021601-02.png","Who must you have to enter?", ["A friend","A teacher","A parent"],[1], "门上写着 Do not ENTER without teacher,没有老师不能进。"), I("021601-03.png","When should you return books?", ["By Monday","By Friday","By Sunday"],[1], "图书馆通知上写着 RETURN books by this Friday,周五前还书。"), I("021601-04.png","What should you sort?", ["Paper and food","Paper and glass","Glass and water"],[1], "回收标识上写着 Please SORT paper and glass,请把纸和玻璃分开。"), ], "second": [ I("021601-05.png","What colour is the handbag?", ["Blue","Red","Green"],[1], "失物招领上写着 Lost: red HANDBAG near playground,丢了红色手提包。"), I("021601-06.png","What is not allowed here?", ["Camera","Books","Shoes"],[0], "展馆标识上写着 No CAMERA in this room,此房间不许拍照。"), I("021601-07.png","When does the park gate close?", ["At seven","At eight","At nine"],[1], "公园标牌上写着 Park GATE closes at eight,大门8点关闭。"), I("021601-08.png","How long to fix a wheel?", ["10 minutes","30 minutes","60 minutes"],[1], "车店标牌上写着 Fix your WHEEL in 30 minutes,30分钟修好轮子。"), I("021601-09.png","Where is the main entrance?", ["South side","East side","North side"],[2], "大楼标识上写着 Main ENTRANCE on north side,主入口在北边。"), ], "desc": """1. 图片材料文本: New school RECORD in jump! 图片材料文本: Sports day — a big EVENT. 图片材料文本: Do not ENTER without teacher. 图片材料文本: RETURN books by this Friday. 图片材料文本: Please SORT paper and glass. 2. 图片材料文本: Lost: red HANDBAG near playground. 图片材料文本: No CAMERA in this room. 图片材料文本: Park GATE closes at eight. 图片材料文本: Fix your WHEEL in 30 minutes. 图片材料文本: Main ENTRANCE on north side.""", }, "021701": { "first": [ I("021701-00.png","Who should you not talk to?", ["The driver","The guard","The teacher"],[0], "公交标牌上写着 Do not talk to the DRIVER,不要和司机说话。"), I("021701-01.png","Where should you look both ways?", ["At school","On the street","At home"],[1], "安全海报上写着 Look both ways on the STREET,过街道要左右看。"), I("021701-02.png","When is the farmers' market?", ["Every Monday","Every Saturday","Every Sunday"],[1], "市场标牌上写着 Farmers' MARKET every Saturday,每周六有农夫市集。"), I("021701-03.png","Where can you get a guidebook?", ["At this desk","At the gate","In the shop"],[0], "咨询台标牌上写着 Free GUIDEBOOK at this desk,此处免费领指南。"), I("021701-04.png","What time does shopping start?", ["At 10 a.m.","At 11 a.m.","At 12 p.m."],[0], "商场标牌上写着 SHOPPING hours: 10 a.m. to 8 p.m.,购物10点开始。"), ], "second": [ I("021701-05.png","Where is the washing machine?", ["On first floor","On second floor","Outside"],[0], "洗衣房标识上写着 Washing MACHINE on first floor,洗衣机在一楼。"), I("021701-06.png","What should you draw?", ["Your school","Your family","Your pet"],[1], "美术社通知上写着 DRAW your family for the show,画你的家人参展。"), I("021701-07.png","When is basketball practice?", ["At three","At four","At five"],[1], "体育通知上写着 BASKETBALL practice at four today,今天四点篮球训练。"), I("021701-08.png","Where should you put the books?", ["On the desk","On the bookcase","On the floor"],[1], "图书馆标识上写着 Put books on the BOOKCASE,把书放回书柜。"), I("021701-09.png","When is the science fair?", ["On Friday","On Monday","On Wednesday"],[1], "科学展标识上写着 Show your INVENTION on Monday,周一展示你的发明。"), ], "desc": """1. 图片材料文本: Do not talk to the DRIVER. 图片材料文本: Look both ways on the STREET. 图片材料文本: Farmers' MARKET every Saturday. 图片材料文本: Free GUIDEBOOK at this desk. 图片材料文本: SHOPPING hours: 10 a.m. to 8 p.m. 2. 图片材料文本: Washing MACHINE on first floor. 图片材料文本: DRAW your family for the show. 图片材料文本: BASKETBALL practice at four today. 图片材料文本: Put books on the BOOKCASE. 图片材料文本: Show your INVENTION on Monday.""", }, "021801": { "first": [ I("021801-00.png","What time does the library close?", ["At 2 p.m.","At 4 p.m.","At 6 p.m."],[1], "图书馆通知上写着 LIBRARY open 8 a.m. to 4 p.m.,下午4点闭馆。"), I("021801-01.png","Where can you read the magazines?", ["At home","Here only","In the park"],[1], "阅览室标牌上写着 New MAGAZINEs — read here only,杂志仅供此处阅读。"), I("021801-02.png","What is on at three?", ["A film","A cartoon","A play"],[1], "TV室标牌上写着 CARTOON at three this afternoon,下午三点播动画片。"), I("021801-03.png","When is the English test?", ["Friday morning","Monday afternoon","Wednesday evening"],[0], "考试通知上写着 English TEST on Friday morning,周五上午英语考试。"), I("021801-04.png","How should you read the instructions?", ["Quickly","Carefully","Slowly"],[1], "实验室标牌上写着 Read CAREFULLY before you start,开始前仔细阅读。"), ], "second": [ I("021801-05.png","What does the toy need?", ["A new book","A new battery","A new bag"],[1], "玩具上贴着 This toy needs a new BATTERY,玩具需要新电池。"), I("021801-06.png","Where is the reading corner?", ["On the right","On the left","In the middle"],[1], "图书馆标牌上写着 Reading CORNER on the left side,阅读角在左边。"), I("021801-07.png","When is the school play?", ["On Friday","On Saturday","On Sunday"],[1], "校公告上写着 Play at the THEATRE this Saturday,周六剧院有演出。"), I("021801-08.png","What should you not climb?", ["The wall","The stairs","The park trees"],[2], "公园警示牌上写着 Do not CLIMB the park trees,不要爬公园的树。"), I("021801-09.png","When is lunch today?", ["At midday","At one","At two"],[0], "食堂通知上写着 Lunch is at MIDDAY today,今天中午十二点午饭。"), ], "desc": """1. 图片材料文本: LIBRARY open 8 a.m. to 4 p.m. 图片材料文本: New MAGAZINEs — read here only. 图片材料文本: CARTOON at three this afternoon. 图片材料文本: English TEST on Friday morning. 图片材料文本: Read CAREFULLY before you start. 2. 图片材料文本: This toy needs a new BATTERY. 图片材料文本: Reading CORNER on the left side. 图片材料文本: Play at the THEATRE this Saturday. 图片材料文本: Do not CLIMB the park trees. 图片材料文本: Lunch is at MIDDAY today.""", }, } # ==================== BUILD & WRITE ==================== def build(qid): def qset(qs): return [{ "questionImage": q["questionImage"], "question": q["question"], "options": q["options"], "answer": q["answer"], "ability": AB, "explanation": q["explanation"], } for q in qs] return { "first": {"category": "reading", "type": "reading_matchInfo", "questionSetID": qid, "questionSet": qset(DATA[qid]["first"])}, "second": {"category": "reading", "type": "reading_matchInfo", "questionSetID": qid, "questionSet": qset(DATA[qid]["second"])}, } # === STEP 1: Create empty records === token = get_token() print("=== Step 1: Create empty records ===") new_rids = {} for qid in sorted(DATA): r = requests.post( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{TOKEN_APP}/tables/{TBL}/records", headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, json={"fields": {"题目集合 ID": qid, "dataStatus": "0"}}) new_rids[qid] = r.json()["data"]["record"]["record_id"] print(f" {qid}: {new_rids[qid]}") time.sleep(0.5) # === STEP 2: Wait for automation === print("\n=== Step 2: Wait 35s ===") time.sleep(35) # === STEP 3: PUT jsonData === print("\n=== Step 3: PUT jsonData ===") token = get_token() for qid in sorted(new_rids): j = build(qid) js = json.dumps(j, ensure_ascii=False) r = requests.put( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{TOKEN_APP}/tables/{TBL}/records/{new_rids[qid]}", headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, json={"fields": {"jsonData": js}}) print(f" {qid}: json={len(js)}chars code={r.json().get('code')}") time.sleep(0.5) # === STEP 4: Wait then PUT 图片描述 === print("\n=== Step 4: Wait 15s + PUT 图片描述 ===") time.sleep(15) token = get_token() for qid in sorted(new_rids): r = requests.put( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{TOKEN_APP}/tables/{TBL}/records/{new_rids[qid]}", headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}, json={"fields": {"图片描述": DATA[qid]["desc"]}}) print(f" {qid}: desc code={r.json().get('code')} len={len(DATA[qid]['desc'])}") time.sleep(0.5) # === STEP 5: Final verify === print("\n=== Step 5: Wait 20s + Verify ===") time.sleep(20) token = get_token() for qid in sorted(new_rids): r = requests.get( f"https://open.feishu.cn/open-apis/bitable/v1/apps/{TOKEN_APP}/tables/{TBL}/records/{new_rids[qid]}", headers={"Authorization": f"Bearer {token}"}) fields = r.json()["data"]["record"]["fields"] jd = fields.get("jsonData", "") desc = fields.get("图片描述", "") or "" try: j = json.loads(jd) fq = len(j["first"]["questionSet"]) sq = len(j["second"]["questionSet"]) ok = (fq == 5 and sq == 5 and len(desc) > 100) print(f" {'✅' if ok else '❌'} {qid} ({new_rids[qid]}): {fq}/{sq}q desc={len(desc)}chars") except Exception as e: print(f" ❌ {qid}: {e}") print("\nDone.")