GoogleAppEngine/Python(以下、GAE/py)から、HipChat API v1/v2を使ってみた時のメモ。
環境
HipChat APIについて
今のところHipChat APIはv1/v2の2つがあります(ただし、v2はBETA)。
APIに関する公式ドキュメントは以下にありました。
また、APIを使うためにはtokenを事前に取得する必要があります。
なお、v1向けのTokenのTypeはAdminとNotificationの2つがありましたが、RoomIDを取得する都合上、Adminを使いました。RoomIDが事前にわかっていれば、Notificationで十分かもしれません。
ライブラリ探し
HipChat公式では、API v1/v2それぞれ向けのライブラリが紹介されています。
GAE/pyでライブラリを使う場合、通常、
ローカルではなく、GAEアプリのlibなどのディレクトリにライブラリを入れる 用意されているのを使ったり、
python setup.py build
で、buildディレクトリ以下にできたものを使ったりする以下を参考に、
appengine_config.py
を作成
GAE/Pyでインポートのパスを追加する
を行うかと思います。
HipChatライブラリでも同じことをやってみましたが、開発環境でのセットアップがうまくできませんでした。
ただ、今回は「GAE/pyからHipChatのRoomに通知」だけをやりたかったため、ライブラリを使うのをやめて直接HipChat APIを叩くことにしました。
なお、Slackに対して同じようなことをやっていたコードがGitHubにあり、とても参考になりました。
albertpadin/slack-gae
GAE/pyからHipChat APIを使う
HipChatのRoomに通知するにはRoomIDが必要になるため、
- HipChatのRoomIDを取得 (API:
/rooms/list
,Get all rooms
) - RoomIDに対して通知 (API:
/rooms/message
,Send room notification
)
という流れを試しましたが、GAE/pyのurlfetch.fetch()
メソッドにより、HipChatAPI v1/v2 のどちらも同じように実行できました。
なお、手軽な方法で実装したため、API v1の通知者名は任意の名前でしたが、v2の通知者名は自身の名前となりました。
そのため、手軽に通知者名を使いたい場合には、API v1の方が良いかもしれません。
また、パラメータの説明は公式ドキュメントの他、以下が参考になりました。
執事のセバスチャンが東京ドームのイベントをHipChatで教えてくれる | feedforce Engineers' blog
HipChat API v1向けの通知コード
API_SEND_BASE_URL = 'https://api.hipchat.com/v1/rooms/message?format=json&auth_token={token}' API_SEND_BASE_PARAMETER = 'room_id={roomId}&from={user}&message={message}&color={color}' SENDER_NAME = 'GAE' url = API_SEND_BASE_URL.format(token=token) parameter = API_SEND_BASE_PARAMETER.format(roomId=roomId, user=SENDER_NAME, message=message, color='purple') urlfetch.fetch(url, payload=parameter, method=urlfetch.POST)
HipChat API v2向けの通知コード
API_SEND_BASE_URL = 'https://api.hipchat.com/v2/room/{id_or_name}/notification?auth_token={token}' url = API_SEND_BASE_URL.format(id_or_name=roomId, token=token) parameter = { 'color': 'yellow', 'message': message, 'message_format': 'text' } json_body = json.dumps(parameter) urlfetch.fetch(url, payload=json_body, method=urlfetch.POST, headers={'Content-Type': 'application/json'})
GAE/pyまわりで調べたところ
HipChat APIとはあまり関係ないのですが、忘れないように残しておきます。
非同期実行のdeferredライブラリ
slack-gaeで使っていたdeferredライブラリが気になり、調べてみました。
deferredはGAE/pyに含まれるライブラリで、Task Queue Python APIより手軽に使えそうなことが分かりました。
Background work with the deferred library - Google App Engine — Google Developers
そこで、今回メッセージ通知を非同期で行うこともあり、初めて試してみました。
ただ、webapp2.RequestHandler
を継承したクラス内ではdeferred.defer()
を使えなかったため、以下を参考に別ファイルに切り出して使うようにしました。
遅延ライブラリを使用したバックグラウンド作業の補足(GAE/python): 鈴木くにのブログ
また、deferred.defer()にself.request
の値をそのまま渡した場合、
(Can't pickle
: it's not the same object as threading._RLock)
のようなエラーが発生したため、事前にself.requestのうちで必要なパラメータを取得してから、それらを渡すようにしました。
他に、リトライ回数を制限するため、以下を参考に webapp2.get_request().headers.get('X-AppEngine-TaskRetryCount')
を使ってリトライ回数を取得しました。
python - Retry count in deferred.defer in GAE - Stack Overflow
リトライ回数を超過した場合は、
Raise a deferred.PermanentTaskFailure exception. This is a special exception, and is treated as a permanent failure. It is logged as an exception, so it will show up in your admin console as one, but causes the task to not be retried again. Background work with the deferred library - Dealing with task failures - Google App Engine — Google Developers
と公式ドキュメントに記載のある通り、raise deferred.PermanentTaskFailure
で例外を発生させました。
JSONのPOST
API v2ではJSON BodyをPOSTする必要があるため、urlfetch.fetchのheadersパラメータを使いました。
この部分のコードの再掲です。
urlfetch.fetch(url, payload=json_body, method=urlfetch.POST, headers={'Content-Type': 'application/json'})
テンプレートの継承
HipChat API v1/v2では、レスポンスのJSON構造が少し異なっています。
そのため、以下を参考に、{% block %}
や{% extends "base.html" %}
を使ってテンプレートの継承を行い、HTML表示を行いました。
GAE アプリのテンプレートを DRY - present
Google App Engine Launcher起動時にエラー
あるとき、Google App Engine LauncherでRunしたものの、長い間起動中になってしまいました。
とりあえず強制終了したところ、次回起動時に
See the logfile 'C:\Program Files (x86)\Google\google_appengine\launcher\GoogleAppEngineLauncher.exe.log' for details
というエラーメッセージが出てLauncherが起動できなくなりました。
エラーメッセージに従いGoogleAppEngineLauncher.exe.log
を探しましたが見当たりませんでした。仕方なくSDKを再インストールしたものの、同じエラーが出続けました。
そこで、エラーメッセージ自体を調べてみたところ、以下の記事がありました。
Google App Engine Launcherの起動エラー - RENAISSANCE
同じようにgoogle_appengine_projects.ini
ファイルを修正したところ、無事に起動するようになりました。ありがとうございました。
ソースコード
GitHubに上げてあります。
thinkAmi-sandbox/GAEHipChat-Sample