长江雨课堂课件下载与复习大纲生成
重要:LLM 行为边界
本 Skill 严格区分 浏览器 MCP 与 本地脚本 的职责。你必须遵守以下边界,禁止越界操作。
你可以使用 chrome-devtools-mcp 做的事(仅限)
- 打开
https://changjiang.yuketang.cn/并检查登录状态。 - 在用户未登录时,提示用户完成登录,并等待用户确认。
- 登录后获取 Cookie:
- 优先通过 DevTools Network 请求头读取
Cookie字段(可获取包括 HttpOnly 在内的所有 Cookie)。 - 若请求头中无法获取,可回退到读取非 HttpOnly 的
document.cookie。 - 处理脚本无法完成的复杂/模糊任务(如页面人机验证、需要用户在页面上手动点选的弹窗、浏览器独有的登录流程)。
- 优先通过 DevTools Network 请求头读取
- 处理脚本无法完成的复杂/模糊任务(如页面人机验证、需要用户在页面上手动点选的弹窗、浏览器独有的登录流程)。
禁止使用 chrome-devtools-mcp 做的事
- 调用课程列表、课时列表、PPT 提取等 API 并读取响应数据来获取业务信息。
- 翻页、抓图、解析页面 HTML 来获取课程/课时/PPT 数据。
- 直接下载图片。
- 直接生成或修改复习大纲。
- 用浏览器反复探测接口正确性。
这些任务必须调用 scripts/bootstrap.js 实现。 具体接口清单见 references/yuketang-api.md。
关键区别:用 MCP 读取网络请求的
Cookie请求头属于“获取登录态”,是允许的;用 MCP 读取 API 响应体属于“获取业务数据”,是禁止的。
最小 Manifest 构造后必须停止 MCP
一旦你通过 MCP 拿到 Cookie,立即停止所有 chrome-devtools-mcp 操作。Cookie 只能通过 RAIN_COOKIES 环境变量传给脚本,Manifest 文件只保留课程信息。后续步骤必须交给脚本:
set RAIN_COOKIES={"sessionid":"...","csrftoken":"...","uv_id":"0","university_id":"0","xtbz":"ykt"}
node <skill-path>/scripts/bootstrap.js verify-auth --manifest <skill-path>/tmp/manifest.json校验登录态。node <skill-path>/scripts/bootstrap.js list-courses --manifest <skill-path>/tmp/manifest.json --json获取课程列表。node <skill-path>/scripts/bootstrap.js --manifest <skill-path>/tmp/manifest.json --json下载课件(默认输出到项目根目录的rain-class-reviewer-downloads/)。node <skill-path>/scripts/bootstrap.js summarize --course-dir "rain-class-reviewer-downloads/<课程名>" --force-summary提取笔记并生成复习大纲。
为兼容 Claude Code auto mode 的安全策略,不要把 Manifest 通过 stdin 传入,也不要在 Manifest 文件中写 Cookie。把最终 Manifest 写入 Skill 目录下的
tmp/manifest.json(覆盖写入),并在命令中通过路径引用;Cookie 通过RAIN_COOKIES环境变量传入。tmp/已在.gitignore中,不会进入版本控制。
只有在脚本明确报告需要人工处理(如验证码、需要用户在浏览器里点选)时,才允许再次启用 MCP,且处理完后必须立刻回到脚本流程。
能力概述
- 自动登录态获取:使用 chrome-devtools-mcp 连接浏览器,检查/等待用户登录后自动提取 Cookie(支持 HttpOnly Cookie)。
- 脚本化后续流程:登录态校验、课程发现、课时列表、PPT 下载、Markdown 笔记提取、复习大纲生成全部通过本地脚本完成。
- 过滤下载:支持按日期、课时 ID、最新课时等条件下载。
- Markdown 笔记:每页 PPT 保存为独立 Markdown 文档,包含标题、要点、公式、关键词、核心概念和详细总结。
- 复习大纲:跨页面整合生成
review.md。
前置条件
开始执行前,必须依次完成以下显式检查:
-
检查 Node.js 和 npm
- 运行
node -v,确认主版本号 >= 18。 - 运行
npm -v,确认 npm 可用。 - 任一不满足时,停止并提示用户安装 Node.js >= 18。
- 运行
-
检查 chrome-devtools-mcp
- 尝试调用一次 MCP 浏览器工具(例如
mcp__chrome-devtools__list_pages或mcp__chrome-devtools__navigate_page)。 - 如果 MCP 不可用,停止并提示用户确认 Claude Code / OpenCode 已启用 chrome-devtools-mcp。
- 尝试调用一次 MCP 浏览器工具(例如
-
检查总结所需 API Key(仅在用户要求生成复习大纲时)
- 检查环境变量
MIMO_TP_API_KEY是否存在且以tp-开头。 - 如果已存在,继续执行。
- 如果不存在,向用户询问 MiMo API Key(以
tp-开头)。 - 获得用户提供的 Key 后,在后续所有涉及总结的命令中通过环境变量传入,例如:
set MIMO_TP_API_KEY=tp-xxxx node .claude/skills/rain-class-reviewer/scripts/bootstrap.js summarize --course-dir rain-class-reviewer-downloads/<课程名> - 禁止要求用户把 Key 写入文件,也禁止 Skill 把 Key 写入磁盘。
- 检查环境变量
-
确认用户已明确指定要下载/总结的课程名。
快速开始
所有命令应在当前 Claude Code / OpenCode 项目根目录执行,通过 Skill 目录的相对路径调用脚本。scripts/bootstrap.js 会自动把项目根目录当作工作目录,因此:
- 相对路径的
--manifest、-o、--course-dir、--lesson-dir等参数都以项目根目录为基准解析,不会出现路径重复。 - 不指定
--output时,默认下载目录会生成在项目根目录的rain-class-reviewer-downloads/下,而不是 Skill 安装目录下。
首次调用时 scripts/bootstrap.js 会优先使用预构建的 dist/cli.cjs(已包含 openai 等依赖),无需联网安装;若不存在才会自动 npm install。
完整流程
1. 询问用户课程名(或关键词)。
2. 用 MCP 打开 https://changjiang.yuketang.cn/ 并获取 Cookie(优先从 Network 请求头读取)。
3. 构造最小 Manifest JSON,写入 <skill-path>/tmp/manifest.json。
4. 运行 node <skill-path>/scripts/bootstrap.js verify-auth --manifest <skill-path>/tmp/manifest.json 校验登录态。
5. 运行 node <skill-path>/scripts/bootstrap.js list-courses --manifest <skill-path>/tmp/manifest.json --json 获取课程列表。
6. 根据用户输入匹配课程;有歧义时向用户展示候选并确认 classroomId。
7. 使用课程列表返回的原始 courseName,构造带 classroomId 的 Manifest(覆盖 tmp/manifest.json),运行 node <skill-path>/scripts/bootstrap.js --manifest <skill-path>/tmp/manifest.json --json 下载(默认输出到 rain-class-reviewer-downloads/)。
8. 设置 `MIMO_TP_API_KEY` 后,运行 `node <skill-path>/scripts/bootstrap.js summarize --course-dir "rain-class-reviewer-downloads/<原始课程名>" --force-summary` 生成复习大纲。
示例(Claude Code 项目级 Skill 路径为 .claude/skills/rain-class-reviewer):
node .claude/skills/rain-class-reviewer/scripts/bootstrap.js \
--manifest .claude/skills/rain-class-reviewer/tmp/manifest.json --json
标准执行流程
1. 获取用户期望的课程名
向用户确认课程名,允许使用简称或关键词,例如“计算机网络”。记录用户原始输入,不要立即做任何匹配。
2. 使用 MCP 获取 Cookie
长江雨课堂的 sessionid 通常是 HttpOnly Cookie,无法通过 document.cookie 读取。你必须通过 Chrome DevTools Network 请求头获取,且必须严格使用下面列出的 URL。
2.1 打开长江雨课堂页面
必须导航到的 URL:
https://changjiang.yuketang.cn/
操作步骤:
- 连接浏览器。
- 使用
mcp__chrome-devtools__navigate_page导航到:https://changjiang.yuketang.cn/ - 如果页面已经加载过,使用
type=reload刷新同一 URL,以产生新的网络请求:mcp__chrome-devtools__navigate_page: type=reload, url=https://changjiang.yuketang.cn/
2.2 触发一条带 Cookie 的网络请求
刷新页面后,浏览器通常会自动产生多个带 Cookie 的请求。如果没有出现足够的请求,必须主动触发下列 URL:
首选触发 URL(该 URL 与脚本后续 verify-auth / list-courses 使用的课程列表接口完全一致,安全且可复用):
GET https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2
触发方式(任选其一,仅用于产生请求流量,禁止读取响应业务数据):
- 方式 A:执行一次页面刷新(见 2.1)。
- 方式 B:通过
evaluate_script执行:fetch('https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2', { credentials: 'include' });
备用触发 URL(当首选请求未出现时,任何发往 changjiang.yuketang.cn 的请求均可):
https://changjiang.yuketang.cn/ (页面文档)
https://changjiang.yuketang.cn/v2/web/index (首页入口)
https://changjiang.yuketang.cn/* (同域名下的静态资源,如 JS/CSS)
禁止使用其他雨课堂子域名或第三方接口来探测 Cookie。
2.3 从 Network 请求头中读取 Cookie
- 调用
list_network_requests查看最近的请求。 - 在请求列表中按以下优先级选择一条请求:
- 优先:
https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2 - 次选:
https://changjiang.yuketang.cn/或https://changjiang.yuketang.cn/v2/web/index - 可接受:任何
https://changjiang.yuketang.cn/*请求
- 优先:
- 使用
get_network_request读取该请求的 Request Headers。 - 在请求头中找到
cookie或Cookie字段,解析以下字段:sessionid(必须)csrftoken(建议携带,用于 CSRF 校验)uv_id(按实际值提取,可能是0或其他值)university_id(按实际值提取,可能与uv_id相同或不同)xtbz(通常为ykt)django_language(可选)
示例 Cookie 头:
sessionid=abc123; csrftoken=xyz789; uv_id=0; university_id=0; xtbz=ykt
不要硬编码
uv_id=2874或university_id=2874,必须从请求头中读取实际值。缺失或0都是允许的。
2.4 处理未登录情况
- 如果请求头中没有
sessionid,或请求被重定向到登录页,说明用户未登录。 - 提示用户手动登录长江雨课堂。
- 等待用户回复“已登录”。
- 刷新页面或再次触发
https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2,重新读取 Cookie。
2.5 回退方案
如果 MCP 无法提供请求头中的 Cookie:
- 尝试读取
document.cookie获取非 HttpOnly Cookie(通常至少能拿到csrftoken)。 - 如果仍无法拿到
sessionid,请用户手动提供sessionid,或检查 MCP 是否支持获取 HttpOnly Cookie。 - 无论回退是否成功,最终仍然必须通过 Network 请求头拿到
sessionid。
3. 构造最小 Manifest
{
"version": "1.0",
"courseName": "计算机网络"
}
courseName 使用用户原始输入。此 Manifest 只用于校验和获取课程列表,不保证最终匹配。构造完此 Manifest 后,立即停止 MCP。
Cookie 通过 RAIN_COOKIES 环境变量传入(下同):
set RAIN_COOKIES={"sessionid":"...","csrftoken":"...","uv_id":"0","university_id":"0","xtbz":"ykt"}
4. 校验登录态
set RAIN_COOKIES={...}
node <skill-path>/scripts/bootstrap.js verify-auth --manifest <skill-path>/tmp/manifest.json
- 成功:继续下一步。
- 失败:返回步骤 2,重新获取 Cookie。
5. 获取课程列表
set RAIN_COOKIES={...}
node <skill-path>/scripts/bootstrap.js list-courses --manifest <skill-path>/tmp/manifest.json --json
返回当前账号下所有课程的 classroomId、courseName、className、teacher。
6. 匹配课程并处理歧义
用用户原始输入匹配课程列表:
- 唯一精确匹配:直接使用该
classroomId。 - 无匹配:向用户展示所有可用课程,要求用户指定课程名或
classroomId。 - 多个匹配:向用户展示候选课程(含班级、教师、classroomId),要求用户确认。
禁止擅自选择。 确认后,使用课程列表返回的原始 courseName 构造新的 Manifest,并覆盖写入 tmp/manifest.json:
{
"version": "1.0",
"courseName": "计算机网络",
"classroomId": "13522533"
}
7. 下载课件
set RAIN_COOKIES={...}
node <skill-path>/scripts/bootstrap.js --manifest <skill-path>/tmp/manifest.json --json
8. 提取 Markdown 笔记并生成复习大纲
set MIMO_TP_API_KEY=tp-xxxx
node <skill-path>/scripts/bootstrap.js summarize --course-dir "rain-class-reviewer-downloads/<课程名>" --force-summary
输出:
- 每页 Markdown 笔记:
rain-class-reviewer-downloads/<课程名>/extracted/<课时>/<页码>.md - 整体复习大纲:
rain-class-reviewer-downloads/<课程名>/review.md
按课时过滤下载
只下载最新一次课时:
node <skill-path>/scripts/bootstrap.js --manifest <skill-path>/tmp/manifest.json --latest --json
按日期范围下载:
node <skill-path>/scripts/bootstrap.js --manifest <skill-path>/tmp/manifest.json --since 2023-11-01 --until 2023-11-05 --json
课程名歧义处理
- 若存在多个同名课程,脚本会报错并列出候选
classroomId。 - 禁止擅自选择,必须向用户展示候选课程并要求确认。
- 确认后,在 Manifest 中显式指定
classroomId再调用脚本。
认证失败处理
若脚本返回 403 / 未登录 / 认证校验失败:
- 说明
sessionid已过期或缺失。 - 重新执行步骤 2(使用 MCP 检查/重新登录)。
- 更新
RAIN_COOKIES环境变量。 - 重新运行脚本。
Claude Code 自动模式特别说明
本 Skill 的 Manifest 文件不再包含 Cookie 等凭据;Cookie 只能通过 RAIN_COOKIES 环境变量传递。因此 Write(tmp/manifest.json) 只写入课程名/classroomId,通常可以通过 auto mode 的文件写入检查。
如果 auto mode 仍然拦截写入临时文件,可在当前项目根目录手动创建 .claude/policy.json:
{
"autoMode": {
"allow": [
"Allow writing the rain-class-reviewer skill manifest file at .claude/skills/rain-class-reviewer/tmp/manifest.json, which only contains course name and classroomId.",
"Allow running node .claude/skills/rain-class-reviewer/scripts/bootstrap.js commands for course download and summarization."
]
}
}
所有命令都应附带 RAIN_COOKIES 环境变量:
set RAIN_COOKIES={"sessionid":"...","csrftoken":"...","uv_id":"0","university_id":"0","xtbz":"ykt"}
node .claude/skills/rain-class-reviewer/scripts/bootstrap.js verify-auth --manifest .claude/skills/rain-class-reviewer/tmp/manifest.json
Git Bash / Linux / macOS 使用
export RAIN_COOKIES='...'。
安全与隐私
- 禁止在对话中明文输出完整 Cookie。
- Manifest 写入 Skill 目录下的
tmp/manifest.json,覆盖之前的内容;Manifest 中不得包含 cookies 字段。tmp/已在.gitignore中,不会进入版本控制。 - Cookie 只能通过
RAIN_COOKIES环境变量传递,不要单独保存cookies.json。 - 下载目录
rain-class-reviewer-downloads/和临时目录tmp/已在.gitignore中。
已知限制
- 工具优先使用新版
lesson-summary+presentation接口获取完整 PPT;若不可用会自动回退到review接口,但后者只包含课堂中展示过的幻灯片。 - 总结功能依赖 MiMo API Key,必须通过
MIMO_TP_API_KEY环境变量传入;禁止写入文件。
参考
references/yuketang-api.md:长江雨课堂接口清单与约束。references/manifest.example.json:Manifest 完整示例。docs/usage.md:CLI 完整参数说明。docs/implementation.md:实现细节。