次にアプリケーションサーバとなるここに関して。
アプリケーションサーバ側でもFirebaseが提供する、Firebase Admin SDKと呼ばれるライブラリを利用できる。ただしサポートされるのはNode、Java、Python、C#、Goであり、phpはない。そんなわけで非公式のphp向けライブラリがあるのでそれを使う。どうしてphp版を公式に出さないんですか…どうして…。それはそれとして、php向けライブラリはドキュメントも充実しているのでありがたい。
アプリケーションサーバでやることは、クライアントから渡されたトークン、番組のシリーズIDをデータベースに保存し、番組表の取り込み時に該当するシリーズの最新話を見つけたらPush通知を行う…といった感じである。やること自体は割と簡単。
このシリーズIDとは何かというと。まず番組表は番組枠が列挙してある。番組枠とは時間で区切られた区間のことだ。この枠に番組が収まっている。この仕様から見れば、番組枠の中に複数の番組を入れることも不可能ではないので、データ上も番組枠(slot)にぶら下がっている番組(programs)は配列になっている。
シリーズIDはこのprogramsの各要素に生えているseriesオブジェクトのidプロパティであり、定義がないので断言はできないが、これが配信される作品全体に対して振られたユニークなIDのようである。また同様にprogramsの各要素に生えているepisodeオブジェクトのsequenceプロパティが該当シリーズにおける放送順を示している、ようである。
したがって、データベースにシリーズIDとその最新シーケンスナンバーのセットを保持しておき、番組表を取り込んだ際に照合して追跡中のシリーズでありかつ新しいシーケンスナンバーを持っている番組枠があれば、それが最新話ということになる(実際には、さらにmarkフラグなども見る)。
ところがここでひとつ問題がある。上記のシリーズIDの正規形は\d+-\d+
らしいのだが、ときおりこのフォーマットから外れたものがある。例えばシリーズIDが175-1rthzhecdme
といったものになったり、シーケンスナンバーが20とか80とか突拍子もないものになったりする。これはどうも「仮のシリーズID」的なもので、未来の番組表に初めて現れた最新話とかがこの状態になったりするようだ。そして、実際の配信日になると本来のシリーズIDが割り振られる。
この仕様がどういう意味を持っているのか分からないが、とにかく不完全なシリーズIDは最新話を検知するための足掛かりにならない。そこで、シリーズIDを元にした検知と平行して、タイトルによるヒューリスティックな検知も行うことにする。これは、例えば検知を開始した番組のタイトルを覚えておいて、それと似た感じなら同一シリーズと見なすものだ。似た感じというのはリーベンシュタイン距離とかそんな感じのアレである。
ところでここで使用する番組のタイトルというのは、正確には番組枠のタイトルである。これは配信される作品のタイトルとは独立しているため、物によって【WEB最速・単独最速】だとか【地上波先行・先行配信】だとか、様々な枕詞が付いたりする。これはヒューリスティックな検知にはノイズなので困る。seriesオブジェクトに作品自体のタイトルを示すプロパティが格納されていると嬉しいのだけど。
というわけでAbema.tvの番組表データはいろいろと不思議な点が多い。