#!/usr/bin/env python3 """ 英文台词优化 & 回填脚本 基于 MEMORY.md 的「对话台词优化通用规则」对列 E(编剧台词)进行优化,写入列 F 知识点:grandmother, grandfather, visit (v.), today (n.) 句型知识点:... visit+sb, Today is... """ import json, subprocess, sys # Rules: # 0. 知识点词汇/句型必须保留 (grandmother/grandfather/visit/today / Today is... / ...visit+sb) # 1. 精简:删除冗余 # 2. 口语化:自然对话,低龄友好,增语气词 # 3. 拆分:>8词拆为2-3短句 # 4. 情绪匹配:匹配角色情绪 # 5. 场景适配:不重复画面信息 # 6. 单句≤10词,知识点句≤7词 # Knowledge-point words to preserve KP_WORDS = {"grandmother", "grandfather", "visit", "today", "today's"} # Mapping: (row_index_0based_sheet) → optimized F value # Only rows where D (role) and E (script line) are non-null # Row index = sheet row - 1 (0-based from API) # Sheet row 1 = header → skip # Sheet row 2 = API row index 1 optimizations = {} def add(row_sheet, f_value): """row_sheet is 1-indexed sheet row number""" optimizations[row_sheet - 1] = f_value # convert to 0-indexed # === SECTION 1: 开场 - 门口 === add(3, "Open up!") add(4, "Your letter is here!") add(6, "Nobody answers?") add(7, "Alright... I'll go in myself.") add(9, "Whoa! What a mess!") add(11, "What's wrong?") add(12, "Vicky? Can you hear me?") # === SECTION 2: 发现家里很乱 === add(14, "Today is a No-Mom-and-Dad day!") # 知识点 Today is add(15, "Our parents aren't home!") # 精简 + 口语化 add(16, "So we can do whatever we want!") add(17, "Really?") add(19, "Yes!") add(20, "Today is a good day!") # 知识点 Today is add(21, "Huh?") add(22, "Are you sure today is a good day?") # 知识点 today # === SECTION 3: 撞到用户,道歉 === add(23, "So on a good day, nobody says sorry?") # 精简 14→8词 add(24, "Eva, Peter, say sorry.") add(25, "Okay. We're sorry.") # 口语化 # === SECTION 4: 继续对话 === add(27, "Ah, kids.") add(28, "Come visit us!") # 知识点 visit,修正"Welcome to visit us"不自然表达 add(29, "Oh, I'm not here to visit.") # 知识点 visit,口语化 add(30, "I'm here to give you something.") # 口语化 # === SECTION 5: 电话 === add(33, "Hello? Grandfather and grandmother, how are you?") # 知识点 grandfather/grandmother add(34, "Good, good! We're great!") # 口语化 add(35, "How are you all, my lovely grandchildren?") add(36, "We're great! Today is so much fun!") # 知识点 Today is, 口语化 add(37, "Great to hear that!") add(38, "Are you ready for us?") # 精简 add(39, "I'm so excited to visit you all!") # 知识点 visit, 口语化 add(40, "Sure! When will you visit us?") # 知识点 visit add(41, "Today is the day, of course!") # 知识点 Today is add(42, "What? You're both coming today?") # 口语化修复 add(43, "Yes! Me and Justin. Your grandmother and grandfather.") # 知识点, 修正 typo gandfather add(44, "We sent you a letter. Remember?") # 口语化 add(45, "See you later!") add(46, "I love you! Bye!") # === SECTION 6: 惊慌 === add(48, "Oh no! What did they say on the phone?") # 修正语法 in→on add(50, "Your grandfather and grandmother are coming to visit you!") # 知识点, 修正 is→are add(51, "On your good day.") # === SECTION 7: 紧急动员 === add(54, "Eva! Peter! Alex! We're in trouble!") # 口语化 add(56, "What happened?") add(57, "Grandfather and grandmother are coming to visit us!") # 知识点, 修正 is→are add(58, "So what?") add(59, "Today! Right now!") # 精简 On today→Today add(62, "No, not today...") # 修正 on today→today add(63, "Look at this place!") # === SECTION 8: 用户互动 === add(65, "Yes, today is a total mess.") # 知识点 today add(66, "It's not the best day for visitors.") # 知识点 visit→visitors 可接受变体, 口语化 add(68, "They could be here at any minute!") # 口语化 # === SECTION 9: 爷爷奶奶会生气 === add(70, "How will they feel about this?") add(72, "Grandfather and grandmother will be so upset!") # 知识点, 精简 mad→upset (正向引导) add(74, "What should we do?") add(76, "Don't worry! I'll help you clean up!") # 增加具体动作词 add(77, "Okay, first pick up the toys from the floor.") # === SECTION 10: 收拾 === add(80, "Oh no! No time to put these away!") # 精简 add(81, "Put them in the cupboard!") # 修正 it→them (玩具是复数) add(83, "Your grandfather and grandmother won't see!") # 知识点 add(85, "Good idea!") add(88, "All done!") add(89, "We need to clean the floor!") add(90, "I'll do it!") # 口语化 # === SECTION 11: 扫地机器人 === add(94, "Will Grandfather and Grandmother be happy?") # 知识点, satisfied→happy (低龄词) add(95, "Well... this will do for now.") # 口语化 add(96, "Before your grandfather and grandmother come to visit.") # 知识点 # === SECTION 12: 沙发污渍 === add(99, "Alex! The sofa is a mess!") # 精简, 正向化 (不说 you made it dirty) add(100, "I'll clean it.") # 口语化 add(103, "I can't get the chocolate off!") add(104, "I'm good at many things. Just not housework!") # 拆分 >8词, 口语化 # === SECTION 13: 更乱 === add(106, "Oh no! We can't clean up in time!") # 精简+口语化 add(107, "I wish we had more time for this!") add(108, "Why today, of all days?") # 口语化 add(109, "I don't want them to see our house like this.") # 口语化修正 add(110, "Why didn't they tell us earlier?") # 口语化修正 # === SECTION 14: 信 === add(113, "I think they did tell you...") # 精简+口语化 add(114, "In this letter.") add(116, "What is in this letter?") # === SECTION 15: 核心互动-听力 (Justin念信) === add(119, "Hi, your grandfather is writing this letter.") # 知识点 grandfather add(120, "I will come to visit you guys.") # 知识点 visit add(121, "Your grandmother will visit you too!") # 知识点 grandmother, visit add(122, "We love you, see you soon!") # === SECTION 16: 反应 === add(124, "They were so happy to visit you!") # 知识点 visit add(125, "Yes. We should be happy too.") add(127, "We should not be grumpy like this.") add(128, "Let's do something to welcome them!") # 口语化 add(130, "You can make something they like!") # 知识点, 精简 add(131, "What is their favourite food?") # === SECTION 17: 苹果派 === add(133, "Grandmother likes apples.") # 知识点 grandmother, 修正 apple→apples add(134, "Grandfather likes pie.") # 知识点 grandfather add(135, "Then you can make apple pie for them!") add(136, "I remember the recipe.") add(137, "I can fix the cooking robot.") add(139, "Okay! Apple pie is today's welcome gift!") # 知识点 today # === SECTION 18: 完成了 === add(142, "You did it!") # 口语化 (替换 You finished) add(143, "Now we just wait for them to arrive.") # 精简 # === SECTION 19: 爷爷奶奶来了 === add(146, "They're coming!") # 口语化 add(148, "Who wants a big hug from Grandfather?") # 知识点, 修正语法 add(149, "Me! Me!") add(150, "Who wants Grandmother's homemade candy?") # 知识点, 修正 grandmother→Grandmother's, handmade→homemade(低龄) add(151, "Me! Me!") add(153, "We made something for you.") add(154, "Mmm! What's that smell? Is that a pie?") # 口语化 add(155, "I smell apples!") # 修正 apple→apples add(156, "Whoa! I know that smell! Apple pie!") # 口语化 add(157, "That is our favourite!") add(159, "Oh, you have a friend over!") # 修正 in home→over add(161, "Hello! I am here to visit Vicky.") # 知识点 visit add(162, "Nice to meet you again!") add(163, "I guess you helped out today too.") # 知识点 today, 口语化修正 # === SECTION 20: 结尾 === add(165, "Today seems pretty busy.") # 知识点 today add(167, "Yes, we made a little mess before you came.") # 知识点 visit, 口语化修正 add(168, "Today was not easy.") # 知识点 today, 修正时态 is→was add(170, "That's okay.") # 口语化 add(172, "Grandfather and Grandmother can fix anything.") # 知识点, 口语化 everything→anything add(173, "That's what family is for!") # 口语化重构 add(174, "Mess or not, we love seeing you!") # 口语化重构 # Print summary and build write payload print(f"Total lines to write: {len(optimizations)}") # Build values payload per row # We need to identify continuous ranges for efficiency # But since the API supports writing individual ranges, let's batch by nearby rows # Sort by row index sorted_rows = sorted(optimizations.items()) # Build the complete column F data: for each row, either the optimized value or empty string ("") # We need all rows 2-149 (sheet rows) all_values = [] for row_idx in range(1, 150): # 1 = sheet row 2, 149 = sheet row 150 if row_idx in optimizations: all_values.append([optimizations[row_idx]]) else: all_values.append([""]) # Write back - use PUT to write the entire column at once # We write empty strings for non-dialogue rows to clear previous content import os import json as jmod app_id = "cli_a931175d41799cc7" config_path = "/root/.openclaw/credentials/xiaoyan/config.json" with open(config_path) as f: cfg = jmod.load(f) app_secret = cfg["apps"][0]["appSecret"] # Get token result = subprocess.run([ "curl", "-s", "-X", "POST", "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", "-H", "Content-Type: application/json", "-d", jmod.dumps({"app_id": app_id, "app_secret": app_secret}) ], capture_output=True, text=True) token = jmod.loads(result.stdout)["tenant_access_token"] spreadsheet_token = "DA7csROG6hmnQMt59oScOLRfnWc" sheet_id = "Nr3Ovs" # Write in batches of 50 rows to avoid too-large payloads batch_size = 50 for batch_start in range(0, len(all_values), batch_size): batch = all_values[batch_start:batch_start + batch_size] # Sheet rows: batch_start + 2 to batch_start + 1 + len(batch) start_row = batch_start + 2 end_row = batch_start + 1 + len(batch) range_str = f"{sheet_id}!F{start_row}:F{end_row}" payload = { "valueRange": { "range": range_str, "values": batch } } result = subprocess.run([ "curl", "-s", "-X", "PUT", f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/values", "-H", f"Authorization: Bearer {token}", "-H", "Content-Type: application/json", "-d", jmod.dumps(payload) ], capture_output=True, text=True) resp = jmod.loads(result.stdout) print(f"Batch F{start_row}:F{end_row} → code={resp.get('code')}, msg={resp.get('msg')}") if resp.get("code") != 0: print(f" ERROR: {result.stdout[:200]}") sys.exit(1) print("All batches written successfully!")