hask-irc/Network/IRC/Handlers/SongSearch.hs

49 lines
1.8 KiB
Haskell

{-# LANGUAGE RecordWildCards, OverloadedStrings, ScopedTypeVariables #-}
module Network.IRC.Handlers.SongSearch (songSearch) where
import Control.Applicative
import Control.Exception
import Control.Monad
import Control.Monad.Trans
import Data.Aeson
import Data.Aeson.Types (emptyArray)
import Data.Configurator
import Data.Text
import Network.Curl.Aeson
import Network.HTTP.Base
import Prelude hiding (putStrLn, drop, lookup)
import Network.IRC.Types
data Song = NoSong | Song { url :: Text, name :: Text, artist :: Text }
deriving (Show, Eq)
instance FromJSON Song where
parseJSON (Object o) = Song <$> o .: "Url" <*> o .: "SongName" <*> o .: "ArtistName"
parseJSON a | a == emptyArray = return NoSong
parseJSON _ = mzero
songSearch :: MonadIO m => BotConfig -> Message -> m (Maybe Command)
songSearch BotConfig { .. } ChannelMsg { .. }
| "!m " `isPrefixOf` msg = liftIO $ do
let query = strip . drop 3 $ msg
mApiKey <- lookup config "songsearch.tinysong_apikey"
fmap (Just . ChannelMsgReply) $ case mApiKey of
Nothing -> -- do log "tinysong api key not found in config"
return $ "Error while searching for " +++ query
Just apiKey -> do
let apiUrl = "http://tinysong.com/b/" ++ urlEncode (unpack query)
++ "?format=json&key=" ++ apiKey
result <- try $ curlAesonGet apiUrl >>= evaluate
return $ case result of
Left (_ :: CurlAesonException) -> "Error while searching for " +++ query
Right song -> case song of
Song { .. } -> "Listen to " +++ artist +++ " - " +++ name +++ " at " +++ url
NoSong -> "No song found for: " +++ query
| otherwise = return Nothing
where
(+++) = append
songSearch _ _ = return Nothing