目次
前提
以下の環境で実装及び動作確認を行った
要素 | バージョン |
---|---|
debian | 8.6 |
ruby | 2.2.2 |
概要
チャットワークのAPIを使える状態にし、Rubyからチャットワークの各種操作を行う。今回の成果物についてはGithubから閲覧、ダウンロード可能。
チャットワークとは
ビジネス向けのチャットツールで以下の特徴がある
- 基本無料
- ルームを個別に作成し、複数人でチャット可能
- ルームごとにタスクの管理が可能
- ファイルの共有が可能
- 音声通話/ビデオ通話も可能
チャットワークAPIとは
チャットワークの基本的な機能をプログラムから利用するためのRestFullなAPI。
現在(2017/05/20)は、プレビュー版のみの限定公開となっており、APIを利用するためには申請する必要がある
チャットワークAPIの利用準備
チャットワークAPIの利用申請
チャットワークにログインしているブラウザで、利用申請ページにアクセスし、APIの利用申請を行う。利用が可能な状態になると、チャットワークで登録しているメールアドレスに、以下のような通知メールが届くのでそれまで待機(1営業日程度?)
いつもお世話になっております。
チャットワーク サポートデスクです。チャットワークAPI(プレビュー版)のご利用が可能となりましたので
お知らせいたします。
APIトークンの確認
メールが届いたら、ブラウザでチャットワークを開き、「動作設定」を開くと、以下のようにAPI発行メニューが追加されていることが確認できる。
パスワードを入力することで、以下のようにAPIトークンを確認することができる(画像のトークンはダミー)
トークンはこの画面で更新可能なので、必要に応じて更新する。
APIトークンはプログラムでAPIを利用するのに必須のため、環境変数に保存しておく。以下のコマンドをbashrcに追記するのがベスト
$ export CHATWORKAPI=hogehogehogehogehogehogehogehogehoge
APIの仕様確認
APIドキュメントを確認すれば、APIのシンプルな仕様を確認できるが、ここでは以下さえ抑えておけば問題ない
- APIのエンドポイントは https://api.chatwork.com/v2
- リクエストは必ずHTTPSを用いる
- リクエストヘッダに”X-ChatWorkToken”というキーでAPIトークンを指定する必要がある
- APIの制限は5分で100回程度
- レスポンスは必ずJSONで返却される
- ただし、APIの成否判定の多くはレスポンスヘッダに含まれている
APIの動作確認
さっそくプログラムを作っても良いが、API及びAPIトークンが正しく機能しているかを確認するため、curlコマンドで試しにAPIを呼び出してみる。
$ curl https://api.chatwork.com/v2/me GET -H "X-ChatWorkToken: hogehoge"
上記curlコマンドは、以下のHTTPリクエストを送信する
- リクエスト先は https://api.chatwork.com/v2/me (自身のステータスを取得するAPI)
- メソッドにGETを用いる
- リクエストヘッダに”X-ChatWorkToken: hogehoge”を含める
すると、以下のレスポンスが返却される
{"account_id":2091543,"room_id":59255776,"name":"笹木信吾","chatwork_id":"","organization_id":1118988,"organization_name":"","department":"","title":"","url":"https://github.com/Sa2Knight","introduction":"","mail":"sasaki@91932.com","tel_organization":"","tel_extension":"","tel_mobile":"090-7067-7376","skype":"","facebook":"","twitter":"","avatar_image_url":"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}
レスポンスを見る限り、無事にチャットワークAPIを用いて、自身のユーザ情報を取得できていることがわかる。
RubyからチャットワークAPIを利用する
Chatworkクラスの作成
とりあえずチャットワークAPIをRubyで叩くためのエンドポイントとなるChatworkクラスを作成する。
require 'net/http' require 'uri' require 'json' require 'date' class Chatwork @@API_BASE = 'https://api.chatwork.com/v2' # tokenを指定してオブジェクトを生成 # tokenを省略した場合、環境変数を参照する def initialize(token = nil) @token = token || ENV['CHATWORKAPI'] end end
例によって、APIトークンを指定してオブジェクトを生成する。トークンの指定を省略した場合に、環境変数”CHATWORKAPI”を参照するようにしてあるので、今回はそれを前提にする。APIのエンドポイントは全てのAPIで共通なので、クラス定数@@API_BASEで定義しておく。
HTTP通信するメソッドの実装
どのAPIでも共通となる、HTTPリクエストを投げてレスポンスを戻すメソッドを作成する。
createRequestObjectは、そのヘルパーメソッドで、指定したHTTPメソッド(:get,:post,:put,:delete)に応じた、空のHTTPRequestオブジェクトを返却する。
createHttpObject、対象のURL,HTTPメソッド,パラメータを指定すると、以下のことをしてくれる。
1. APIのエンドポイントと各APIのURLを結合し、URIオブジェクトを生成する
2. URIを元にHTTPオブジェクトを生成し、SSLを有効にする
3. (メソッドがGETの場合) URIにパラメータを付与する
4. メソッドに応じたRequestオブエクトを取得
5. リクエストヘッダにAPIトークンを付与
6. (メソッドがGET以外の場合) リクエストボディにパラメータを付与する
7. リクエストを送信し、レスポンスを戻す
## HTTPリクエストを送信する def createHttpObject(url, method, params = {}) api_uri = URI.parse(@@API_BASE + url) https = Net::HTTP.new(api_uri.host, api_uri.port) https.use_ssl = true api_uri.query = URI.encode_www_form(params) if method == :get req = createRequestObject(method, api_uri) req["X-ChatWorkToken"] = @token req.set_form_data(params) unless method == :get https.request(req) end ## リクエストオブジェクトを生成する def createRequestObject(method, uri) case method when :get return Net::HTTP::Get.new(uri.request_uri) when :post return Net::HTTP::Post.new(uri.request_uri) when :put return Net::HTTP::Put.new(uri.request_uri) when :delete return Net::HTTP::Delete.new(uri.request_uri) end end
上記のメソッドを用いて、各APIに対応したメソッドを実装する。
各APIごとのメソッドを実装する
あとはAPIドキュメントを参考に、各種APIを呼び出すためのメソッドを順に実装する。全て実装するのは疲れるので、とりあえず以下を実装した。残りもおいおい実装する予定
メソッド名 | 内容 |
---|---|
me | 自身のユーザ情報を取得 |
myStatus | 自身の未読数、未読To数、未完了タスク数を取得する |
myTasks | 自身のタスク一覧を取得する |
myContact | 自身のコンタクト一覧を取得する |
myRooms | 自信が参加しているチャット一覧を取得する |
getRoom | チャットの情報を取得する |
createRoom | 新しいチャットを作成する |
updateRoom | チャットの情報を更新する |
getRoomMembers | チャットに参加しているユーザ一覧を取得する |
getRoomMessages | チャットのメッセージ一覧を取得する |
sendMessage | チャットに新規メッセージを投稿する |
getRoomTask | チャット内のタスク一覧を取得する |
getTask | タスク情報を取得する |
createTask | タスクを新規登録する |
getRoomFiles | アップロードされたファイル一覧を取得する |
getFile | アップロードされたファイルの情報を取得する |
※ 何故か既存のタスクを操作するためのAPIが無い。タスクを作ることは出来るのに完了したり編集したりすることがでない謎。
実装例
どのメソッドも基本的に実装内容は同じ(URL、メソッド、パラメータの有無などが異なるだけ)なので、全てを記載しないが、ここでは以下の2種類について記載する。
myStatus(自身の未読数、未読To数、未完了タスク数を取得する)
myStatusは特定のURLに対して、パラメータなしでシンプルにGETするだけなので、以下のように実装した
def myStatus url = '/my/status' res = createHttpObject(url, :get) return JSON.parse(res.body) end
createTask(タスクを新規登録する)
createTaskは少しだけ複雑で、タスクを新規登録するルーム(チャット)IDとタスクの内容、担当者のユーザID一覧を指定して登録する。また、オプションでタスクの期限を指定することができる。
APIが要求するパラメータでは、担当者のユーザID一覧はカンマ区切りで、期限はUNIXTIMEで指定する必要がある。これはそのままだと使いづらいので、メソッド側では担当者のユーザID一覧を配列で、期限をDateTimeオブジェクトで受け取るようにしている。メソッド内でそれをAPI用に変換して実行している。
def createTask(room_id, body, to_ids = [], params = {}) url = '/rooms/' + room_id + '/tasks' params[:body] = body params[:to_ids] = to_ids.join(',') params[:limit] = params[:limit].to_i if params[:limit].class == Time res = createHttpObject(url, :post, params) return res.body ? JSON.parse(res.body) : [] end
動作確認
本項では、以下の手順で動作確認する
- 動作確認用の新しいチャットルームを作成する(自分のみ参加)
- チャット内で適当に発言する
- チャット内にタスクを追加する
- チャットルームの情報を取得する
- チャットルームの発言一覧を取得する
- チャットルームのタスク一覧を取得する
なお、動作確認中に使用するユーザのIDを’2091543′,及び作成するチャットルームのIDを’76097933’とし、以下のようにChatworkオブジェクトを生成済みとする。
cw = Chatwork.new
チャットルームを作成
動作確認用に、「API動作確認ルーム」というチャットルームを作成する。参加者は、自身のみを管理者ユーザとして設定する。
cw.createRoom('API動作確認ルーム', ['2091543'], :description => '動作確認用のルームです')
実行すると、以下のように新規チャットルームが作成されたことがわかる。
チャット内で適当に発言する
「こんにちは,APIからの投稿です」という発言を、先ほど作成したルームに対して送信する
cw.sendMessage('76097933', 'こんにちは、APIからの投稿です')
チャット内にタスクを追加する
「WordPressを更新する」というタスクを、本日(5/21)を締め切りにして登録する
cw.createTask('76097933', 'WordPressを更新する', ['2091543'], :limit => Time.now)
チャットの情報を取得する
先程作成したチャットルームの情報を取得する。
cw.getRoom('76097933')
実行すると、チャットルームの基本的な情報を確認することができる
{"room_id"=>76097933, "name"=>"API動作確認ルーム", "type"=>"group", "role"=>"admin", "sticky"=>false, "unread_num"=>0, "mention_num"=>0, "mytask_num"=>1, "message_num"=>3, "file_num"=>0, "task_num"=>1, "icon_path"=>"https://appdata.chatwork.com/icon/ico_group.png", "description"=>"動作確認用のルームです", "last_update_time"=>1495307674}
チャットルーム内のメッセージ一覧を取得する
メッセージ一覧(と言っても先程の1件のみだが)を取得する
cw.getRoomMessages('76097933')
メッセージ一覧及び個々のメッセージの発言者の情報が取得できることがわかる
[{"message_id"=>"2020162066", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"[info][title][dtext:chatroom_groupchat_created][/title][dtext:chatroom_chatname_is]API動作確認ルーム[dtext:chatroom_set]\n\n[dtext:chatroom_description_is]動作確認用のルームです[dtext:chatroom_set]\n\n[dtext:chatroom_member_is][piconname:2091543][dtext:chatroom_added][/info]", "send_time"=>1495307261, "update_time"=>0}, {"message_id"=>"2020162308", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"こんにちは、APIからの投稿です", "send_time"=>1495307439, "update_time"=>0}, {"message_id"=>"2020162647", "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "body"=>"[info][title][dtext:task_added][/title][task aid=2091543 st=open lt=1495378799]WordPressを更新する[/task][/info]", "send_time"=>1495307674, "update_time"=>0}]
チャットルーム内のタスク一覧を取得
こちらも先程登録した1件のみだが、タスクの情報を取得する
p cw.getRoomTasks('76097933')
実行すると、タスク及びそのメタ情報が確認できる
[{"task_id"=>68592616, "account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "assigned_by_account"=>{"account_id"=>2091543, "name"=>"笹木 信吾", "avatar_image_url"=>"https://appdata.chatwork.com/avatar/1623/1623307.rsz.png"}, "message_id"=>"2020162647", "body"=>"WordPressを更新する", "limit_time"=>1495378799, "status"=>"open"}]
所感
- チャットワークのAPIはそれは見事なRestFull設計で感動を覚えるほど使いやすかった
- だがまだプレビュー版で、既存タスクの更新ができないなど、痒いところに手が届かないので正式リリースが待たれる
- APIを叩くライブラリを作ったはいいが、問題はこれをどう活用するか。そこは全然考えてない。おそらくサーバを監視して報告をチャットワークに流すとか、プロジェクト管理ツールの更新をチャットワークでも通知するとか、読み込みより書き込みがメインになるとは思う