enebular で slack status を更新する

enebular でslack status更新
やってみたこと

こんにちは。ウフルのデバプラ部のはらだです。
絵に描いたような三寒四温で毛布を出したり畳んだりな毎日です。皆さんも体調管理に気を付けて、GWに備えましょう(*’ω’*)
GWの予定ですか?聞かないでくd

さて、今回は「slackに新たに追加されたstatus機能をenebularを使って自動更新する」というのを書いていきます✌️

    目次

  1. slack statusとは
  2. enebularで実装してみる
  3. slackのメッセージを監視する
  4. sample json

slack statusとは

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 設定画面

パーツがそろったので、以下のフローを作ります。
①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はこのようにセット

この後は先ほどと同様に、受け取った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":[]}]

次回は、上で少し書いたビーコン連携について、記事を書く予定です!

それでは~✋