この記事は GRIPHONE Advent Calendar 2020 22日目の記事です。
こんにちは。サーバーサイドエンジニアの森と申します。
今回はPhoton Chatのwebhookを使って自社のPHP APIサーバー側で過去ログを作り、メッセージの改変をする実装をしたので、その詳細を書きます。
Photon Chatを利用する際のまとめが5日の記事にまとめられていますので、興味ある方はそちらもご覧ください。
実現したこと
この記事でPhoton Chatのwebhookを使って実現したことは以下の2点です。
過去ログの作成
Photon Chatのチャンネルにも元々過去ログを保存する機能はあるのですが、過去ログの保存件数の上限が100件なのと、チャンネルから人がいなくなるとその過去ログが揮発するという性質があります。
揮発しない過去ログをどうやって実現するか考えた結果、自社側のDBに過去ログを保存し、それをクライアントに渡すことにしました。
チャットに投稿されたメッセージの改変
クライアント側で投稿されたメッセージを、サーバー側で改変、追記したいということはよくあると思います。
うちのプロジェクトでは以下のような用件がありました。
- メッセージごとにユニークなIDを振るために、自社DBを使いたい
- メッセージの投稿時刻に自社サーバーの正確な時刻を使いたい
- サーバーの自社DBにある値をメッセージに入れたい
Photonのwebhookについて
Photon Chatサーバーには、C#などの特定の言語以外の自社サーバーからREST APIなどでリクエストを投げることはできません。
しかし、webhookを使うことで、ある程度イベントの制御を行うことができます。
webhookの種類
ChannelCreate | 新たなチャンネルが作成される時に送信される。 |
ChannelDestroy | チャンネルが揮発する際に送信される。 |
ChannelSubscribe | チャンネルにクライアントが参加した際に送信される。 |
ChannelUnsubscribe | クライアントがチャンネルとの接続を切った時に送信される。 |
PublishMessage | クライアントがチャンネルにメッセージを送ると送信される。 メッセージの内容を書き換えることができる。 |
今回はPublishMessage webhookを使って、過去ログの保存とメッセージの書き換えを行います。
実装手順
Photon Chatダッシュボードの設定
まず、ダッシュボードからwebhookを送信するurlとパスを設定します。
BaseUrlとPathPublishMessageに、自社サーバーのwebhook用のエンドポイントを指定します。上の画像の例だと、「https://(ドメイン)/PhotonWebhook/PublishMessage」にwebhookのリクエストが飛んでくるようになります。
また、このダッシュボードからwebhookに追加するCustomHttpHeadersを指定できます。これを利用すると、webhookが偽造されてないかvalidateを行うことで、セキュリティの強化ができます。
PHPの実装
次にPHPでwebhookを受け取る実装をします。
PublishMessageのwebhookデータはリクエストのbody部分に入るので、php://inputを読み込むことで内容を取得できます。
以下のようなJSON文字列が飛んできます。
'{"AppId":"00000000-0000-0000-0000-000000000000","AppVersion":"1.0","Region":"EU","ChannelName":"openChannel001","HistoryCount":0,"UserId":"01547610","Message":"今年ももう終わりかあ","ChannelType":"Public"}'
また、webhookへの戻り値としては、以下のパラメータを設定します。
ResultCode | 0が成功、0以外だと失敗を表す |
Message | 失敗した時のエラーメッセージを入れる |
Data | Photon Chatへ送信されるメッセージを書き換えたい場合、ここに入れる |
コード
ここでは、例として、
- メッセージデータをDBに入れる
- 1.のDBレコードのIDをメッセージに追加する
をするPHPコードを書いてみます。コードは以下のようになります。
try {
$requestParamsArray = json_decode(file_get_contents('php://input'), true);
$message = $requestParamsArray['Message'];
$chatMessageHistory = $chatMessageHistoryDbDao->add($message, $requestParamsArray['ChannelName']);
$outputJson = json_encode(
[
'ResultCode' => 0,
'Message' => 'OK',
'Data' => sprintf("[%d] %s", $chatMessageHistory->getId(), $message),
]
);
echo $outputJson;
exit;
} catch (Throwable $e) {
$outputJson = json_encode(
[
'ResultCode' => $e->getCode(),
'Message' => $e->getMessage(),
]
);
echo $outputJson;
exit;
}
処理を詳細に見ていきます。
webhookのJSONデータはphp://inputに入っているので、以下で取得できます。
また、チャットのメッセージはMessageパラメータに入っています。
$requestParamsArray = json_decode(file_get_contents('php://input'), true);
$message = $requestParamsArray['Message'];
以下の処理では、メッセージとチャンネル名を自社のDBに追加しています。
この関数は、DBに追加したレコードの値を戻り値として返します。追加の際に、レコードには自動採番でユニークなidが振られます。
$chatMessageHistory = $chatMessageHistoryDbDao->add($message,
$requestParamsArray['ChannelName']);
以下はWebhookにデータを返す部分で、JSONを出力しています。成功の際はResultCodeに0を指定します。
Data部分を指定すると、Photon Chatに送られるメッセージが改変されます。ここでは、DBに振られたIDの数値をメッセージに追加しています。
例えば、本来クライアントが送ったメッセージが「今年ももう終わりかあ」というメッセージだった場合、以下の処理で「[1] 今年ももう終わりかあ」というメッセージに改変されてPhoton Chatサーバーに送られます。
$outputJson = json_encode(
[
'ResultCode' => 0,
'Message' => 'OK',
'Data' => sprintf("[%d] %s", $chatMessageHistory->getId(), $message),
]
);
echo $outputJson;
以下はエラーハンドリング部分です。エラーが起きた際は、webhookにエラーの内容を返します。
シンプルにResultCodeとMessageはエラーコードとエラーメッセージをそれぞれ渡しています。
catch (Throwable $e) {
$outputJson = json_encode(
[
'ResultCode' => $e->getCode(),
'Message' => $e->getMessage(),
]
);
echo $outputJson;
exit;
}
以上で、Photon Chatのメッセージを自社DBに保存し、メッセージを改変する処理が実現できました!
まとめ
今回はPhoton Chatのwebhookを使って、クライアントがPhoton Chat サーバーに送るメッセージを自社のPHPサーバーで取得し、メッセージを改変する方法を紹介しましたがいかがでしたか。
webhookを使うことでPhoton Chatの各種操作を柔軟に扱うことができます。
この記事が少しでもPhoton Chatを実装する際のお役に立てたならば幸いです。