| fastTimeParser :: Data.Attoparsec.Text.Parser UTCTime
|
| fastTimeParser = do
|
| y <- decimal; char '-'; m <- decimal; char '-'; d <- decimal; char ' '
|
| h <- decimal; char ':'; n <- decimal; char ':'; s <- decimal
|
| pure $ UTCTime (fromGregorian y m d)
|
| (fromIntegral (h * 3600 + n * 60 + s))
|
|
|
| fastParseTime :: T.Text -> Maybe UTCTime
|
| fastParseTime t = either (const Nothing) Just $ parseOnly fastTimeParser t where
|
|
|
| parseWeechatLog :: T.Text -> T.Text -> (M.HashMap T.Text T.Text, V.Vector (UTCTime, WeechatLogEntry))
|
| parseWeechatLog chan log = either (const $ (M.empty, V.empty)) id . (flip parseOnly $ log) $ execute M.empty V.empty
|
|
|
| where opGlyphs = S.fromList "+%@&~"
|
| execute hostmasks acc = do
|
| done <- atEnd
|
| if done then return (hostmasks, acc)
|
| else do
|
| ts <- weechatTimestampParser
|
| (hostmasks', result) <- choice [ Data.Attoparsec.Text.string "--\t" >> takeTill isEndOfLine >> char '\n' >> return (hostmasks, Nothing)
|
| , Data.Attoparsec.Text.string "<--\t" >> weechatPartMsgParser chan hostmasks
|
| , Data.Attoparsec.Text.string "<--\t" >> weechatKickMsgParser chan hostmasks
|
| , Data.Attoparsec.Text.string "<--\t" >> weechatQuitMsgParser hostmasks
|
| , Data.Attoparsec.Text.string "Welcome\t" >> takeTill isEndOfLine >> char '\n' >> return (hostmasks, Nothing)
|
| , Data.Attoparsec.Text.string "-->\t" >> weechatJoinMsgParser chan hostmasks
|
| , parseWeechatPrivMsg chan hostmasks
|
| ]
|
| end <- atEnd
|
| case result of
|
| Just entry -> if end then return $ (hostmasks', V.snoc acc $ (ts, entry))
|
| else execute hostmasks' . V.snoc acc $ (ts, entry)
|
| Nothing -> execute hostmasks acc
|
| weechatTimestampParser :: Data.Attoparsec.Text.Parser UTCTime
|
| weechatTimestampParser = do
|
| t <- fastTimeParser
|
| Data.Attoparsec.Text.take 1
|
| return t
|
|
|
| weechatJoinMsgParser :: T.Text -> M.HashMap T.Text T.Text -> Data.Attoparsec.Text.Parser (M.HashMap T.Text T.Text, Maybe WeechatLogEntry)
|
| weechatJoinMsgParser chan hostmasks = do
|
| n <- takeTill isHorizontalSpace
|
| Data.Attoparsec.Text.take 2
|
| h <- takeTill (== ')')
|
|
|
| takeTill isEndOfLine
|
| (char '\n' >> return ()) <|> pure ()
|
| let hostmasks' = M.insert n h hostmasks
|
| return (hostmasks', Just (WeechatJoinMsg n h chan))
|
| weechatPartMsgParser :: T.Text -> M.HashMap T.Text T.Text -> Data.Attoparsec.Text.Parser (M.HashMap T.Text T.Text, Maybe WeechatLogEntry)
|
| weechatPartMsgParser chan hostmasks = do
|
| n <- takeTill isHorizontalSpace
|
| Data.Attoparsec.Text.take 2
|
|
|
| h <- takeTill (== ')')
|
| Data.Attoparsec.Text.string ") has left "
|
| takeTill (== '(')
|
| Data.Attoparsec.Text.take 1
|
|
|
| m <- takeTill isEndOfLine
|
|
|
| (char '\n' >> return ()) <|> pure ()
|
|
|
| let hostmasks' = M.insert n h hostmasks
|
| return (hostmasks', Just (WeechatPartMsg n h chan (T.dropEnd 1 m)))
|
|
|
| weechatKickMsgParser :: T.Text -> M.HashMap T.Text T.Text -> Data.Attoparsec.Text.Parser (M.HashMap T.Text T.Text, Maybe WeechatLogEntry)
|
| weechatKickMsgParser chan hostmasks = do
|
| n <- takeTill isHorizontalSpace
|
|
|
| Data.Attoparsec.Text.take 1
|
| string "has kicked "
|
| p <- takeTill isHorizontalSpace
|
| Data.Attoparsec.Text.take 2
|
| m <- takeTill isEndOfLine
|
| (char '\n' >> return ()) <|> pure ()
|
| let host = M.lookup n hostmasks
|
| return (hostmasks, Just (WeechatKickMsg n host p chan (T.dropEnd 1 m)))
|
|
|
| weechatQuitMsgParser :: M.HashMap T.Text T.Text -> Data.Attoparsec.Text.Parser (M.HashMap T.Text T.Text, Maybe WeechatLogEntry)
|
| weechatQuitMsgParser hostmasks = do
|
| n <- takeTill isHorizontalSpace
|
|
|
| Data.Attoparsec.Text.take 2
|
| h <- takeTill (== ')')
|
| takeTill (== '(')
|
| Data.Attoparsec.Text.take 1
|
| m <- takeTill isEndOfLine
|
| (char '\n' >> return ()) <|> pure ()
|
| let hostmasks' = M.insert n h hostmasks
|
| return (hostmasks', Just (WeechatQuitMsg n h (T.dropEnd 1 m)))
|
| parseWeechatPrivMsg :: T.Text -> M.HashMap T.Text T.Text -> Data.Attoparsec.Text.Parser (M.HashMap T.Text T.Text, Maybe WeechatLogEntry)
|
| parseWeechatPrivMsg chan hostmasks = do
|
| n <- takeTill (== '\t')
|
| Data.Attoparsec.Text.take 1
|
| m <- takeTill isEndOfLine
|
| (char '\n' >> return ()) <|> pure ()
|
| let host = M.lookup n hostmasks
|
| return (hostmasks, Just (WeechatPrivMsg (T.filter (not . (`elem` opGlyphs)) n) host chan m))
|