raytency’s diary

画像とテーブルはそのうち上げます

nodejsでairreserveの非公式APIを叩く

※ソフト公開 github.com

↑これを作った時のメモ書きです

背景

わたしがお世話になっている仕事先の一つに塾的なものがあるんですが、そこの授業日程はairreserveで管理しています。 無料枠で出来る予約数が比較的多いのと、多くの親御さんがリクルートIDをすでに持っている(多分ホットペッパーのアプリで登録しているよう?)なので重宝しています。

ところで私はGoogle Calenderで予定を管理しているわけですが、airreserveには連携機能がありません。これはいただけませんね。

というわけでairreserveから予約データを取得できるようにしましょう。

目標

「こっちが予めコマを設定するタイプのカレンダー」(airreserveには現在2つのカレンダータイプがある)のコマ情報(時間/コマ名/予約数/定員)を取得する

下ごしらえ

nodejsは入っているとして、以下のパッケージを利用する

http client

cookie support

html parser

  • cheerio(html parser) ※ログイン画面のパースにのみ使用

AxiosのCookieJar対応

後述するログインページをGETしたときに、一緒にCookieの認証情報も飛んでくる。

これを持たないままフォームのPOSTなどを行っても認証エラーで弾かれるので、Cookieを保存できるようHttpクライアント用CookieJarを追加する。

なお、axiosCookieJarSupportを使うのが最善かは謎。今のところ(2020/01/26)脆弱性アラートは上がってこないのでメンテされてると思う。

const axios_ = require('axios').default
const cheerio = require('cheerio') 
const axiosCookieJarSupport = require('axios-cookiejar-support').default
const tough = require('tough-cookie')

const axios = axios_.create({withCredentials: true})
axiosCookieJarSupport(axios)
axios.defaults.jar = new tough.CookieJar()
//以降、普通にaxiosを使う 

ログイン

ここではAPIアクセスに必要な下記情報を取得するため、通常のログインと同等の操作をaxiosで行う。

ログイン画面の取得

ログインフォームの送信を行うにはユーザー名/パスワードの他にCSRFトークンが必要なので、(いきなりフォーム情報をPOSTするのではなく、)画面をGETする必要がある。

f:id:raytency:20200201102126p:plain

ただログイン画面のURL

connect.airregi.jp/login 

に直接アクセスすると、コームバック先が無くてエラーが出るので、

airreserve.net/reserve/calendar/ 

などにアクセスし、リダイレクトしてもらう。

フォーム

アクションURL

フォームのActionは相対パスだが、アクセスしたurlとは違うホスト名なのでリダイレクトされたアドレスをaxiosのresponceから取得する。

ホスト名のみ取得したい場合はURLクラスに入れるとよしなにパース

url = new URL(response_get.config.url) 
url.host // 'connect.airregi.jp' 

要素

HTMLからフォーム要素を全部取ってくる (フォームの送信要素以外(type='submit'のボタンとか)は入れないようにする) Username/passwordはプログラム上で設定

フォーム形式のPOST

axiosでそのままPOSTすると、コンテンツタイプがJSONなので、なんとかする。

github.com

qiita.com

api-tokenの取得

ここまでやると、calenderページのhtmlが取得出来る。

calenderページに埋まっているapi-tokenはidがついているので#api-tokenで取得出来る。

非公開APIを叩く

基本作法

GET

POST

ヘッダにapi-token

指定期間のコマを取得

コマ情報の取得

ユーザー情報の取得