Browse Source

initial commit

master
Wesley Kerfoot 5 years ago
parent
commit
a903345c55
  1. 29
      app/Main.hs
  2. 1
      package.yaml
  3. 47
      src/IRCParser.hs
  4. 15
      src/Lib.hs
  5. 7
      src/Types.hs

29
app/Main.hs

@ -1,3 +1,5 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where module Main where
import Lib import Lib
@ -9,6 +11,22 @@ import Network.Socket hiding (recv)
import Network.Socket.ByteString as S import Network.Socket.ByteString as S
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
import Control.Concurrent (threadDelay, forkIO) import Control.Concurrent (threadDelay, forkIO)
import Data.Text (isInfixOf)
getNick (Message source _ _) = maybe "" id (sourceNick <$> source)
react sock msg = do
case (ircCommand msg) of
"PING" -> sendMany sock (buildCommand <$> [pong (head $ ircCommandArgs msg)])
"PRIVMSG" -> if ("crapbot" `isInfixOf` (head $ tail $ ircCommandArgs msg)) then
sendMany sock
(buildCommand <$>
[privmsg (head $ ircCommandArgs msg) (mconcat ["Hello there ", getNick msg, "!"])])
else
return ()
command -> print command
return ()
channel = "#thisisatestwhatever" channel = "#thisisatestwhatever"
@ -24,7 +42,11 @@ getIRCSock addr = socket (addrFamily addr) Stream defaultProtocol
recvLoop sock = do recvLoop sock = do
msg <- recv sock 4096 msg <- recv sock 4096
print $ runParseMessage msg case runParseMessage msg of
Left _ -> return ()
Right msg -> do
_ <- react sock msg
print msg
threadDelay 1000000 threadDelay 1000000
recvLoop sock recvLoop sock
@ -36,4 +58,7 @@ sendIRCConnect host = do
threadDelay 1000000 threadDelay 1000000
sendMany sock (buildCommand <$> [userCmd, nickCmd, joinCmd, initMsgCmd]) sendMany sock (buildCommand <$> [userCmd, nickCmd, joinCmd, initMsgCmd])
main = undefined main = do
_ <- sendIRCConnect "irc.freenode.org"
_ <- getLine
return ()

1
package.yaml

@ -25,6 +25,7 @@ dependencies:
- bytestring - bytestring
- network - network
- attoparsec - attoparsec
- either
library: library:
source-dirs: src source-dirs: src

47
src/IRCParser.hs

@ -1,24 +1,47 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module IRCParser where module IRCParser where
import Data.Text (strip)
import Data.Text.Encoding (decodeUtf8)
import Data.ByteString (pack) import Data.ByteString (pack)
import Data.Attoparsec.ByteString import Data.Attoparsec.ByteString
import Control.Applicative import Control.Applicative
import Data.Either.Combinators (rightToMaybe)
import Types
-- :nisstyre!wes@oftn/oswg-member/Nisstyre PRIVMSG #thisisatestwhatever :yay\r\n stripWhitespace = filter $ (all id) . (sequence $ map (/=) [" ", "\r", "\n", ""])
-- :nisstyre!wes@oftn/oswg-member/Nisstyre PART #thisisatestwhatever :\"WeeChat 2.2\"\r\n
-- :nisstyre!wes@oftn/oswg-member/Nisstyre JOIN #thisisatestwhatever\r\n
-- :nisstyre!wes@oftn/oswg-member/Nisstyre QUIT :Quit: WeeChat 2.2\r\n
-- PING :asimov.freenode.net\r\n
space = word8 32 space = word8 32
notSpace = notWord8 32 notSpace = notWord8 32
colon = word8 58 -- :
-- 13 = \r, 10 = \n -- 13 = \r, 10 = \n
crlf c = c == 13 || c == 10 crlf c = c == 13 || c == 10
-- : bang = (== 33) -- !
colon = word8 58 atsign = (== 64) -- @
isSpace = (== 32)
parseNick = takeWhile1 (not . bang)
parseUsername = do
_ <- word8 33
username <- takeWhile1 (not . atsign)
return username
parseHostmask = do
_ <- word8 64
hostmask <- takeWhile1 (not . isSpace)
return hostmask
parseSource = do
nickname <- parseNick
username <- parseUsername
hostmask <- parseHostmask
return $ Source
(decodeUtf8 nickname)
(decodeUtf8 username)
(decodeUtf8 hostmask)
command = choice $ map string ["PRIVMSG", "PART", "JOIN", "QUIT", "PING"] command = choice $ map string ["PRIVMSG", "PART", "JOIN", "QUIT", "PING"]
@ -33,7 +56,7 @@ parseArgs = do
args <- (argument `sepBy` space) <|> alwaysMatch [] args <- (argument `sepBy` space) <|> alwaysMatch []
_ <- space <|> (alwaysMatch 0) _ <- space <|> (alwaysMatch 0)
finalArg <- parseFinalArg <|> (alwaysMatch "") finalArg <- parseFinalArg <|> (alwaysMatch "")
return (args, finalArg) return $ args ++ [finalArg]
source = do source = do
_ <- colon _ <- colon
@ -49,6 +72,12 @@ parseMessage = do
commandName <- command commandName <- command
_ <- space _ <- space
arguments <- parseArgs arguments <- parseArgs
return (pack sourceName, commandName, arguments)
let source = parseOnly parseSource $ pack sourceName
return $ Message
(rightToMaybe source)
(decodeUtf8 commandName)
(map strip $ stripWhitespace $ map decodeUtf8 arguments)
runParseMessage = parseOnly parseMessage runParseMessage = parseOnly parseMessage

15
src/Lib.hs

@ -7,15 +7,18 @@ import qualified Data.Text.Encoding as TE
import Data.ByteString import Data.ByteString
import Types import Types
user name desc = Message "USER" [" ", name, " * * :", desc] user name desc = Message Nothing "USER" [" ", name, " * * :", desc]
nick name = Message "NICK" [" ", name] nick name = Message Nothing "NICK" [" ", name]
join channel = Message "JOIN" [" ", channel] join channel = Message Nothing "JOIN" [" ", channel]
privmsg channel message = Message "PRIVMSG" [" ", channel, " :", message] privmsg channel message = Message Nothing "PRIVMSG" [" ", channel, " :", message]
quit = Message "QUIT" [] pong message = Message Nothing "PONG" [":", message]
quit = Message Nothing "QUIT" []
buildCommand :: Message -> ByteString buildCommand :: Message -> ByteString
buildCommand (Message cmd args) = TE.encodeUtf8 $ (cmd `T.append` (mconcat args)) `T.append` "\r\n" buildCommand (Message Nothing cmd args) = TE.encodeUtf8 $ (cmd `T.append` (mconcat args)) `T.append` "\r\n"
buildCommand (Message (Just source) cmd args) = TE.encodeUtf8 $ (cmd `T.append` (mconcat args)) `T.append` "\r\n"

7
src/Types.hs

@ -2,7 +2,14 @@ module Types where
import qualified Data.Text as T import qualified Data.Text as T
data Source = Source {
sourceNick :: T.Text,
sourceUsername :: T.Text,
sourceHostmask :: T.Text
} deriving (Show)
data Message = Message { data Message = Message {
ircSource :: Maybe Source,
ircCommand :: T.Text, ircCommand :: T.Text,
ircCommandArgs :: [T.Text] ircCommandArgs :: [T.Text]
} deriving (Show) } deriving (Show)

Loading…
Cancel
Save