rsp

返却期限を忘れない (図書館→Googleカレンダー自動同期)

3行でまとめる

  • scarper で貸出資料一覧を取得
  • Google Calendar API で資料ごとに登録・更新・削除
  • AWS Lambda + Cloud Watch で定期実行

貸出資料一覧を取得

Rust で。

  • reqwest で図書館サイトへログインする
    • 今回は HTML Form からの POST を模倣した。
    • reqwest::Client のインスタンスをもって、 Cookie を保持するのが味噌。多分
  • 貸出資料一覧のページに遷移し、得た HTML を scraper に食わせる
    • CSS Selector で目当てのテキスト(タイトルと期限)を取り出す
    • Chrome Developer Tool で、狙った要素について「Copy as CSS Selector」ができるので楽
    • 1つの CSS Selector で複数の要素が得られる場合は Rust のイテレータで全部取り出せる
  • LibraryItem 構造体に詰めて Vec<LibraryItem> で返す
#[derive(Debug)]
struct LibraryItem {
    title: String,
    due_date: chrono::naive::NaiveDate,
}

参考:

Google Calendar API を Rust からいじる

準備

プログラム

let events = reqwest::blocking::Client::new()
    .get(CALENDAR_API_ROOT.to_string() + "events")
    .bearer_auth(access_token)
    .send()
    .unwrap();
  • 全イベントを CalendarItem 構造体につめて Vec<CalendarItem> で返す
#[derive(Debug)]
struct CalendarItem {
    summary: String,
    start: chrono::naive::NaiveDate,
    id: String,
}

参考:

情報反映処理

上の2節の Vec を集めて、

let library_items = get_books_list_from_library();
let calendar_items = get_items_list_from_calendar(&access_token);

各アイテムがこの2つに所属するしかたによってやることを分岐する。

  • library_items になくて、 calendar_items にある ⇒ 返却した資料。 当該 calendar_item の id を使って、削除 API を叩く
  • library_items にあって、 calendar_items にない ⇒ 新しく借りた資料。 登録 API を叩く
  • library_items, calendar_items の両方にある ⇒ 持っている資料。 返却期日が同じならば何もしない。異なるならば、貸出延長が行われているため更新 API を叩く。

定期実行

まずプログラムを AWS Lambda に対応させる。

  • aws-lambda-rust-runtime crate を追加し、 main 関数の interface を合わせる
  • x86_64-unknown-linux-musl 向けにクロスビルドする
    • musl 向けのリンカがなくて失敗したりした
      • musl 向けビルド環境の Docker イメージがあるみたいなので使うと楽かもしれない
    • reqwest で、 OpenSSL ではなく rustls を使うように設定しないといけないはず

AWS Lambda に載せる。

  • Amazon Linux 2 カスタムランタイムの関数を立ち上げる
  • 手元で cargo build --release したバイナリを bootstrap とリネームし、他に必要なファイルを同梱した zip を作る
  • zip を AWS Lambda コンソールからアップロードする
  • 必要に応じてタイムアウト時間を長くする
  • 試しにトリガしてみる

定期実行させる。

  • CloudWatch Events トリガを設定する
    • 10 分毎など

f:id:nor_isio:20220407222653p:plain 窓口で延長処理をすると自動で Google カレンダーに反映される。便利。

参考: