Help us understand the problem. What is going on with this article?

Intercomの会話データぜんぶ抜く

TL;TR

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8

からファイルをダウンロードする。

<YOUR API KEY> の箇所を書き換える。

IntercomのPHPのSDKを同じ階層にcomposer経由でダウンロードする。

composer require intercom/intercom-php php-http/guzzle6-adapter

以下のコマンドで実行する。

php index.php

解説

IntercomのAPIを純粋に片っ端から叩いてデータを集めてきて最後に配列にして1行ずつCSVに書き出しています。

Intercomの画面上から会社やユーザー情報はCSVエクスポートできます。
会話のデータもエクスポートできますが、過去2年分でサマリーのみになるため、細かな会話のやり取りを出力するにはAPIを使う方法しかありません。(個々の会話の画面から plain text でダウンロードするボタンもありますが、件数が多いと大変かと思います。)

処理に時間がかかる

IntercomのAPIはレスポンスがそんなに早くなく、4年ほどの会話データおよそ2万行を抽出するのに10時間くらいかかりました。

RateLimitに引っかかることはなさそう

IntercomのAPIはたまにタイムアウトしてしまいます。

このスクリプトを回してる途中にRateLimitに引っかかるかなと思っていましたが、レスポンスが爆速でもないので引っかからずに最後まで処理できるかと思います。
https://developers.intercom.com/intercom-api-reference/reference#rate-limiting

タイムアウトするなど途中で処理が止まってしまうとまた最初からやり直しになってしまうため、会話データは最後にまとめてではなく1行ずつCSVに書き出すようにしています。

APIの結果をファイルに保存する

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L69

file_put_contents("admins.dat", serialize($admins));

のように配列を全部シリアライズしてファイルに書き出しているのは、途中でタイムアウトして失敗したときはそれ以前のAPIコール部分はファイルをデシリアライズしてそれを代替として使えるようにするためファイルに保存しています。

会話データのhtmlタグ除去

パラメータに 'display_as' => 'plaintext'を指定することでタグが除去されます。

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L124-L126

$result = $client->conversations->getConversations([
    'display_as' => 'plaintext'
]);

IntercomのAPI設計は微妙

ページングの処理が微妙

微妙というか過渡期というか、ページングの処理がまちまちです。

AWSをはじめ多くのAPIの設計が nextToken でページング処理をしていると思いますが、

https://developers.intercom.com/intercom-api-reference/reference#pagination

にあるようにパラメータに page= で渡すパターンが中心です。(v2.3時点)

contactsだけはなぜか

    "next": {
      "page": 4,
      "starting_after": "1HaSB+xrOyyMXAkS/c1RteCL7BzOzTvYjmjakgTergIH31eoe2v4/sbLsJWP\nIncfQLD3ouPkZlCwJ86F\n"
    }

のようにしてページ番号とともにページ送りをするためのトークンがセットされています。

https://developers.intercom.com/intercom-api-reference/reference#pagination-cursor

contacts取得時のページ送りの処理

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L86-L88

    if (! empty($result->pages->next)) {
        $result = $client->contacts->nextCursor($result->pages);
    }

とそれ以外のページ送りの処理

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L109-L111

    if (! empty($result->pages->next)) {
        $result = $client->nextPage($result->pages);
    }

が異なっているのは上記の理由からです。

逆にcontactsではnextPage()が動きません。

Intercom PHP SDK v4.4.2 の nextCursorPage バグ

2020年11月19日 時点での最新版 v4.4.2 には nextCursorPageの処理にバグがあります。

https://github.com/intercom/intercom-php/pull/323

でプルリクが出ていますが、APIを叩いたレスポンスをモデルに変換する処理が二重で行われているためエラーになります。

https://github.com/intercom/intercom-php/pull/323/files

のように修正する必要があります。

メインデータのレスポンスが微妙

管理者ユーザーの一覧データのレスポンスは

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L60-L62

    foreach ($result->admins as $admin) {
        $admins[$admin->id] = $admin->name;
    }

ですが、会社の一覧データのレスポンスは

https://gist.github.com/YoshiteruIwasaki/3edd71eb1d968fcfa4c56ef7a0bcfbd8#file-index-php-L104-L106

    foreach ($result->data as $company) {
        $companies[$company->id] = $company;
    }

だったりして、なぜか $result->admins のようなケースと $result->data のようなケースがあるので注意が必要です。

感想

IntercomのAPI叩いて会話のデータをCSV出力するのなんて世界のどこかに先人がいるだろう、と思っていましたが、Dockerのコンテナ上でCをコンパイルして会話データを取得するっぽいことをしてたりなんやかんやいいのがないので致し方なく自分でスクリプトを組みました。

とりあえず1回きりのデータ全出力、のつもりで作っているのでエラーハンドリングとかは無考慮です。

別にPHPじゃなくてPerlやRuby,Pythonでもいいんですが(JavaとNodeは下準備が多いので却下)
https://developers.intercom.com/building-apps/docs/sdks-plugins
用意されているSDKを見て、まあRubyより書き慣れているPHPで書いておくか、という判断をしました。

town-inc
私たちは、クラウドを主軸としてさまざまな市場にITを浸透させ、永続的に成長するITカンパニーをめざしています。
https://town.biz/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away