Edited at

Slackからメッセージ取得してShinyで表示してみる

More than 1 year has passed since last update.

R言語のWebアプリ作成フレームワークShinyを使って、外部のWebAPIにアクセスするときのTipsです。

いろんなAPIと連携できるとRとShinyの表現力がより活かせますね。

今回はSlackからメッセージ履歴を取得してみます。


Slack側の準備

WebAPIを利用する場合、大体利用するシステム側でこういった準備が必要かと。不要な場合もありますが。


トークン取得

slack APIのページからトークン取得を行います。

レガシーなやつと新しいやつがありますが、今回はとりあえずレガシーなほうで。

こちらはAPIにアクセスするときに必要になるのでメモしておきましょう。


チャンネルIDの取得

指定のチャンネルのメッセージをとってくる場合、チャンネル名指定ではダメで、チャンネルIDが必要になります。

このIDがどこから取得していいかわかりにくいかったので、簡単な方法をメモ。

Web版のslackに移行し、該当ちゃんねるを開くと、URLにIDが出てきます。


エンドポイントの確認

利用したいアクションごとにURLが用意されているので、使いたいものを確認します。このページで必要なパラメータを確認します。

今回は特定のチャンネルのメッセージをとってこようと思うので、channels.historyを利用します。

おっと、期間指定がUNIX時間のようですね。


Shiny側のTips


パラメータ作成

まず、API側に送りつけるパラメータをlist形式で作成します。

Shinyの通常の構成としては画面側(ui.R)で入力部品を用意して、その入力の変化をトリガーにロジック側(server.R)の処理を動かします。

例えば、期間指定とトークンとチャンネルIDを受け取って、パラメータを作る場合は


ui.R

# サイドバーのところ

sidebarLayout(
sidebarPanel(
dateRangeInput(
"date_range",
"範囲選択",
start = format(Sys.Date()-1, "%Y-%m-%d"),
end = format(Sys.Date(), "%Y-%m-%d")
),
textInput('token',"トークン"),
textInput('channel',"チャンネルID")
),
# MainPanel
mainPanel(
###
)
)


server.R

getVal <- function(obj){

if(is.null(obj) || is.na(obj)){
return("")
}else{
return(obj)
}
}

endPoint.history <- 'https://slack.com/api/channels.history'

# slackへの送信パラメータ作成
getParams <- reactive({
oldest = as.numeric(as.POSIXct(as.Date(input$date_range[1])))
latest = as.numeric(as.POSIXct(as.Date(input$date_range[2])))
token = input$token
channel = input$channel

params <- list(
token = getVal(token),
channel = getVal(channel),
count = 1000,
latest = latest,
oldest = oldest
)
params
})


こんな感じ。

UNIX時間に変換する場合はPOSIXct型のものをas.numericで数値にすると大丈夫です。

また、入力を受ける場合reactiveである必要があるのでreactive({})で定義します。


URLからパラメータ取得

トークンなどをプログラム中に埋め込むのはいやなので、URLに引っ付けれるようにします。

http://xxx/shiny/?token=aaaaa

みたいなページを開くとトークンが設定されるようにしてみます。

URLの情報を取得したい場合は

session$clientDataから各種情報が取得できます。

?token=aaaaaを取得して、それをセットした状態でテキストボックスを生成するという場合、ui.R側にはuiOutput('name')を用意しておき、サーバー側でtextInput部品を生成します。


ui.R

#    textInput('token',"トークン"),

uiOutput('tokenOut')


server.R

output$tokenOut <- renderUI({

urlInfo <- parseQueryString(session$clientData$url_search)

textInput('token',"トークン", urlInfo[["token"]])
})



APIアクセスとデータ取得

HTTPアクセス周りをサポートしてくれるhttrパッケージを入れておくと便利です。

こちらのPOSTメソッドを使ってアクセスします。上で作成したパラメータを渡して情報を取得します。


server.R

  getSlackData <- reactive({

params <- getParams()

resp <- POST(endPoint.history,
body = params,
encode = "multipart",
content_type = "application/x-www-form-urlencoded"
# ,verbose() # コレつけるとリクエスト・レスポンスの詳細が見れる
)
jsonFromSlack <- content(resp, "parsed")
# 取得した情報がlist形式に得られるのでここから自由に加工
})


[翻訳] httr vignette: httrはやわかり

このあたりが抑えられれば、あとは通常のR&Shinyの書き方でグラフやら表やらを作っていくとWebアプリが出来上がりそうです。

とりあえず作ってみているサンプルソースコードはこちら

Slackはメッセージ自体に階層構造持たせたりできるので、そのあたりもうまく解析して必要なメッセージが取得できるような汎用性を持たせたい。