macbeth-lib-0.0.12: src/Macbeth/Fics/Parsers/FicsMessageParser.hs
{-# LANGUAGE OverloadedStrings #-}
module Macbeth.Fics.Parsers.FicsMessageParser (
parseFicsMessage
) where
import Macbeth.Fics.Api.Api
import Macbeth.Fics.Api.Challenge
import Macbeth.Fics.FicsMessage hiding (move)
import Macbeth.Fics.Api.Game
import Macbeth.Fics.Api.Move hiding (Observing)
import Macbeth.Fics.Api.PendingOffer
import Macbeth.Fics.Parsers.Api
import Macbeth.Fics.Parsers.GamesParser
import Macbeth.Fics.Parsers.MoveParser
import Macbeth.Fics.Parsers.RatingParser
import qualified Macbeth.Fics.Parsers.Players as P
import qualified Macbeth.Fics.Parsers.SeekMsgParsers as SP
import Control.Applicative
import Data.Attoparsec.ByteString.Char8
import qualified Data.ByteString.Char8 as BS
parseFicsMessage :: BS.ByteString -> Either String FicsMessage
parseFicsMessage = parseOnly parser where
parser = choice [ SP.clearSeek
, SP.newSeek
, SP.removeSeeks
, SP.seekNotAvailable
, gameMove
, gameCreation
, pieceHolding
, challenge
, matchDeclined
, matchUserNotLoggedIn
, games
, observing
, noSuchGame
, userNotLoggedIn
, abortRequest
, abortRequestDeclined
, takebackRequest
, takebackAccepted
, acceptTakeback
, drawRequest
, drawRequestDeclined
, gameResult'
, promotionPiece
, P.finger
, P.history
, P.players
, P.partnerNotOpen
, P.partnerOffer
, P.partnerAccepted
, P.partnerDeclined
, pending
, pendingTo
, pendingRemoved
, pendingWithdraw
, login
, loginTimeout
, password
, guestLogin
, unknownUsername
, loggedIn
, invalidPassword
, ping
]
gameMove :: Parser FicsMessage
gameMove = GameMove <$> pure None <*> move
gameCreation :: Parser FicsMessage
gameCreation = GameCreation <$> ("{Game " *> decimal <* takeTill (== ')') <* ") Creating ")
observing :: Parser FicsMessage
observing = Observing <$> ("You are now observing game " *> decimal)
noSuchGame :: Parser FicsMessage
noSuchGame = commandHead 80 *> "There is no such game." *> pure NoSuchGame
userNotLoggedIn :: Parser FicsMessage
userNotLoggedIn = UserNotLoggedIn <$> (commandHead 80 *> many1 letter_ascii <* " is not logged in.\n\ETB")
games :: Parser FicsMessage
games = Games <$> (commandHead 43 *> parseGamesList)
challenge :: Parser FicsMessage
challenge = MatchRequested <$> (Challenge
<$> ("Challenge: " *> manyTill anyChar space)
<*> ("(" *> skipSpace *> rating)
<*> (") " *> manyTill anyChar space)
<*> ("(" *> skipSpace *> rating)
<*> (") " *> manyTill anyChar ".")) --unrated blitz 2 12."
matchDeclined :: Parser FicsMessage
matchDeclined = MatchDeclined <$> ("\"" *> manyTill anyChar "\" declines the match offer.")
matchUserNotLoggedIn :: Parser FicsMessage
matchUserNotLoggedIn = MatchUserNotLoggedIn <$> (commandHead 73 *> manyTill anyChar " " <* "is not logged in.")
drawRequest :: Parser FicsMessage
drawRequest = manyTill anyChar space *> "offers you a draw." *> pure DrawRequest
drawRequestDeclined :: Parser FicsMessage
drawRequestDeclined = DrawRequestDeclined <$> manyTill anyChar space <* "declines the draw request."
abortRequest :: Parser FicsMessage
abortRequest = AbortRequest <$> (manyTill anyChar " " <* "would like to abort the game;")
abortRequestDeclined :: Parser FicsMessage
abortRequestDeclined = AbortRequestDeclined <$> manyTill anyChar space <* "declines the abort request."
takebackRequest :: Parser FicsMessage
takebackRequest = TakebackRequest
<$> manyTill anyChar " " <* "would like to take back "
<*> decimal <* " half move(s)."
takebackAccepted :: Parser FicsMessage
takebackAccepted = TakebackAccepted <$> manyTill anyChar " " <* "accepts the takeback request."
acceptTakeback :: Parser FicsMessage
acceptTakeback = GameMove <$>
pure (Takeback Nothing) <*> -- ^ User accepted takeback himself
(commandHead 11 *> "You accept the takeback request from" *> takeTill (== '<') *> move)
gameResult' :: Parser FicsMessage
gameResult' = GameResult
<$> (takeTill (== '{') *> "{Game " *> decimal)
<*> (takeTill (== ')') *> ") " *> manyTill anyChar "} ")
<*> ("1-0" *> pure WhiteWins <|> "0-1" *> pure BlackWins <|> "1/2-1/2" *> pure Draw <|> "*" *> pure Aborted)
promotionPiece :: Parser FicsMessage
promotionPiece = PromotionPiece <$> (commandHead 92 *> "Promotion piece set to " *>
("QUEEN" *> pure Queen <|> "BISHOP" *> pure Bishop <|> "KNIGHT" *> pure Knight <|> "ROOK" *> pure Rook <|> "KING" *> pure King))
pending :: Parser FicsMessage
pending = Pending <$> (PendingOffer
<$> (("<pf>" *> pure From) <|> ("<pt>" *> pure To))
<*> (" " *> decimal)
<*> (" w=" *> P.userHandle)
<*> (" t=" *> manyTill anyChar " ")
<*> ("p=" *> manyTill anyChar "\n"))
pendingTo :: Parser FicsMessage
pendingTo = commandHead 73 *> takeTill (=='<') *> pending
pendingRemoved :: Parser FicsMessage
pendingRemoved = PendingRemoved <$> ("<pr> " *> decimal)
pendingWithdraw :: Parser FicsMessage
pendingWithdraw = commandHead 147 *> takeTill (=='<') *> pendingRemoved
login :: Parser FicsMessage
login = "login: " *> pure Login
loginTimeout :: Parser FicsMessage
loginTimeout = "**** LOGIN TIMEOUT ****" *> pure LoginTimeout
password :: Parser FicsMessage
password = "password: " *> pure Password
guestLogin :: Parser FicsMessage
guestLogin = GuestLogin <$> ("Press return to enter the server as \"" *> manyTill anyChar "\":")
unknownUsername :: Parser FicsMessage
unknownUsername = UnkownUsername <$> ("\"" *> manyTill anyChar "\" is not a registered name.")
loggedIn :: Parser FicsMessage
loggedIn = LoggedIn <$> ("**** Starting FICS session as " *> P.userHandle <* " ****")
invalidPassword :: Parser FicsMessage
invalidPassword = "**** Invalid password! ****" *> pure InvalidPassword
ping :: Parser FicsMessage
ping = Ping
<$> (":min/avg/max/mdev = " *> round `fmap` double)
<*> ("/" *> round `fmap` double)
<*> ("/" *> round `fmap` double)