LoginSignup
8
9

More than 5 years have passed since last update.

SpockとLINE BOTでオウム返しを作ってみた

Posted at

LINE BOT API がトライアル版ですが公開されたので早速試してみました。
APIの詳細なドキュメントはここに載っています。
https://developers.line.me/bot-api/overview

プログラムは
とりあえずLINE BOT APIでオウムを作ってみた
LINE BOT をとりあえずタダで Heroku で動かす
を参考にしながらオウム返しを作りました。

{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Lens ((^?))
import Control.Monad.IO.Class (liftIO)
import Data.Aeson
import Data.Aeson.Lens (key, _Array)
import qualified Data.ByteString.Char8 as BS
import Data.Foldable (for_)
import System.Environment (lookupEnv)

import Network.HTTP.Conduit
import Web.Spock.Safe

main :: IO ()
main = do
    -- 環境変数の読み込み
    port <- maybe 8080 read <$> lookupEnv "PORT" :: IO Int
    Just fixie_basic         <- lookupEnv "FIXIE_BASIC"
    Just line_channel_id     <- lookupEnv "LINE_CHANNEL_ID"
    Just line_channel_secret <- lookupEnv "LINE_CHANNEL_SECRET"
    Just line_channel_mid    <- lookupEnv "LINE_CHANNEL_MID"
    -- サーバーの起動
    runSpock port . spockT id $ do
       -- POST /callback
       post "callback" $ do
           b <- body
           let Just result = (b ^? key "result" . _Array)
           for_ result $ \msg -> do
               let Just content = msg ^? key "content"
                   Just from    = content ^? key "from"
               liftIO $ do
                   -- メッセージ送信リクエストの作成
                   req <- parseUrl "https://trialbot-api.line.me/v1/events"
                   manager <- newManager tlsManagerSettings
                   let res = object [ "to"        .= Array [from]
                                    , "toChannel" .= Number 1383378250
                                    , "eventType" .= String "138311608800106203"
                                    , "content"   .= content]
                       req' = req { proxy = Just (Proxy {proxyHost = "velodrome.usefixie.com", proxyPort = 80})
                                  , method = "POST"
                                  , requestHeaders = [ ("Content-Type", "application/json; charser=UTF-8")
                                                     , ("X-Line-ChannelID", BS.pack line_channel_id)
                                                     , ("X-Line-ChannelSecret", BS.pack line_channel_secret)
                                                     , ("X-Line-Trusted-User-With-ACL", BS.pack line_channel_mid)
                                                     , ("Proxy-Authorization", BS.pack $ "Basic " ++ fixie_basic)
                                                     ]
                                  , requestBody = RequestBodyLBS (encode res)
                                  }
                   -- 送信
                   httpLbs req' manager
           text ""

少し躓いたのはhttp-conduitProxyはプロキシのURLのBasic認証の部分をパースしてくれないのでProxy-Authorizationのヘッダを自分で作らないといけないというところ。環境変数のFIXIE_BASICにはFixieのBasic認証のユーザー名とパスワードがBase64でエンコードされたものが入っています。

上記コードは実際にHerokuにデプロイして動作確認しました。
HaskellアプリのHerokuへのデプロイ方法は手前味噌ですが以下が参考になります。
HerokuにHaskellのアプリを公開する

Haskellはいいぞ!

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9