※ バチャ、というより非AtCoderの日本語コン、というほうが正いかもしれません。とりあえず、この記事では「バチャ」で進めます。
できたもの
このページを開いて、右下の「+」ボタンを押せば自分のカレンダーに表示されるようになります。
何これ
AtCoder ProblemsおよびMojacoderで開かれているバチャを自動で取得し、カレンダーに追加してくれます。
AtCoderコンテストカレンダー、yukicoderコンテストカレンダーあたりと併用したらいいんじゃないかと思います。
注意点
なんとなく察しがついているかもしれませんが、これを入れるとカレンダーがコンテストで埋まります。非表示設定とかを頑張るか諦めるかしてください。
あと、情報の正確性などは全く保証しません。一部非表示にしているコンテストもあります。(後述)
製作記
発想
今までぼーっと競プロしてきたけど、そろそろ精進もするべきだし、バチャにでも出ようかな〜、でもTwitterの告知見る時には終わってるしな〜、ということで、Googleカレンダーに表示することにしました。
ちょうどTwitterでRustを見かけて、なんか難しそうだけど面白そう、ってことでRustを使いたかったってのもあります。手段の為ならば目的を選ばない、ってやつですね。
製作
まずはコンテストサイトの選定です。とりあえずよくお世話になっているProblemsにバチャ機能があるらしいので、これは表示したいですね。あと、Twitterでよく流れてくるサイトでMojacoderってのがあったので、これもせっかくなので入れておきます。他にも何か良さそうなサイトがあれば教えてください。やる気があったら追加します。
Rustの勉強
なんで全く知らない言語でプロダクト作るんだ、という話は聞きません。ロマンですロマン。
とりあえず、なんか所有権とかいうのがあって、GCを使ってなくて、なぜかメモリ安全なコードが書けるらしい、くらいの認識だったので、公式のチュートリアル(の和訳)を読みました。
途中まで読んで†完全に理解†状態になったので、即プロジェクト作成です。
処理の実装
対象サイトをスクレイピングして、Google CalenderにAPIアクセスを送りつけるCLIになるだろうな、と思ってたので、とりあえずreqwest
を使ってProblemsにアクセスを送るコードを書きました。Chromeの開発者ツールを使ってそれっぽいJSONをGETしに行くコードを書きました。で、なんかアクセス拒否されます。
Postmanでアクセスしたら普通に帰ってくるので、ヘッダーかな? と思い、hyper
に乗り換えてAccept-Encoding: gzip
を追加して送信。とりあえずリクエストは帰ってきました。
でもなんか文字化けするので困ってたんですが、そういえばgzip圧縮ってことよな? と思い、flate2
のGzDecoder
を使って復号してみるとJSONになりました。やったー
Mojacoderは、https://mojacoder.app/_next/data/gFS1O7T42djs1wRKmTHvP/ja/contests.json
(もうアクセスできません)という、いかにも更新時にパスが変わりそうなURLのものがあったので、どうしようかな...手動更新は嫌だな...と思ったのですが、コンテストページのHTMLの下の方に、<script id="__NEXT_DATA__" ... >
という場所があって、その中身がコンテスト情報だったので、少し汚いやり方ですがここを正規表現で取ってくる事にしました。
次にGoogle APIです。どうやら、
- Google Cloud?でアプリ作成
- Calender APIを使えるよう登録
- API Key的な情報がJSONファイルでもらえるので、それを使ってhttpリクエスト(JWT)
- するとOAuthトークンが降りてくるので、実リクエスト時はこれをヘッダーに入れて使う
という感じっぽかったので、色々サイトを調べながら作ってみました。
こことかここがわかりやすかったです。
最後に重複など確認して、まだカレンダーにないコンテストだけ追加して完成です。
ただ、そのまま追加すると、Problemsなどにある超長期コン(2ヶ月くらいのやつとかありますよね)が入ってしまって溢れてしまうので、24時間を超える長さのものや、もう終了したコンテストのことは無視するようにしました。
実行
cronで回すのも面倒だったので、適当にloop {}
の中に1時間sleepをかましています。(あまりにひどい...)
あとはこれを持ってるレンタルサーバーの無料枠(クソスペック)に放り込んで実行して完了です。
バックグラウンドで実行してもらうために、screenコマンドで実行しています。
終わりに
一応作ってみたはいいんですが、忙しくて全然参加できる気がしないんですよね...
ていうわけで供養です。誰かの役に立ってくれると嬉しいですね...