こんにちは。ウフルのデバプラ部のはらだです。
絵に描いたような三寒四温で毛布を出したり畳んだりな毎日です。皆さんも体調管理に気を付けて、GWに備えましょう(*’ω’*)
GWの予定ですか?聞かないでくd
さて、今回は「slackに新たに追加されたstatus機能をenebularを使って自動更新する」というのを書いていきます✌️
slack statusとは
4月14日より、名前の横にemojiを表示することができるようになりました。「会社につきました」「退勤しました」「MTG中です」「有給もらいました」など、自分でstatusを更新し、チームのメンバーに知らせることができます。(詳しくはこちら→「Set your status in Slack | Slack」)
チームに追加されているemojiも表示することができます。自由に運用するのも良いですが、チームである程度ルールを決めて運用するともっと便利になりますね。
enebularで実装してみる
でも、あれですね。「こちとら、status変更に時間割いてる場合じゃないんじゃ!」って時ありますよね。emoji探す時間もそれなりにロスだったり(´・ω・`)
_人人人人人人人人人人人人人人人人人人人人_
> じゃあ、APIで更新すればよいのでは!💡 <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
「User presence and status | Slack」にstatusのAPIリファレンスが載っているので、enebularを使って更新してみたいと思います。
「users.profile.set | Slack」メソッドのprofile
パラメータに以下のようなJSONを送ればおっけーです。
{ "status_text": "遅延なう", "status_emoji": ":tain:" }
URLにエンコードするとこんな感じ
%7B%22sta tus_text%22:%22%E9%81%85%E5%BB%B6%E3%81%AA%E3%81%86%22,%22status_emoji%22:%22:train:%22%7D
他のパラメータも併せてURLを設定します。以下が叩くURL
https://slack.com/api/users.profile.set?token=${APITOKEN}&user=${USERID}&profile=${status}&pretty=1
APIトークンとユーザーIDが必要なようです。
とりあえず動かしたいので、トークンは以下より取得。
Legacy tokens | Slack
UserIDはslackで表示される名前とは違います。以下のURLから取得できます。
https://slack.com/api/users.list?token=[APITOKEN]
APIトークンは先ほど取得したものを使用します。
users.list | Slack
アクセスすると以下のJSONが返ってくるので、該当するユーザーIDを取得
{ "cache_ts": 1492755316, "members": [ { "color": "9f69e7", "deleted": false, "has_2fa": false, <strong><span style="color: #e02d2d;">"id": "U3xxxxxx10",</span> </strong> "is_admin": true, "is_bot": false, "is_owner": true, "is_primary_owner": true, "is_restricted": false, "is_ultra_restricted": false, "name": "k.harada", "profile": { "avatar_hash": "xxxxxxxxxxx", "email": "xxxxxxxxxあっとuhuru.jp", ~~~~~ 省略 ~~~~~~
これで準備は整いました
さくっとURLにアクセスするだけのフローを作ります。
https://slack.com/api/users.profile.set?token=${APITOKEN}&user=${USERID}&profile=${status}&pretty=1
取得してきた値をそれぞれ、置き換えて、、
timestampノードをポチっと押すと、
電車のアイコンになりました👏
statusチェンジする仕組みはわかったので、場面場面ごとに適するstatusに自動で変更するようにしてみます。
slackのメッセージを監視する
私が所属するデバプラ部は、毎日出社したら「やること」、帰る前に「やったこと」をslackに書くルールがあります。
日報チャンネルにそれぞれのメッセージが書き込まれたときに「出社したこと」、「退勤したこと」がわかるようにstatusを自動で変更すると便利そうです。
メッセージを監視するためのslack botを立ち上げます。
一番シンプルな「bots | slack」を使いました。
作成したbotを監視させたいchannnelへinviteし、設定ページからbot用のAPIトークンを取得します。
パーツがそろったので、以下のフローを作ります。
①Botsによってslackのchannnelを監視する
②発言内容によって、statusを変更する
③URLを生成し、APIを叩く
シンプルにまとまりそうです。
で、完成したのがこちら↓
少し解説します٩( ‘ω’ )و
【setting flow】
APIトークンやユーザーIDはフローがデプロイされた瞬間にglobalオブジェクトにセットされます。
後々の変更がありうる固有のパラメ―タはこのようにglobalオブジェクトで管理すると、改修する際に工数が削減されます。これについては、またの機会に詳しく記述します。
【monitor flow】
slackで発言すると以下のようなフォーマットのJSONが生成されます。
{ "payload": "昼食とってきます", "slackObj": { "channel": "xxxxxxx", "channelName": "xxxxxx", "fromUser": "k.harada", "text": "昼食取ってきます", "type": "message" } }
slackObj.fromUser
に発言者が入っているので、ここでまず場合分け。
その後、ayload
の文字列を正規表現を用いて場合分けし、際するstatus情報をセットします。
中身は以下のようになってます。
この後は先ほどと同様に、受け取ったstatusの値をURLにセットして、APIを叩いてあげればおっけーです🙌
slackの監視以外にもenebularを使えば、こんなことができそうです。
- お昼休憩の時間(13時)🍴になったら、statusを変更する。
- Googleカレンダーと連携をして、MTGの時間💬や移動時間🏇🏻にstatusを変更する。
- フローの中でフラグを作って、残業😵していることをわかるようにする
- フローの中でフラグを作って、遅刻🙇していることがわかるようにする
弊社では社員がみなビーコンを持っているので、私自身は今上記のほかに、会社に着いた瞬間、「arrive now」にstatusが変わるようにフローを組んでいます。
9:30に出社フラグを立てておいて、私のビーコンが検知されたら、「arrive now」 に変化します!
部署の付近にはいないけど、出社してることをチームに知らせることができています٩( ‘ω’ )و
sample json
enebularやnode-redでインポートできるjsonを用意しました。また、commentで編集するべき箇所に印付けました。パラメータを変更してご使用ください。
[{"id":"a96fdc60.39bdf","type":"comment","z":"d387286f.9dae88","name":"setting flow","info":"https://slack.com/api/users.profile.set?\ntoken=xoxp-112461145334-111785520034-112473991495-9c344fa960fc0883423afa78fc907d98&\nuser=U39P3FA10&\nprofile=%7B%22status_emoji%22%3A%22%3Abug%3A%22%7D&\npretty=1","x":90,"y":520,"wires":[]},{"id":"ba983334.7cedc","type":"inject","z":"d387286f.9dae88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":130,"y":580,"wires":[["5fd22491.3618dc"]]},{"id":"5fd22491.3618dc","type":"change","z":"d387286f.9dae88","name":"slack","rules":[{"t":"set","p":"slack.user","pt":"global","to":"userID","tot":"str"},{"t":"set","p":"slack.api","pt":"global","to":"APIToken","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":580,"wires":[[]]},{"id":"c611af32.f7f35","type":"Slack Bot In","z":"d387286f.9dae88","name":"slack監視","apiToken":"","channel":"","x":120,"y":720,"wires":[["f41083ad.0370a","cd0507bc.0b1af8"]]},{"id":"e3c278f5.89b838","type":"debug","z":"d387286f.9dae88","name":"","active":true,"console":"false","complete":"true","x":1050,"y":820,"wires":[]},{"id":"b1683eaf.cd343","type":"switch","z":"d387286f.9dae88","name":"","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":".*やること.*","vt":"str","case":false},{"t":"regex","v":".*やったこと.*","vt":"str","case":false},{"t":"regex","v":".*遅延.*","vt":"str","case":false}],"checkall":"true","outputs":3,"x":410,"y":800,"wires":[["b1e17d14.42132"],["f1deb750.7445b8"],["8a3e3382.a561e"]]},{"id":"ede4b4c0.ab2d38","type":"function","z":"d387286f.9dae88","name":"url設定","func":"var sts ={\n \"status_text\": msg.sts.mes,\n \"status_emoji\": msg.sts.emoji\n};\n\nsts = JSON.stringify(sts);\nsts =encodeURI(sts);\n\nmsg.url=`https://slack.com/api/users.profile.set?token=${msg.slack.api}&user=${msg.slack.user}&profile=${sts}&pretty=1`;\n\nreturn msg;","outputs":1,"noerr":0,"x":820,"y":820,"wires":[["29c93548.955c4a","c44d380e.5c2ac8"]]},{"id":"b1e17d14.42132","type":"change","z":"d387286f.9dae88","name":"","rules":[{"t":"set","p":"sts.emoji","pt":"msg","to":":office:","tot":"str"},{"t":"set","p":"sts.mes","pt":"msg","to":"working now","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":760,"wires":[["ede4b4c0.ab2d38"]]},{"id":"81150d81.975db","type":"change","z":"d387286f.9dae88","name":"","rules":[{"t":"set","p":"slack","pt":"msg","to":"slack","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":800,"wires":[["b1683eaf.cd343"]]},{"id":"29c93548.955c4a","type":"http request","z":"d387286f.9dae88","name":"","method":"GET","ret":"txt","url":"","tls":"","x":950,"y":760,"wires":[["e3c278f5.89b838"]]},{"id":"f1deb750.7445b8","type":"change","z":"d387286f.9dae88","name":"","rules":[{"t":"set","p":"sts.emoji","pt":"msg","to":":house:","tot":"str"},{"t":"set","p":"sts.mes","pt":"msg","to":"退勤しました('ω')","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":800,"wires":[["ede4b4c0.ab2d38"]]},{"id":"8a3e3382.a561e","type":"change","z":"d387286f.9dae88","name":"","rules":[{"t":"set","p":"sts.emoji","pt":"msg","to":":train:","tot":"str"},{"t":"set","p":"sts.mes","pt":"msg","to":"電車遅延なう(*_*;","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":840,"wires":[["ede4b4c0.ab2d38"]]},{"id":"f41083ad.0370a","type":"debug","z":"d387286f.9dae88","name":"","active":true,"console":"false","complete":"true","x":310,"y":700,"wires":[]},{"id":"cd0507bc.0b1af8","type":"switch","z":"d387286f.9dae88","name":"","property":"slackObj.fromUser","propertyType":"msg","rules":[{"t":"eq","v":"k.harada","vt":"str"}],"checkall":"true","outputs":1,"x":190,"y":760,"wires":[["81150d81.975db"]]},{"id":"c44d380e.5c2ac8","type":"debug","z":"d387286f.9dae88","name":"","active":true,"console":"false","complete":"url","x":1010,"y":940,"wires":[]},{"id":"9f58ffab.0c268","type":"comment","z":"d387286f.9dae88","name":"monitor flow","info":"https://slack.com/api/users.profile.set?\ntoken=xoxp-112461145334-111785520034-112473991495-9c344fa960fc0883423afa78fc907d98&\nuser=U39P3FA10&\nprofile=%7B%22status_emoji%22%3A%22%3Abug%3A%22%7D&\npretty=1","x":90,"y":640,"wires":[]},{"id":"eaac3ea9.2873b","type":"comment","z":"d387286f.9dae88","name":"↓パラメータ入れる","info":"","x":310,"y":540,"wires":[]},{"id":"78a83bfe.579254","type":"comment","z":"d387286f.9dae88","name":"↓パラメータ入れる","info":"","x":130,"y":680,"wires":[]},{"id":"1a670f7d.945c51","type":"comment","z":"d387286f.9dae88","name":"正規表現で場合分けする文字列を入れる↑","info":"","x":300,"y":860,"wires":[]},{"id":"8750d52d.dcb3a8","type":"comment","z":"d387286f.9dae88","name":"↓場合分け後それぞれセットするstatusを入れる","info":"","x":680,"y":720,"wires":[]}]
次回は、上で少し書いたビーコン連携について、記事を書く予定です!
それでは~✋