このプロジェクトについて
ClassSniperは、予約ウィンドウが開いた瞬間にジムのクラスを予約するための個人用オートメーションプロジェクトです。オーストラリアの特定のジムチェーン(One Playground)を対象としており、クラスの予約は開始時間のちょうど72時間前に開始されます。人気の枠やインストラクターは数分で埋まってしまうため、このツールが有効に機能します。このリポジトリは、自身のアカウントや施設に合わせて調整可能なテンプレートとして提供されています。
動作原理
- 外部のcronサービスが60秒ごとにリポジトリのworkflow_dispatchエンドポイントを呼び出します。実行ごとに、キューにある予約の72時間ウィンドウが開いたかを確認します。
- ウィンドウが開くと、ボットがクラスを予約します。まず高速なダイレクトAPIパスを試行し、結果が不確定な場合はPlaywrightによる完全なブラウザオートメーションにフォールバックします。
- 併設されたスクレイパーが、同じ頻度ですべてのスタジオ拠点のライブスケジュールを取得します。これにより、ウェブダッシュボードには単なる日時ではなく、実際の今後のクラス(名称、インストラクター、残り枠数)が表示されます。
- 安全ルールとして、開始まで30時間未満のクラスの予約設定や実行はブロックされます。これは、24時間以内のキャンセルに手数料が発生するためです。
アーキテクチャ
リポジトリは、3つのコミット済みJSONファイル(pending_booking.json, status.json, class_list.json)を通じて信頼できる唯一の情報源(source of truth)として機能します。GitHub Pagesダッシュボードがこれらのファイルを直接読み取り(公開されており、閲覧に認証は不要)、リポジトリにスコープされた微細な権限を持つPAT(Personal Access Token)を使用して、GitHub Contents API経由で予約の有効化や削除の変更を書き戻します。GitHub Actionsがスケジューラーを実行し、bot/scraper.pyがスケジュールを更新し、bot/striker.pyが予約を実行します。スクリーンショットと結果の状態はライブのPlaywrightコンテキスト内でキャプチャされるため、失敗してもサイレントに処理されず記録されます。
エンジニアリング上の詳細
- クラスの識別:同じ場所で同じ時間帯に異なるクラスが設定されていることが多いため、日付と時間だけでの照合は曖昧になります。そのため、施設のセッションAPIから取得した固有のbooking_idを使用して正確に照合します。
- 高速パス:施設のJavaScriptバンドルを解析した結果、UIの「予約クリック → サインイン → 確認」というフローは、内部的には2つのHTTPコールであることが判明しました。これらの公開エンドポイントを直接呼び出し、ブラウザフローはテスト済みのフォールバックとして保持しています。
- タイミング:実行タイミングを正確に計算し、直前までスリープさせます。約5秒前にHTTP接続をウォームアップし、その後リクエストを送信します。
- スケジューラーの選択:GitHub Actionsのスケジュールトリガーはベストエフォートであり、負荷状況によって実行間隔が大きく変動することが観察されました。そのため、1分ごとにworkflow_dispatchを叩く外部cronを採用しています。並行実行グループとfetch-rebaseリトライループにより、git pushで競合する重複実行を処理しています。
- 認証情報の衛生管理:PlaywrightのタイムアウトエラーにログインメールアドレスなどのDOM値が含まれる可能性があるため、ログインタイムアウトハンドラーでクリーンなメッセージを生成します。デバッグ用スクリーンショットではメールアドレスやパスワードフィールドをマスクし、公開されるstatus.jsonに書き込む前に、認証情報に一致する箇所を削除する処理を行っています。
- レート制限:高速パスは1回の試行につき最大3リクエストのみを行い、リトライはしません。これにより、フォールバックのログインに予算を残しています。
スタックとセットアップ
Python, Playwright, GitHub Actions、およびGitHub Pages上のフレームワークレスなHTML/CSS/JSで構成されています。導入には、リポジトリのフォーク、GYM_EMAILおよびGYM_PASSWORDシークレットの追加、PagesとActionsの有効化、ダッシュボード用の微細なトークンの提供が必要です。また、組み込みのcronだけでは定時実行に信頼性が不十分であるため、Actionsにスコープされた2つ目のトークンを使用して外部トリガーを設定することが重要です。
範囲
本プロジェクトは、利用者が料金を支払っているサービスの個人アカウントの予約を、そのサービスのウェブサイトが使用しているものと同じ公開インターフェースを用いて自動化するものです。認証のバイパス、他メンバーのデータへのアクセス、または文書化されたレート制限を超える行為は行わないとしています。MITライセンスの下で提供されています。
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.