长江雨课堂 コーススライドダウンロード&復習概要生成
重要:LLMの行動境界
本スキルは、ブラウザMCPとローカルスクリプトの役割を厳密に区別します。以下の境界を遵守し、越権操作を禁止します。
chrome-devtools-mcpで許可されること(限定)
https://changjiang.yuketang.cn/を開き、ログイン状態を確認する。- ユーザーが未ログインの場合、ログインを促し、ユーザーの確認を待つ。
- ログイン後にCookieを取得する:
- 優先:DevTools Networkリクエストヘッダーから
Cookieフィールドを読み取る(HttpOnlyを含む全てのCookieを取得可能)。 - リクエストヘッダーで取得できない場合、非HttpOnlyの
document.cookieを読み取るフォールバックを使用する。 - スクリプトでは完了できない複雑/曖昧なタスクを処理する(例:ページのCAPTCHA、ユーザーが手動でクリックする必要があるポップアップ、ブラウザ独自のログインフロー)。
- 優先:DevTools Networkリクエストヘッダーから
- スクリプトでは完了できない複雑/曖昧なタスクを処理する(例:ページのCAPTCHA、ユーザーが手動でクリックする必要があるポップアップ、ブラウザ独自のログインフロー)。
chrome-devtools-mcpで禁止されること
- コース一覧、授業一覧、PPT抽出などのAPIを呼び出し、レスポンスデータをビジネス情報として読み取ること。
- ページング、スクリーンショット、ページHTMLの解析を行い、コース/授業/PPTデータを取得すること。
- 画像を直接ダウンロードすること。
- 復習概要を直接生成または変更すること。
- ブラウザを使ってAPIの正しさを繰り返しプローブすること。
これらのタスクは scripts/bootstrap.js を使用して実装する必要があります。 具体的なAPI一覧は 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はスキルディレクトリ内の
tmp/manifest.jsonに(上書きで)書き込み、コマンド内でパス参照してください。CookieはRAIN_COOKIES環境変数で渡します。tmp/は.gitignoreに含まれているため、バージョン管理には入りません。
スクリプトが明示的に手動処理(CAPTCHA、ユーザーがブラウザで選択する必要がある場合など)を必要とする場合のみ、再度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をファイルに書き込むようユーザーに要求したり、スキルがKeyをディスクに書き込んだりすることを禁止する。
- 環境変数
-
ユーザーがダウンロード/要約するコース名を明示的に指定していることを確認する。
クイックスタート
全てのコマンドは、現在のClaude Code / OpenCodeプロジェクトルートで実行し、スキルディレクトリへの相対パスでスクリプトを呼び出します。scripts/bootstrap.js は自動的にプロジェクトルートを作業ディレクトリとみなします。そのため:
- 相対パスの
--manifest、-o、--course-dir、--lesson-dirなどの引数は全てプロジェクトルートを基準に解決され、パスの重複は発生しません。 --outputを指定しない場合、デフォルトのダウンロードディレクトリはプロジェクトルートのrain-class-reviewer-downloads/以下に生成され、スキルのインストールディレクトリの下ではありません。
初回呼び出し時、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プロジェクトレベルスキルのパスが .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を使用して、次のURLにナビゲートする:https://changjiang.yuketang.cn/- ページが既に読み込まれている場合、
type=reloadを使用して同じURLをリロードし、新しいネットワークリクエストを生成する:mcp__chrome-devtools__navigate_page: type=reload, url=https://changjiang.yuketang.cn/
2.2 Cookieを含むネットワークリクエストを1つトリガーする
ページのリロード後、ブラウザは自動的に複数のCookieを含むリクエストを生成することがよくあります。十分なリクエストが現れない場合、必ず以下のURLを能動的にトリガーする必要があります:
優先トリガーURL(このURLはスクリプトの後続の verify-auth / list-courses で使用されるコース一覧APIと完全に一致し、安全で再利用可能です):
GET https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2
トリガー方法(いずれかを選択。リクエストトラフィックを生成するためだけに使用し、レスポンスの業務データを読み取ることは禁止):
- 方法A:ページリフレッシュを1回実行する(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など)
禁止:他の雨课堂サブドメインやサードパーティAPIを使用してCookieをプローブすること。
2.3 NetworkリクエストヘッダーからCookieを読み取る
list_network_requestsを呼び出し、最近のリクエストを表示する。- リクエストリストから、以下の優先順位で1つのリクエストを選択する:
- 優先:
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 自動モードに関する特別な注意
本スキルの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はスキルディレクトリ下の
tmp/manifest.jsonに上書き書き込みします。Manifestにcookiesフィールドを含めてはなりません。tmp/は.gitignoreに含まれているため、バージョン管理には入りません。 - Cookieは
RAIN_COOKIES環境変数でのみ渡します。cookies.jsonを個別に保存しないでください。 - ダウンロードディレクトリ
rain-class-reviewer-downloads/と一時ディレクトリtmp/は.gitignoreに含まれています。
既知の制限
- ツールは優先的に新しい
lesson-summary+presentationAPIを使用して完全なPPTを取得します。利用できない場合は自動的にreviewAPIにフォールバックしますが、後者は授業中に表示されたスライドのみを含みます。 - 要約機能はMiMo API Keyに依存し、
MIMO_TP_API_KEY環境変数で渡す必要があります。ファイルへの書き込みは禁止されています。
参考
references/yuketang-api.md:长江雨课堂API一覧と制約。references/manifest.example.json:Manifest完全な例。docs/usage.md:CLI完全なパラメータ説明。docs/implementation.md:実装の詳細。