#PokemonGO で捕まえたポケモンを呟く Twitter bot を作ってみた

## 序文

Pokemon GO，ようやく日本でもローンチされましたね :tada:

海外勢は
[リバースエンジニアリングしたり][pokemongo-android-re]，
[内部APIをこねくり回したり][pokemongo-map]，
遊んでいるようです

その甲斐あってか，GitHub にはごまんと Pokemon GO 関連のレポジトリがあります

...これは自分もいじくり回して遊ぶしかないな！

よし
**Pokemon GO で捕まえたポケモンを呟く Twitter bot を作ろう:exclamation::exclamation:**

と，思い立って作りました

**試すときには自己責任でお願いします**

## 3846masa/Tweet-PokemonGO-Journal

書いたコードを GitHub に載せておきます

https://github.com/3846masa/Tweet-PokemonGO-Journal

動かすとこんな感じ

https://twitter.com/EBAGmasa_pokego

## tejado/pgoapi

API を叩けるライブラリっぽいものはいろいろありましたが，
なんとなく [tejado/pgoapi] を選んでみました

Dockerfile まで用意されているので，手軽に遊べます

## 方針

ポケモンを捕まえると，ぼうけんノート（英語名：Journal）に記録が残ります
つまり， **ぼうけんノートのデータさえ取れればよさそうです**

## ぼうけんノート

tejado/pgoapi には，あいにく Journal の Example はありませんでした

関数とかを探してみると， [pgoapi.py#L107-L127] に

```py3
def __getattr__(self, func):
    def function(**kwargs):
    
        if not self._req_method_list:
            self.log.info('Create new request...')
    
        name = func.upper()
        if kwargs:
            self._req_method_list.append( { RequestType.Value(name): kwargs } )
            self.log.info("Adding '%s' to RPC request including arguments", name)
            self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
        else:
            self._req_method_list.append( RequestType.Value(name) )
            self.log.info("Adding '%s' to RPC request", name)

        return self

    if func.upper() in RequestType.keys():
        return function
    else:
        raise AttributeError
```

``RequestType.Value`` を追っていくと，
[AeonLucid/POGOProtos - RequestType.proto] にたどり着きます

Pokemon GO の通信は，[Protocol Buffers] を使っているようです

実際にどういったデータが流れているのか，パケットキャプチャしましょう

## パケットキャプチャ

Android のパケットキャプチャは，[こちら][android-packet]を参考にしました

キャプチャするとこんな感じになっていました

[<img width="300" src="https://i.gyazo.com/a24715c103329dda408250e24278a28f.png"/>](https://gyazo.com/a24715c103329dda408250e24278a28f)

なんとなく見ていくと，``801``という数字が気になりますね

[AeonLucid/POGOProtos - RequestType.proto]で探すと，
``SFIDA_ACTION_LOG`` らしいです

tejado/pgoapi のコードと照らし合わせれば，
``api.sfida_action_log()``で何かが得られそうです

（ちなみに，現時点の tejado/pgoapi にある POGOProtos は古いので置き換えましょう）

## ``api.sfida_action_log()``

実行結果はこんな感じ

```py3
{
  'api_url': ...,
  'auth_ticket': { ... },
  'request_id': ...,
  'responses': {
    'SFIDA_ACTION_LOG': {
      'log_entries': [{
        'catch_pokemon': {
          'combat_points': 156,
          'pokemon_id': 114,
          'result': 1
        },
        'timestamp_ms': 1469169999498
      }, {
        'fort_search': {
          'items': [{
            'count': 3,
            'item_id': 1
          }],
          'result': 1
        },
        'timestamp_ms': 1469233607913
      }],
      'result': 1
    }
  },
  'status_code': 2
}
```

おそらく ``fort_search`` が，ポケストップ情報で，
``catch_pokemon`` が，捕獲したポケモン情報でしょう

あとはザックリと，Twitter bot を作るだけですね :muscle:

## おわりに

こういった非公開APIは，ゲームの改ざんのような悪い印象が強いですが，
ログを取るという方面では面白いことができそうな気がしてきます

もちろん， **サーバに負荷をかけるようなことはダメ :no_entry_sign: ですけど**
ちょっと遊んでみるぐらいはよいのではないでしょうか

[pokemongo-android-re]: https://github.com/applidium/PokemonGo_Android_RE
[pokemongo-map]: https://github.com/mchristopher/PokemonGo-DesktopMap
[tejado/pgoapi]: https://github.com/tejado/pgoapi
[pgoapi.py#L107-L127]: https://github.com/tejado/pgoapi/blob/1f25e907f3e5f1b603330e71041e1ad7bee7580f/pgoapi/pgoapi.py#L107-L127
[AeonLucid/POGOProtos - RequestType.proto]: https://github.com/AeonLucid/POGOProtos/blob/1d8400036dccb8dcd41f35e54c0c3206c92128ef/src/POGOProtos/Networking/Requests/RequestType.proto
[Protocol Buffers]: https://developers.google.com/protocol-buffers/
[android-packet]: http://qiita.com/usamao/items/ab9b14f8a5b3810ab406#packet-capture