Haskell
Slack

HaskellでSlack bot (RTM API)

More than 1 year has passed since last update.


はじめに

SlackでBotを書きたいけど、Hubotは使いたくないし、なによりJavascriptを書きたくない。

でも直にReal Time Messaging APIを叩きに行くのはしんどい。

Hackageにいい感じのライブラリないかな…→ありました

https://hackage.haskell.org/package/slack-api

ということで、覚えたてのHaskell stackを使って、RTM APIを叩きに行くサンプルを作りました。

今回はgithubに載ってたEchoBotを動かすとこまで。


Slack bot

まずはbotのtokenを発行します。

https://slack.com/apps/A0F7YS25R-bots

(無料プランだとintegrationは10個までなので気をつけてください)

適当にUsernameを決めると謎の文字列(token)が手に入ります。魔法の呪文なので公開しないように。

もうこの時点でAPI documentのやつが使えるので、適当に

$ curl "https://slack.com/api/api.test" -X POST -d "token=xxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"

とかやるとjsonが帰ってきます。

{"ok":true,"args":{"token":"xxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"}}

お手軽ですね。

chat.postMessageとかもあります。一通り遊んでみましょう。


Haskell stack

stackが神すぎて泣いてます。

How to installに書いてある一行でインストールできるので今すぐ入れましょう。

適当な作業directoryで

$ stack new my-bot && cd my-bot

するといい感じのtemplateができます。

slack-apiはStackageには入ってないようなので、extra-depsに書きます。

diff --git a/stack.yaml b/stack.yaml

index 45ed1cb..754e7ac 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -39,7 +39,8 @@ packages:
- '.'
# Dependency packages to be pulled from upstream that are not in the resolver
# (e.g., acme-missiles-0.3)
-extra-deps: []
+extra-deps:
+- slack-api-0.11

そしてmy-bot.cabalに依存関係を書きます。

diff --git a/slackbot.cabal b/slackbot.cabal

index 75da504..041d58c 100644
--- a/slackbot.cabal
+++ b/slackbot.cabal
@@ -25,6 +25,7 @@ executable slackbot
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, slackbot
+ , slack-api
default-language: Haskell2010

test-suite slackbot-test

いったんbuildしてみます。結構時間がかかると思います。

$ stack build

これだけでslack-apiが使えるようになりました。


サンプルコードを動かす

slack-apiのgithubにあるExampleを動かしてみます。

app/Main.hsをまるっと以下で書き換えます。

module EchoBot where

import Web.Slack
import Web.Slack.Message
import System.Environment (lookupEnv)
import Data.Maybe (fromMaybe)
import Control.Applicative

myConfig :: String -> SlackConfig
myConfig apiToken = SlackConfig
{ _slackApiToken = apiToken -- Specify your API token here
}

echoBot :: SlackBot ()
echoBot (Message cid _ msg _ _ _) = sendMessage cid msg
echoBot _ = return ()

main :: IO ()
main = do
apiToken <- fromMaybe (error "SLACK_API_TOKEN not set")
<$> lookupEnv "SLACK_API_TOKEN"
runBot (myConfig apiToken) echoBot ()

そしてbuild。

$ stack build

起動。

$ env SLACK_API_TOKEN=xxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx stack exec my-bot-exe

botがオンライン状態になると思います。DMを送ってみましょう。

slack.png

OK. オウム返しBOTの完成です。


まとめ

Haskell Stackを使ってSlackのRTM APIを叩くライブラリを扱えました。

stack.yamlとmy-bot.cabalの連携が最初よくわからなかったんですが、stackがここにこう書けばいいよ~って教えてくれたりしてすごかったです。

stack便利だなぁ

今回はデプロイまでは扱いませんでしたが、サーバって感じでもない(外部にポート晒したりしない)のでローカルで動かしておけばいいのでは?って感じもします。

どうでもいいけどslackとstackをよく見間違えます。