Moved to basic-prelude, sanitized imports

master
Abhinav Sarkar 2014-05-10 20:01:25 +05:30
parent f8471130e4
commit cfc796564a
7 changed files with 59 additions and 65 deletions

25
Main.hs
View File

@ -1,14 +1,13 @@
{-# LANGUAGE OverloadedStrings, OverlappingInstances #-} {-# LANGUAGE OverloadedStrings, OverlappingInstances, NoImplicitPrelude #-}
module Main (main) where module Main (main) where
import qualified Data.Configurator as CF
import qualified Data.Text as T import qualified Data.Text as T
import BasicPrelude hiding (try, getArgs)
import Control.Exception import Control.Exception
import Control.Monad
import Data.Configurator
import Data.Configurator.Types import Data.Configurator.Types
import Data.Maybe
import System.Environment import System.Environment
import System.Exit import System.Exit
@ -25,25 +24,25 @@ main = do
prog <- getProgName prog <- getProgName
when (length args < 1) $ do when (length args < 1) $ do
putStrLn ("Usage: " ++ prog ++ " <config file path>") putStrLn $ "Usage: " ++ T.pack prog ++ " <config file path>"
exitFailure exitFailure
let configFile = head args let configFile = head args
loadBotConfig configFile >>= run loadBotConfig configFile >>= run
loadBotConfig :: FilePath -> IO BotConfig loadBotConfig :: String -> IO BotConfig
loadBotConfig configFile = do loadBotConfig configFile = do
eCfg <- try $ load [Required configFile] eCfg <- try $ CF.load [Required configFile]
case eCfg of case eCfg of
Left (ParseError _ _) -> error "Error while loading config" Left (ParseError _ _) -> error "Error while loading config"
Right cfg -> do Right cfg -> do
eBotConfig <- try $ do eBotConfig <- try $ do
server <- require cfg "server" server <- CF.require cfg "server"
port <- require cfg "port" port <- CF.require cfg "port"
channel <- require cfg "channel" channel <- CF.require cfg "channel"
botNick <- require cfg "nick" botNick <- CF.require cfg "nick"
timeout <- require cfg "timeout" timeout <- CF.require cfg "timeout"
handlers <- require cfg "handlers" handlers <- CF.require cfg "handlers"
return $ BotConfig server port channel botNick timeout handlers cfg return $ BotConfig server port channel botNick timeout handlers cfg
case eBotConfig of case eBotConfig of

View File

@ -1,20 +1,19 @@
{-# LANGUAGE RecordWildCards, ScopedTypeVariables #-} {-# LANGUAGE RecordWildCards, ScopedTypeVariables, NoImplicitPrelude, OverloadedStrings #-}
module Network.IRC.Client (run) where module Network.IRC.Client (run) where
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Format as TF
import qualified Data.Text.Format.Params as TF
import Control.Exception import BasicPrelude hiding (log)
import Control.Concurrent import Control.Concurrent
import Control.Monad
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State import Control.Monad.State
import Network import Network
import Prelude hiding (log)
import System.IO import System.IO
import System.Time import System.Time
import System.Timeout import System.Timeout
import Text.Printf
import Network.IRC.Handlers import Network.IRC.Handlers
import Network.IRC.Protocol import Network.IRC.Protocol
@ -23,13 +22,14 @@ import Network.IRC.Types
oneSec :: Int oneSec :: Int
oneSec = 1000000 oneSec = 1000000
log :: String -> IO () log :: Text -> IO ()
log msg = getClockTime >>= \t -> printf "[%s] ** %s\n" (show t) msg log msg = getClockTime >>= \t -> TF.print "[{}] ** {}\n" $ TF.buildParams (show t, msg)
sendCommand :: Bot -> Command -> IO () sendCommand :: Bot -> Command -> IO ()
sendCommand Bot { .. } reply = do sendCommand Bot { .. } reply = do
let line = T.unpack $ lineFromCommand botConfig reply let line = lineFromCommand botConfig reply
hPrintf socket "%s\r\n" line >> printf "> %s\n" line TF.hprint socket "{}\r\n" $ TF.Only line
TF.print "> {}\n" $ TF.Only line
listen :: IRC () listen :: IRC ()
listen = do listen = do
@ -46,7 +46,7 @@ listen = do
Nothing -> return Disconnected Nothing -> return Disconnected
Just line -> do Just line -> do
now <- getClockTime now <- getClockTime
printf "[%s] %s\n" (show now) line TF.print "[{}] {}\n" $ TF.buildParams (show now, line)
let message = msgFromLine botConfig now (T.pack line) let message = msgFromLine botConfig now (T.pack line)
case message of case message of
@ -59,7 +59,7 @@ listen = do
msg -> forM_ (handlers botConfig) $ \handlerName -> forkIO $ do msg -> forM_ (handlers botConfig) $ \handlerName -> forkIO $ do
let mHandler = getHandler handlerName let mHandler = getHandler handlerName
case mHandler of case mHandler of
Nothing -> log $ "No handler found with name: " ++ T.unpack handlerName Nothing -> log $ "No handler found with name: " ++ handlerName
Just handler -> do Just handler -> do
mCmd <- runHandler handler botConfig msg mCmd <- runHandler handler botConfig msg
case mCmd of case mCmd of

View File

@ -1,20 +1,16 @@
{-# LANGUAGE RecordWildCards, OverloadedStrings #-} {-# LANGUAGE RecordWildCards, OverloadedStrings, NoImplicitPrelude #-}
module Network.IRC.Handlers (getHandler) where module Network.IRC.Handlers (getHandler) where
import qualified Data.List as L import qualified Data.Text as T
import Data.Text import BasicPrelude
import Prelude hiding ((++))
import Network.IRC.Handlers.SongSearch import Network.IRC.Handlers.SongSearch
import Network.IRC.Types import Network.IRC.Types
clean :: Text -> Text clean :: Text -> Text
clean = toLower . strip clean = T.toLower . T.strip
(++) :: Text -> Text -> Text
(++) = append
getHandler :: HandlerName -> Maybe Handler getHandler :: HandlerName -> Maybe Handler
getHandler "greeter" = Just $ Handler greeter getHandler "greeter" = Just $ Handler greeter
@ -23,7 +19,7 @@ getHandler "songsearch" = Just $ Handler songSearch
getHandler _ = Nothing getHandler _ = Nothing
greeter :: Monad m => BotConfig -> Message -> m (Maybe Command) greeter :: Monad m => BotConfig -> Message -> m (Maybe Command)
greeter _ ChannelMsg { .. } = case L.find (== clean msg) greetings of greeter _ ChannelMsg { .. } = case find (== clean msg) greetings of
Nothing -> return Nothing Nothing -> return Nothing
Just greeting -> return . Just . ChannelMsgReply $ greeting ++ " " ++ userNick user Just greeting -> return . Just . ChannelMsgReply $ greeting ++ " " ++ userNick user
where where

View File

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

View File

@ -1,18 +1,18 @@
{-# LANGUAGE RecordWildCards, OverloadedStrings #-} {-# LANGUAGE RecordWildCards, OverloadedStrings, NoImplicitPrelude #-}
module Network.IRC.Protocol (msgFromLine, lineFromCommand) where module Network.IRC.Protocol (msgFromLine, lineFromCommand) where
import qualified Data.List as L import qualified Data.List as L
import qualified Data.Text as T
import Data.Text import BasicPrelude
import Prelude hiding (drop, unwords, takeWhile, (++))
import System.Time import System.Time
import Network.IRC.Types import Network.IRC.Types
msgFromLine :: BotConfig -> ClockTime -> Text -> Message msgFromLine :: BotConfig -> ClockTime -> Text -> Message
msgFromLine (BotConfig { .. }) time line msgFromLine (BotConfig { .. }) time line
| "PING :" `isPrefixOf` line = Ping time . drop 6 $ line | "PING :" `T.isPrefixOf` line = Ping time . T.drop 6 $ line
| otherwise = case command of | otherwise = case command of
"JOIN" -> JoinMsg time user "JOIN" -> JoinMsg time user
"QUIT" -> QuitMsg time user message "QUIT" -> QuitMsg time user message
@ -21,7 +21,7 @@ msgFromLine (BotConfig { .. }) time line
"MODE" -> if source == botNick "MODE" -> if source == botNick
then ModeMsg time Self target message [] then ModeMsg time Self target message []
else ModeMsg time user target mode modeArgs else ModeMsg time user target mode modeArgs
"NICK" -> NickMsg time user (drop 1 target) "NICK" -> NickMsg time user (T.drop 1 target)
"PRIVMSG" -> if target == channel "PRIVMSG" -> if target == channel
then ChannelMsg time user message then ChannelMsg time user message
else PrivMsg time user message else PrivMsg time user message
@ -29,16 +29,16 @@ msgFromLine (BotConfig { .. }) time line
where where
isSpc = (== ' ') isSpc = (== ' ')
isNotSpc = not . isSpc isNotSpc = not . isSpc
splits = split isSpc line splits = T.split isSpc line
source = drop 1 . takeWhile isNotSpc $ line source = T.drop 1 . T.takeWhile isNotSpc $ line
target = splits !! 2 target = splits !! 2
command = splits !! 1 command = splits !! 1
message = drop 1 . unwords . L.drop 3 $ splits message = T.drop 1 . unwords . L.drop 3 $ splits
user = let u = split (== '!') source in User (u !! 0) (u !! 1) user = let u = T.split (== '!') source in User (u !! 0) (u !! 1)
mode = splits !! 3 mode = splits !! 3
modeArgs = L.drop 4 splits modeArgs = L.drop 4 splits
kicked = splits !! 3 kicked = splits !! 3
kickReason = drop 1 . unwords . L.drop 4 $ splits kickReason = T.drop 1 . unwords . L.drop 4 $ splits
lineFromCommand :: BotConfig -> Command -> Text lineFromCommand :: BotConfig -> Command -> Text
lineFromCommand (BotConfig { .. }) reply = case reply of lineFromCommand (BotConfig { .. }) reply = case reply of
@ -48,5 +48,4 @@ lineFromCommand (BotConfig { .. }) reply = case reply of
JoinCmd -> "JOIN " ++ channel JoinCmd -> "JOIN " ++ channel
ChannelMsgReply { .. } -> "PRIVMSG " ++ channel ++ " :" ++ rmsg ChannelMsgReply { .. } -> "PRIVMSG " ++ channel ++ " :" ++ rmsg
PrivMsgReply (User { .. }) rmsg -> "PRIVMSG " ++ botNick ++ " :" ++ rmsg PrivMsgReply (User { .. }) rmsg -> "PRIVMSG " ++ botNick ++ " :" ++ rmsg
where
(++) = append

View File

@ -1,11 +1,13 @@
{-# LANGUAGE RecordWildCards, RankNTypes, GeneralizedNewtypeDeriving #-} {-# LANGUAGE RecordWildCards, RankNTypes, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}
module Network.IRC.Types where module Network.IRC.Types where
import BasicPrelude hiding (show)
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State import Control.Monad.State
import Data.Configurator.Types import Data.Configurator.Types
import Data.Text (Text) import Prelude (Show(..))
import System.IO import System.IO
import System.Time import System.Time

View File

@ -51,7 +51,8 @@ cabal-version: >=1.10
library library
build-depends: base >=4.5 && <4.7, text >=0.11 && <0.12, mtl >=2.1 && <2.2, build-depends: base >=4.5 && <4.7, text >=0.11 && <0.12, mtl >=2.1 && <2.2,
network >=2.3 && <2.5, old-time >=1.1 && <1.2, configurator >= 0.2, network >=2.3 && <2.5, old-time >=1.1 && <1.2, configurator >= 0.2,
curl-aeson ==0.0.3, aeson >=0.6.0.0, HTTP, transformers >=0.3 curl-aeson ==0.0.3, aeson >=0.6.0.0, HTTP, transformers >=0.3,
basic-prelude ==0.3.8, text-format >= 0.3.1
exposed-modules: Network.IRC.Types, Network.IRC.Protocol, exposed-modules: Network.IRC.Types, Network.IRC.Protocol,
Network.IRC.Handlers, Network.IRC.Client Network.IRC.Handlers, Network.IRC.Client
@ -74,7 +75,8 @@ executable hask-irc
-- Other library packages from which modules are imported. -- Other library packages from which modules are imported.
build-depends: base >=4.5 && <4.7, text >=0.11 && <0.12, mtl >=2.1 && <2.2, build-depends: base >=4.5 && <4.7, text >=0.11 && <0.12, mtl >=2.1 && <2.2,
network >=2.3 && <2.5, old-time >=1.1 && <1.2, configurator >= 0.2, network >=2.3 && <2.5, old-time >=1.1 && <1.2, configurator >= 0.2,
curl-aeson ==0.0.3, aeson >=0.6.0.0, HTTP, transformers >=0.3 curl-aeson ==0.0.3, aeson >=0.6.0.0, HTTP, transformers >=0.3,
basic-prelude ==0.3.8, text-format >= 0.3.1
-- Directories containing source files. -- Directories containing source files.
-- hs-source-dirs: -- hs-source-dirs: