まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:slack

このブログエントリの続きです:
Slack の OAuth API を使ってみる

↑ここで紹介した方法を使って実際にアプリケーション・サービスを作ってみました。作った内容はこれ↓の Slack 版です:
お絵かき LIFF アプリを作ってみた

2019052501


(実はもともとは Twitter 向けに作ったのですが)LINE のフロントエンドフレームワーク: LIFF を使って、その場で指でお絵描きした画像を LINE のトークルームに送信する、という連携アプリケーションを以前に作りました。その Slack への移植です。

なお、このアプリケーションは Barloon というエンジニア向けバーで企画されたハッカソン向けに作成しました。興味ある方は "Barloon" でググって調べてみてください。


【作った物】
こちらで MIT ライセンスで公開しています。よかったら使ってください:
https://github.com/dotnsf/slack-doodle

2019052502



以下でも紹介していますが、注意点として「ワークスペースごとにアプリケーション・サーバーが1台必要」です。その理由ですが、このアプリは Slack API を利用して作っているのですが、Slack API に登録アプリを申請する際にワークスペース(https://○○○○.slack.com/ の ○○○○部分)を指定して申請する必要があるからです。ここで申請したワークスペース向けにアプリケーションを作って動かす形になるため、複数のワークスペースで動くアプリケーションを1つの URL で動かすことができないのでした(このあたりが上記の LINE 向けアプリと異なります)。


【サーバーの動かし方】
このアプリケーションは Node.js 上で動くウェブアプリケーションです。一応レスポンシブ対応しているつもりなので、PC ブラウザからも、スマホのブラウザからも使えます(PC ブラウザの場合はマウスで、スマホブラウザの場合は指でお絵描きすることになります)。したがって Node.js が導入済みのアプリケーション・サーバーが必要です。

利用にあたっては、まず Slack API のアプリケーション登録が必要です。こちらの詳しい手順はこのリンク先を参照してください:
http://dotnsf.blog.jp/archives/1074688701.html

ただし1点だけ注意が必要です。上記ページではアプリケーションの scope に channels:read のみを指定していますが、このお絵描きアプリケーションでは更に加えて:
 chat:write:user
 files:write:user
の2つ(計3つ)の scope を指定する必要があります(描いた画像を API でアップロードするために必要な scope です)。この3つを scope に指定する必要がある、という点に注意してください。

2019052503

※必要に応じてアプリケーションのアイコンなども好きなものに変えておいてください。


その上で上記 github の URLからソースコード一式を Node.js アプリケーションサーバー上に git clone するか download & unzip して、ソースコードを展開します。

展開後、settings.js というファイルが存在しているので、このファイルをテキストエディタで開き、exports.slack_client_id の値と、exports.slack_client_secret の値をそれぞれ Slack API 登録アプリの client_id および client_secret の値に書き換えて保存します(このあたりの具体的な情報はこちらを参照してください)。

そしてアプリケーションサーバーを起動、これで準備完了です:
$ npm install
$ node app

【遊び方】
アプリケーション・サーバー(例えば https://slack-doodle.xxx.com/ )が動いている状態で、そのアプリケーションサーバーの URL に PC かスマホのブラウザにアクセスするだけなのですが、その前にやっておくことがあります。

上記でも触れたのですが、このアプリケーションサーバーは特定のワークスペース向けに作られています(そのワークスペースでしか使えません)。一方、ブラウザで Slack にアクセスすると、いろんなワークスペースに切り替えて使うことができます。ということはブラウザが目的のワークスペース以外のセッションなどを保持している可能性があり、その状態で使っても期待通りの挙動にならない可能性があるのです。

この状態をクリアするために『念の為』以下の手順を最初に行っておくことを推奨します。まず PC かスマホのブラウザを起動し、目的のワークスペース(例えば目的のワークスペースが "abc" であれば https://abc.slack.com/ )にアクセスして、認証してログインします。これでブラウザが目的のワークスペースのセッションを保持した状態が作れました。

その上で、そのままアプリケーションサーバー( https://slack-doodle.xxx.com/ )にアクセスします。以下はスマホでの画面例ですが、PCブラウザだともう少し横に大きな画面になると思います(一応、この未ログインの時点でお絵描きを試すことはできるのですが、送信することはできません)。ではログインするため左上の "Login" をタップします:
2019052504


Slack アプリケーションのページに転送され、目的のワークスペースに向けた OAuth の認証が行われます:
2019052505


内容を確認して、「許可する」を選択します:
2019052506


するとログインが完了し、元のアプリの画面に戻ります。この時、画面上部にワークスペース上で自分が利用することのできるチャネルが選択できるようになり、POST をクリックすると、ここで選択したチャネルに描いた画像がアップロードされます:
2019052507


実際に POST するとこんな感じで目的のワークスペースの目的のチャネルに画像をアップロードすることができます:
2019052508


この系統のアプリ、Twitter ではじめて、LINE に移植して、今回は Slack にも移植して・・・ 次は何にしよう?? ちなみに facebook は publish の API が昨年廃止になってしまったので技術的に作れないことがわかってます。



某アプリを Slack 対応する経緯で Slack API の中の、特に認証/認可を司る OAuth API を使う機会があったので自己まとめです。

もともとやりたかったのはウェブアプリに Slack アカウントでログインして、そのログインした人の権限でチャネル一覧を取得し(※)、ウェブアプリから指定したチャネルにメッセージを書き込む、ということでした。この中の※部分までを Node.js + Express + EJS で実現したコードを Github に公開しています(後述)。


実際に試してみるにはまず Slack に対象アプリケーションを登録する必要があります。 https://api.slack.com/apps を開いてログインし、"Create New App" ボタンをクリックしてウェブアプリを登録します:
2019052401


登録するアプリの名前と、対象ワークスペースを指定します(つまり同じアプリを複数のワークスペースで使いたい場合は、アプリを複数登録する必要があります)。以下では名前は "Slack OAuth Sample"、ワークスペースは "dotnsf" を指定しています(ワークスペースはログインしたユーザーが利用可能なワークスペース一覧から選択します)。最後に "Create App" ボタンをクリックして作成します:
2019052402


すると指定したアプリケーションの API 設定画面に切り替わります。画面左上に入力したアプリ名がデフォルトアイコンと一緒に表示されていて、"Basic Information" メニューが選択されていることを確認します:
2019052403


この画面を下スクロールすると App Credentials という項目があります。この中の Client IDClient Secret の値を後で使うので、どこかにコピーしておくか、いつでもこの画面を開ける状態にしておきましょう。なお Client ID の値は画面内に表示されていますが、Client Secret の値は初期状態では非表示になっています。"Show" ボタンをクリックして内容を表示し、その表示された値をあとで使うことに注意してください。またこれらの値は他の人には教えないように、自分で管理する必要があります:
2019052404


次に画面左のメニューから "OAuth & Permissions" を選び、少し下にスクロールすると Redirect URLs という項目があります。ここにウェブアプリケーションを動かす際のコールバック URL を登録しておく必要があります。"Add New Redirect URL" ボタンをクリックします:
2019052405


すると Redirect URL を追加する画面になるので、http(s)://サーバー名/slack/callback と入力します。この値は開発時には開発時用のサーバー名とポート番号、本番環境では本番環境用のサーバー名を指定する必要があります。下図では開発時向けに localhost の 6010 番ポートで動かす想定で http://localhost:6010/slack/callback と指定しています。ここの値は実際の環境に合わせて適宜変更してください。入力し終わったら "Add" ボタンをクリックして、その後 "Save URLs" ボタンをクリックします:
2019052406


画面上部に "Success!" というメッセージが表示されればリダイレクト URL の設定は完了です。正しい Redirect URLs が登録されたことを確認します:
2019052407


続けて、このアプリで利用する Slack 機能のスコープを指定します。実は OAuth 認証だけであればここの設定は不要なのですが、今回のデモアプリでは OAuth 認証後にログインユーザーが参照できるチャネルの一覧を取得して表示する、という機能が含まれています。また実際のアプリケーションではそのアプリケーションで実装する機能によって、ここでスコープを追加する必要があります:
2019052408


今回はログインユーザーが利用できるチャネル一覧を取得するため、"channels:read" スコープを追加します。また他に必要なスコープがあればここで追加します。最後に "Save Changes" ボタンをクリックして変更を反映します:
2019052409


これで Slack API 側の設定は完了しました。

では改めて Github からアプリケーションを取得します。Node.js がインストール済みの実行サーバー上で以下の URL を指定して git clone するか、ソースコードをダウンロード&展開してください:
 https://github.com/dotnsf/slack-oauth

2019052410


ソースコード内の settings.js をテキストエディタで開き、exports.slack_client_id の値と exports.slack_client_secret の値を上記で確認した client_id と client_secret の値に(コピー&ペーストなどで)変更して、保存してください。

なお、このサンプルアプリケーションでは以下のリクエスト API(?)が用意されていて、これらを明示的&内部的に使って動きます:
リクエスト API用途
GET /ユーザーがアクセスする唯一のページ。アクセス時に認証情報がセッションに含まれているとチャネル一覧が表示される。認証情報がセッションに含まれていない場合は認証前とみなして「ログイン」ボタンを表示する
GET /slack/loginユーザーページで「ログイン」ボタンをクリックした時に実行される。Slack の OAuth 認証ページにリダイレクトされる
GET /slack/callbackSlack の OAuth 認証ページで Authorize された時のリダイレクトページ。この URL が Slack OAuth 設定時に指定されている必要がある。アクセストークンを暗号化してセッションに保存し、GET / へリダイレクトされる
POST /slack/logoutログアウト(セッション情報を削除)する
GET /channelsチャネル一覧を取得する。認証後にユーザーページが表示されると内部的にこの REST API が AJAX 実行されて、画面にチャネル一覧が表示される。


では実際に起動してみます。起動サーバーにログインし、ソースコードのあるフォルダに移動した状態で、以下を実行します:
$ npm install
$ node app

そしてウェブブラウザで起動中のアプリケーションにアクセスします。以下の例では localhost:6010 でアプリケーションが起動されている想定になっているので、http://localhost:6010/ にアクセスします。上記の GET / が実行され、ログイン前のシンプルなページが表示されます。ここで "Login" を選択します:
2019052411


GET /slack/login が実行され、ブラウザは Slack API の OAuth 認証ページにリダイレクトされます。アプリケーションが利用する scope が表示され、このまま認証処理を許可するかどうかを聞かれます。許可する場合は "Authorize" を選択します:
2019052412


Authorize を選択すると認証と認可が完了し、そのアクセストークンが GET /slack/callback へ渡されます。そこでアクセストークンを暗号化してセッションに含めます。この状態であらためてトップページ(GET /)が表示され、ログイン処理が住んでいるのでログイン後の画面が表示されます。AJAX で GET /channels が実行され、ログインユーザーが参照することのできるチャネルの一覧が表示されれば成功です:
2019052413


以上、Slack API の OAuth を使ってウェブアプリケーションから Slack の認証を行い、認証ユーザーの権限で Slack API を外部から実行する、というアプリケーションのサンプルを作って実行するまでの手順紹介でした。


 

BotKit を使って導入した Slack のボットの挙動を自分なりにカスタマイズしてみましょう。まずは以下のエントリを参考にして、BotKit を導入し、ボットがデフォルトの挙動で動くような状態を作っておいてください:
Slack の BotKit を使う


さて、ボットの実体は bot.js ファイルです。このファイルをテキストエディタで開くと、初期化処理などの後にこのような contoller.hears() の処理がいくつか定義されていることに気付きます:
controller.hears( コマンド, 種類, 処理 );

例えばコマンドとして ['hello','hi'] が定義されているものとして、このような記載を見つけることができます:
controller.hears( ['hello','hi'], 'direct_message,direct_mention,mention', function(bot, message){
       :
  (処理の中身)
       :
} );

これは次のような意味になります:
(1) 'hello' または 'hi' というコマンドを、
(2) 'direct_message'(1対1でのメッセージ)か、'direct_mention'(@XXX hello のように直接メンションされた場合)か、'mention'(hello @XXX のようにメッセージ中でメンションされた場合)に、
(3) function(bot,message){ ... } の内容を実行する

つまり前回のエントリでボットに対して @XXX hello というメッセージをダイレクトメンションで送った時に実行される処理がこれ、ということになります。


では簡単な処理でカスタマイズしてみましょう。bot.js 内に以下のようなコードを追加します:
controller.hears(['double (.*)'],'direct_mention',function(bot, message) {
    var matches = message.text.match(/double (.*)/i);
    var msg = matches[1];
    bot.reply(message,msg+' '+msg);
});

これはボットに対してダイレクトメンションで "@XXX double ABCDE" のようなメッセージが送られた時にハンドルし、"ABCDE ABCDE" のように double に続く部分を2度喋る、という処理をするようなコードです。

この bot.js を保存して実行(実行方法は前回のエントリ参照)し、"@XXX double Happy" のようにダイレクトメンションでメッセージを送ると、"Happy Happy" のような反応をしてくれるはずです:
2016031802


この例では処理内容がかなりシンプルな例でしたが、5行程度の追加でここまでは出来てしまいました。実際には受け取ったパラメータを元にデータベースや外部などから情報を作り出して返す、といったより本格的な Slack ボットを作ることもできると思っています。

応用編というわけではないのですが、REST API を使って外部から情報を取り出して表示する、というサンプルも1つ作ってみました。こちらも同様に bot.js に追加します:
   :
   :
controller.hears(['(usd|eur|gbp|aud|nzd|cad|chf)'],'direct_mention',function    (bot, message) {
  var matches = message.text.match(/(usd|eur|gbp|aud|nzd|cad|chf)/i);
  var cur = matches[0].toUpperCase() + "JPY";
  var request = require( 'request' );
  url = 'http://fx.mybluemix.net/';
  request( url, function( error, response, body ){
    if( !error && response.statusCode == 200 ){
      var json = JSON.parse( body );
      var dt = json['datetime'];
      var rate = json['rate'];
      var p = rate[cur];
      bot.reply( message, dt + ' ' + p );
    }
  });
});

以前作った為替の JSON サービス(http://fx.mybluemix.net/)を使い、ダイレクトメンションで USD(米ドル)EUR(ユーロ)GBP(英ポンド)AUD(豪ドル)NZD(NZドル)CAD(カナダドル)CHF(スイスフラン)のいずれかを受け取った場合、それらの通貨が日本円だといくらになるのか、をリアルタイムに計算して返信してくれる、というボットです:
2016032101


Node.js、というか JavaScript での実装に慣れない人がいるかもしれませんが、比較的簡単な言語だと思うので、この Slack ボットを作る機会と一緒に勉強して慣れておくと面白いと思います。


Slack のボットを作るためのフレームワークである BotKit の使い方(というか導入方法)を紹介します。


前提条件として、当然ですが Slack のアカウントは必要です。お持ちでない場合は Slack のページでサインアップおよびサインインを済ませておいてください。サインイン済みの環境に対してボットを作成します。

また BotKit は Node.js のアプリケーションとして動作するので、そのパッケージマネージャである npm が導入されている必要があります。(CentOS 環境用の内容ですが)以下のページを参照するなどして、npm コマンドが使える状態を作っておいてください:
CentOS に StrongLoop をインストールする


最初に Slack の Bot creation page にアクセスして、新しいボットを1つ作成します:
Bot creation page


アクセス先でボットの名前を指定(下図では @dotnsf_bot)して、"Add bot integration" ボタンをクリックすると、ボットが作成されます。ボットの名前は他の人が使っていると使えないので気をつけてください:
2016031701


ボットの作成に成功すると以下の様な画面になり、API Token が表示されます。この値を後で使います。メモ帳などにコピーしておきます:
2016031702


仮にこの API Token の値が xoxb-XXX(API Token)XXX であったとして以下を紹介します。適宜自分の環境と読み替えてください。

次に BotKit をダウンロードします。npm をセットアップしたシステムにログインし、適当なディレクトリ(以下の例では /usr/local/src/)で以下のコマンドを続けて実行し、必要なパッケージとその依存パッケージをダウンロードします:
# cd /usr/local/src
# git clone https://github.com/howdyai/botkit.git
# cd botkit
# npm install

全て導入が完了したら、上記で取得した API Token を使ってボットを動かします(以下を一行で実行します):
# token=xoxb-XXX(API Token)XXX node bot.js

すると以下の様な画面になって、ボットが起動します(途中でボットを強制終了させる場合は Ctrl+C で抜けます):
2016031703



デフォルトのボット(実体は bot.js)ではいくつかの決められた挙動をするように実装されています。いくつか試してみましょう。


まず自分の Slack ID で(ボットを作成した時の Slack ID で)Slack にアクセスし、適当なチャネル(例えば #general)に入ります:
2016031704


以下のコマンドをメッセージとして入力し、ボットをこのチャネルに招待します:
/invite @(ボットの名前)
2016031705


続けて "Hello" というメッセージをこのボット宛に送ります。頭に @(ボットの名前): を付けてメッセージを送ります:
@(ボットの名前): Hello


するとボットが反応し、Hello というメッセージを返してくれます。最初の会話が成立しました:
2016031706



続けて自分のことを聞いてみます。先程と同様にして "Who am i" というメッセージを送ってみますが、"I don't know yet!"(「まだ知らない」)という答が返ってきました。そりゃそうだ:
2016031707


というわけで自分のことを教えてあげましょう。"call me (名前)" というメッセージを送ります。「次からはそう呼ぶ」と分かってくれたっぽい感じ:
2016031708


では改めて "Who am i" と聞いてみます。今度は自分が指定した名前を返してくれました。一応覚えていてくれたっぽいです:
2016031709


最後にこのボットを Slack から終了する方法も紹介します。実行中のコマンドラインから Ctrl + C で強制終了することもできますが、"shutdown" と命令し、確認のメッセージに "Y" と回答するとボットはシャットダウンします(コマンドも終了します):
2016031801




と、デフォルトのボットの挙動はまあこんな感じです。この中身は bot.js の中で実装されていて、そのカスタマイズもこのファイルを編集することになりますが、それについては別のまた機会に。

(2016/Mar/22 追記)
続きはこちら


このページのトップヘ