AirPodsを買った

春先にBeats solo2 wirelessが壊れてしまい、充電出来なくなってしまった。カスタマーサポートに電話すると修理代は約15,000円とのこと。 もうすぐ夏になることもあり、着けていて暑くなるヘッドホンのBeatsを直してもあまり利用機会はないなと考え、それならば値段が近いAirPodsを買おうということになった。

しかし、Apple Storeを見ると未だに6週間待ち。
ググってみると以下の記事が出てきた。

mag.app-liv.jp

記事には、Twitterアカウントをフォローすれば良い旨書かれているが、調べてみると入荷時に確実にツイートされていないことが分かった。
なので記事中にある各Apple StoreAirPodsの在庫状況を表示しているサイトを監視して、在庫の状態になったら自分にプッシュ通知を送るようにした。
本当はApple Storeの販売ページを監視したかったが、JavaScriptによる動的なレンダリングがされていたので、あまり作る時間をかけたくなかったので今回はスキップ。

プッシュ通知はIFTTTのMaker Webhooks経由で送るようにした。流れは以下

  1. AirPodsの在庫状況が在庫ありになる
  2. IFTTTのwebhookを叩く
  3. IFTTTからプッシュ通知が来る
  4. Apple Storeにて当日受け取り購入

監視スクリプトはGroovyでサクッと書いて、VPSにcronで毎分ごとに実行するように設定。
Gebスクレイピング、OkHttpでHTTPリクエスト、jSlackでSlackへポストしている。

@Grab('com.github.seratch:jslack:1.0.11')
import com.github.seratch.jslack.Slack
import com.github.seratch.jslack.api.webhook.Payload

@Grab('org.seleniumhq.selenium:selenium-support:2.52.0')
@Grab('org.seleniumhq.selenium:selenium-htmlunit-driver:2.52.0')
@Grab('org.gebish:geb-core:1.1.1')
@GrabExclude('org.codehaus.groovy:groovy-all')
import geb.Browser

@Grab('com.squareup.okhttp:okhttp:2.6.0')
import com.squareup.okhttp.MediaType
import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.Request
import com.squareup.okhttp.RequestBody


def WEBHOOK_URL__IFTTT = System.getenv('WEBHOOK_URL__IFTTT')
def WEBHOOK_URL__SLACK = System.getenv('WEBHOOK_URL__SLACK')
if (!WEBHOOK_URL__IFTTT || !WEBHOOK_URL__SLACK) {
    println 'WEBHOOK_URL required.'
    return
}

// 渋谷、表参道、銀座の在庫状況ページ
def sites = [
        'https://airpods.isinstock.com/locations/apple-4',
        'https://airpods.isinstock.com/locations/apple-5',
        'https://airpods.isinstock.com/locations/apple-6',
]

Browser.drive {

    sites.each { site ->
        go site

        // 最新の在庫状況
        String message = $('.stock-history-listing li', 0).text()
//        println message

        // 在庫ありならIFTTT webhookにリクエスト
        if (message.contains('In stock')) {

            OkHttpClient client = new OkHttpClient();

            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/json"), '{"value1": "AirPods"}'
            );

            Request request = new Request.Builder()
                    .url(WEBHOOK_URL__IFTTT)
                    .post(requestBody)
                    .build();
            client.newCall(request).execute();

            println '' + new Date() + ': posted. site: ' + site
        }
    }

    // Slackと標準出力にログ出力
    def finishedMessage = '' + new Date() + ': finished'
    Payload payload = Payload.builder()
            .channel("#log")
            .username("AirPods checker")
            .iconEmoji(":blush:")
            .text(finishedMessage)
            .build();
    Slack.getInstance().send(WEBHOOK_URL__SLACK, payload)
    println finishedMessage
}

最近の傾向通り、このスクリプトを動かした次の水曜日の朝に銀座に入荷し、すぐにプッシュ通知が来たので難なく買うことが出来た。

P.S.

買った後に気付いたのだが、このTwitterアカウントは正確に呟いていたのでこれを監視すれば楽だった😇

twitter.com

参考