ai_member_xiaoyan/scripts/generate_component_configs.py

445 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Generate component configurations for the script sheet and write them back."""
import json
import subprocess
import sys
# Get bot token
def get_token():
result = subprocess.run(
["jq", "-r", ".apps[0].appSecret",
"/root/.openclaw/credentials/xiaoyan/config.json"],
capture_output=True, text=True
)
app_secret = result.stdout.strip()
import urllib.request
import urllib.parse
data = json.dumps({"app_id": "cli_a931175d41799cc7", "app_secret": app_secret}).encode()
req = urllib.request.Request(
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
data=data,
headers={"Content-Type": "application/json"}
)
resp = json.loads(urllib.request.urlopen(req).read())
return resp["tenant_access_token"]
TOKEN = get_token()
SPREADSHEET_TOKEN = "Dk1fs7TJ4hWs5PtUvXlc1EaEnvb"
SHEET_ID = "fmqYrx"
# Component configurations for each row
# Format: {row_number: config_text}
CONFIGS = {
# Row 12: 图片无序多选 (1217101) - motorbike
12: """【任务标题】
在图片中寻找摩托车
【情境引入】
Ben: Whoa! Those are motorbikes!
User: Where? Let me take a look.
【互动内容】
Find the $motorbikes$ in the picture.(音频)
选项:
00
01
02
答案:
00
01
辅助信息motorbike 指"摩托车"
【互动反馈】
正确 Ben : That's right! Those are two motorbikes!
错误 Ben : Look again. Can you find the motorbikes?
【后置对话】
""",
# Row 30: 对话朗读 (1217102) - people
30: """【任务标题】
询问那些人是谁
【资源配置】
图片时机:无
【情境引入】
【互动内容】
Who are those people?(朗读)
【后置对话】
""",
# Row 46: 对话挖空 (1217103) - people
46: """【任务标题】
向镇长报告发现
【资源配置】
【情境引入】
User: Tom! We found two strange people.
【互动内容】
We found two strange ___.(音频)
选项1people正确
选项2animals
【互动反馈】
正确 Tom : Good! Tell me more about them.
错误 Tom : Animals? Are you sure about that?
【后置对话】
""",
# Row 53: 对话挖空 (1217104) - motorbike
53: """【任务标题】
描述可疑人员的特征
【资源配置】
【情境引入】
Tom: Tell me more about them.
【互动内容】
They're on ___.(音频)
选项1motorbikes正确
选项2bicycles
【互动反馈】
正确 Tom : Good job! I'm coming right now!
错误 Tom : Bicycles? That doesn't sound right.
【后置对话】
""",
# Row 67: 对话朗读 (1217105) - people
67: """【任务标题】
盘问来人身份
【资源配置】
图片时机:无
【情境引入】
【互动内容】
Who are you people?(朗读)
【后置对话】
""",
# Row 81: 对话挖空 (1217106) - show
81: """【任务标题】
要求检查袋子
【资源配置】
【情境引入】
Jay: The bag is a secret!
【互动内容】
You must ___ me what is in the bag!(音频)
选项1show正确
选项2tell
【互动反馈】
正确 Jay : No, no! We can't show you!
错误 Jay : Ha! We won't tell you, either!
【后置对话】
""",
# Row 96: 对话选择 (1217107) - motorbike
96: """【任务标题】
回应 Jay 的炫耀
【资源配置】
【情境引入】
Jay: Let me show you how fast it is!
【互动内容】
要求:选择正确的回复
选项:(音频)
选项1Your motorbike looks really old.(正确)
- 反馈: 无
选项2Your motorbike looks so cool!
- 反馈 Jay : Thank you, kid! But let me show you more!
【后置对话】
""",
# Row 110: 对话朗读 (1217108) - Show...
110: """【任务标题】
要求 Jay 继续展示
【资源配置】
图片时机:无
【情境引入】
【互动内容】
Wow! Show me more!(朗读)
【后置对话】
""",
# Row 122: 对话组句 (1217109) - Show...
122: """【任务标题】
请 Lin 展示摩托车
【资源配置】
【情境引入】
Lin: My motorbike never does that.
【互动内容】
题目:请 Lin 展示她的摩托车
(音频)
选项1Cool
选项2Show
选项3me
选项4your
选项5motorbike
答案Cool! Show me your motorbike!
辅助信息Cool 作感叹词放句首Show me 后接名词表示"给我看看..."
【互动反馈】
正确 Lin : Hmph. Fine.
错误 Lin : What do you want me to show?
【后置对话】
""",
# Row 142: 对话选读 (1217110) - motorbike
142: """【任务标题】
评价谁的摩托车更好
【资源配置】
【情境引入】
Jay: Hey kids! Which motorbike is better?
【互动内容】
要求:选择一个你想表达的观点
选项:
选项1I think the red motorbike is better.
- 反馈 Jay : What? I don't agree!
选项2I think the orange motorbike is better.
- 反馈 Lin : Hey! You're wrong!
【后置对话】
""",
# Row 161: 对话朗读 (1217111) - ... can/can't hold...
161: """【任务标题】
答应帮忙拿袋子
【资源配置】
图片时机:无
【情境引入】
【互动内容】
Okay! I can hold it.(朗读)
【后置对话】
""",
# Row 176: 对话选择 (1217112) - ... can/can't hold...
176: """【任务标题】
回应 Ben 的关心
【资源配置】
【情境引入】
Ben: Are you okay?
【互动内容】
要求:选择正确的回复
选项:(音频)
选项1Don't worry. I can hold it.(正确)
- 反馈: 无
选项2Help! I can't hold it!
- 反馈 Ben : Oh no! Let me help you!
【后置对话】
""",
# Row 192: 对话组句 (1217113) - ... can/can't hold...
192: """【任务标题】
让 Ben 放心你能拿住
【资源配置】
【情境引入】
Ben: Let's see what's inside.
【互动内容】
题目:告诉 Ben 你能拿住袋子,让他放心
(音频)
选项1Don't
选项2worry
选项3I
选项4can
选项5hold
选项6it
答案Don't worry. I can hold it.
辅助信息Don't worry 表示"别担心"can 后跟动词原形表示"能/会"
【互动反馈】
正确 Ben : Ouch!
错误 Ben : What? Are you okay?
【后置对话】
""",
# Row 204: 对话朗读 (1217114) - ... can/can't hold...
204: """【任务标题】
呼救求助
【资源配置】
图片时机:无
【情境引入】
【互动内容】
I can't hold it!(朗读)
【后置对话】
""",
# Row 233: 阅读理解 (1217115) - motorbike/people/hold/show
233: """【任务标题】
向 Tom 描述事情的经过
【情境引入】
Tom: Can anybody tell me what happened here?
【互动内容】
问题1Who came from out of town?
答案These two people.
问题2What did they ride?
答案They ride motorbikes.
问题3What did you ask them to do?
答案Show us what's in their bags.
【后置对话】
""",
# Row 245: 对话选读 (1217116) - ... can/can't hold...
245: """【任务标题】
为自己的失误道歉
【资源配置】
【情境引入】
Lin: And you opened the bags without asking.
【互动内容】
要求:选择一个你想表达的观点
选项:
选项1Sorry, but I can't hold it.
- 反馈 Tom : It's okay. Everybody makes mistakes.
选项2Sorry, I can't hold it anymore.
- 反馈 Tom : It's okay. Everybody makes mistakes.
【后置对话】
""",
}
def write_to_sheet(row, config_text):
"""Write config to a single cell in the sheet."""
import urllib.request
range_str = f"{SHEET_ID}!H{row}:H{row}"
data = json.dumps({
"valueRange": {
"range": range_str,
"values": [[config_text]]
}
}).encode()
req = urllib.request.Request(
f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{SPREADSHEET_TOKEN}/values",
data=data,
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
},
method="PUT"
)
resp = json.loads(urllib.request.urlopen(req).read())
return resp.get("code") == 0
def verify_write(row, expected_prefix):
"""Verify what was written."""
import urllib.request
range_str = f"{SHEET_ID}!H{row}:H{row}"
url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{SPREADSHEET_TOKEN}/values/{range_str}?valueRenderOption=ToString"
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {TOKEN}"})
resp = json.loads(urllib.request.urlopen(req).read())
values = resp.get("data", {}).get("valueRange", {}).get("values", [])
if values and values[0] and values[0][0]:
actual = values[0][0]
if actual.startswith(expected_prefix):
return True, actual[:80]
else:
return False, actual[:80]
return False, "EMPTY"
def main():
success = 0
failed = []
for row, config in sorted(CONFIGS.items()):
try:
ok = write_to_sheet(row, config)
if ok:
prefix = config.strip()[:50].replace("\n", " ")
verified, preview = verify_write(row, prefix[:20])
if verified:
print(f"✓ Row {row}: Written and verified - {preview}...")
success += 1
else:
print(f"⚠ Row {row}: Write reported OK but verification failed: {preview}")
failed.append(row)
else:
print(f"✗ Row {row}: Write failed")
failed.append(row)
except Exception as e:
print(f"✗ Row {row}: Error - {e}")
failed.append(row)
print(f"\n=== Summary ===")
print(f"Success: {success}/{len(CONFIGS)}")
if failed:
print(f"Failed rows: {failed}")
return 0 if not failed else 1
if __name__ == "__main__":
sys.exit(main())