Files
EFAuto/ef_course_loop.py
T
2026-05-21 23:08:35 +08:00

150 lines
4.7 KiB
Python
Executable File
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
"""
EF Course Autopilot — 交互式循环运行脚本
从 token.txt 文件读取 JWT token(默认读取运行目录下的 token.txt)。
token 需从浏览器开发者工具中获取,详见 README.md。
用法示例:
python3 ef_course_loop.py # 默认读取 ./token.txt
python3 ef_course_loop.py --token-file /path/to/token.txt
"""
import argparse
import random
import sys
import time
from ef_course_autopilot import EFCourseAutopilot
def read_token(token_file: str) -> str:
"""从指定文件读取 token(仅支持单行内容)"""
try:
with open(token_file, "r") as f:
token = f.read().strip()
if not token:
print(f"❌ token 文件为空: {token_file}")
sys.exit(1)
print(f" 📄 从文件读取 token ({token_file})")
return token
except FileNotFoundError:
print(f"❌ token 文件不存在: {token_file}")
print(f" 请创建 {token_file} 并将 ef_access_token 粘贴到第一行")
sys.exit(1)
except IOError as e:
print(f"❌ 读取文件失败: {e}")
sys.exit(1)
QUOTES = [
"我的答案是乱编的,但我的坚持是真的",
"孩子不会了,所以孩子放弃了",
"代码替我上课,良心替我请假",
"EF 没教会我英语,但我教会了 EF 怎么跑路",
"我提交的不是答案,是对教育系统的一封情书",
"这门课过了,但我的英语水平还卡在加载中",
"别人是来学习的,我是来给服务器刷数据的",
"如果努力有用的话,我还要写脚本干嘛",
"我和这门课,总得先疯一个",
]
def main():
parser = argparse.ArgumentParser(
description="EF Course Autopilot — 交互式循环运行",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""\
使用示例:
python3 ef_course_loop.py # 默认读取 ./token.txt
python3 ef_course_loop.py --token-file /path/to/token.txt
token.txt 说明:
- 仅能包含一行,即 ef_access_token 的值
- 从浏览器开发者工具中取请求携带的 ef_access_token 内容,手动粘贴
""",
)
parser.add_argument(
"--token-file",
default="token.txt",
help="从文件读取 JWT token(默认: ./token.txt",
)
parser.add_argument(
"--verify-ssl",
action="store_true",
help="启用SSL证书验证(默认禁用)",
)
args = parser.parse_args()
print("=" * 60)
print(" EF Course Autopilot — 交互式循环运行")
print("=" * 60)
while True:
# 1. 从文件获取 token
token = read_token(args.token_file)
# 2. 输入课程数量
while True:
try:
count_str = input("请输入要完成的课程数量: ").strip()
count = int(count_str)
if count <= 0:
print("❌ 数量必须大于 0")
continue
break
except ValueError:
print("❌ 请输入有效数字")
# 3. 循环完成课程
total_success = 0
total_fail = 0
start_time = time.time()
for i in range(count):
print(f"\n{'=' * 60}")
print(f"{i + 1}/{count} 门课程")
print(f"{'=' * 60}")
autopilot = EFCourseAutopilot(
token=token,
skip_on_fail=True,
verify_ssl=args.verify_ssl,
)
try:
success = autopilot.run()
if autopilot.repeat_detected:
print("\n⚠️ 检测到重复课程,自动循环终止。")
print(f"{random.choice(QUOTES)}」 —— 凯特莎")
print(" 请手动完成此课程,完成后重新运行本程序继续后续课程。")
total_fail += 1
break
if success:
total_success += 1
else:
total_fail += 1
except Exception as e:
print(f"\n❌ 课程执行异常: {e}")
total_fail += 1
elapsed = time.time() - start_time
print(f"\n{'#' * 60}")
print(f" 本轮完成!")
print(f" 计划: {count}")
print(f" ✅ 成功: {total_success}")
print(f" ❌ 失败: {total_fail}")
print(f" ⏱️ 耗时: {elapsed:.1f}")
print(f"{'#' * 60}")
# 4. 询问是否继续
again = input("\n是否继续?(y/n): ").strip().lower()
if again != "y":
print("\n程序结束。")
break
if __name__ == "__main__":
main()