glirc 2.0 → 2.1
raw patch · 18 files changed
+1171/−1434 lines, 18 filesdep +memorydep +vector
Dependencies added: memory, vector
Files
- ChangeLog.md +8/−0
- README.md +6/−0
- glirc.cabal +4/−1
- src/Client/ChannelState.hs +5/−1
- src/Client/Commands.hs +7/−0
- src/Client/Configuration.hs +2/−0
- src/Client/ConnectionState.hs +41/−14
- src/Client/Image.hs +4/−0
- src/Client/Image/ChannelInfo.hs +75/−0
- src/Client/Image/Message.hs +89/−49
- src/Client/Image/UserList.hs +11/−3
- src/Client/NetworkConnection.hs +4/−1
- src/Client/ServerSettings.hs +23/−17
- src/Client/State.hs +4/−2
- src/Irc/Codes.hs +854/−1337
- src/Irc/Commands.hs +23/−0
- src/Irc/Message.hs +11/−3
- src/Irc/RateLimit.hs +0/−6
ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for glirc2 +## 2.1++* Add red highlighting for own nick+* Synchronize reply codes with Freenode+* Add textual interpretation of reply codes+* Add SASL support+* Add `/channelinfo` command+ ## 2.0 * First version of glirc rewrite
README.md view
@@ -21,6 +21,7 @@ * Run commands upon connection * Ban lists don't obstruct chat messages * Ban list and user list are searchable+* CERTFP and SASL authentication TLS ===@@ -100,6 +101,8 @@ * `username` - text - username * `realname` - text - realname / GECOS * `password` - text - server password+* `sasl-username` - text - SASL username+* `sasl-password` - text - SASL password * `tls` - yes/no - use TLS to connect * `tls-insecure` - yes/no - disable certificate validation * `tls-client-cert` - text - path to TLS client certificate@@ -109,6 +112,8 @@ * `socks-port` - number - port number of SOCKS proxy to connect through * `server-certificates` - list of text - list of CA certificates to use when validating certificates * `chanserv-channels` - list of text - list of channels with chanserv op permission+* `flood-penalty` - number - cost in seconds per message+* `flood-threshold` - number - threshold of seconds for burst Commands@@ -140,6 +145,7 @@ * `/part` - Part from current channel * `/users` - Show channel user list * `/masks <mode>` - Show channel bans(b), quiets(q), exempts(e), or invex(I)+* `/channelinfo` - Show channel topic, creation, url Filters
glirc.cabal view
@@ -1,5 +1,5 @@ name: glirc-version: 2.0+version: 2.1 synopsis: Console IRC client description: Console IRC client license: ISC@@ -30,6 +30,7 @@ Client.EventLoop Client.IdentifierColors Client.Image+ Client.Image.ChannelInfo Client.Image.MaskList Client.Image.Message Client.Image.UserList@@ -69,6 +70,7 @@ unordered-containers >=0.2.7 && <0.3, hashable >=1.2.4 && <1.3, network >=2.6.2 && <2.7,+ vector >=0.11 && <0.12, tls >=1.3.8 && <1.4, split >=0.2 && <0.3, profunctors >=5.2 && <5.3,@@ -79,6 +81,7 @@ data-default-class >=0.1.2 && <0.2, stm >=2.4 && <2.5, directory >=1.2.6 && <1.3,+ memory >=0.13 && <0.14, filepath >=1.4.1 && <1.5 ghc-options: -threaded -rtsopts
src/Client/ChannelState.hs view
@@ -16,9 +16,10 @@ module Client.ChannelState ( -- * Channel state type- ChannelState+ ChannelState(..) , chanTopic , chanTopicProvenance+ , chanUrl , chanUsers , chanModes , chanLists@@ -56,6 +57,8 @@ -- ^ topic text , _chanTopicProvenance :: !(Maybe TopicProvenance) -- ^ author and timestamp for topic+ , _chanUrl :: !(Maybe Text)+ -- ^ channel URL , _chanUsers :: !(HashMap Identifier String) -- ^ user list and sigils , _chanModes :: !(Map Char Text)@@ -80,6 +83,7 @@ newChannel :: ChannelState newChannel = ChannelState { _chanTopic = Text.empty+ , _chanUrl = Nothing , _chanTopicProvenance = Nothing , _chanUsers = HashMap.empty , _chanModes = Map.empty
src/Client/Commands.hs view
@@ -141,6 +141,7 @@ , ("part" , ChannelCommand cmdPart simpleChannelTab) , ("users" , ChannelCommand cmdUsers noChannelTab)+ , ("channelinfo", ChannelCommand cmdChannelInfo noChannelTab) , ("masks" , ChannelCommand cmdMasks noChannelTab) ] @@ -359,6 +360,12 @@ cmdUsers _ _ _ st _ = commandContinue $ changeSubfocus FocusUsers $ consumeInput st++cmdChannelInfo :: NetworkName -> ConnectionState -> Identifier -> ClientState -> String -> IO CommandResult+cmdChannelInfo _ _ _ st _+ = commandContinue+ $ changeSubfocus FocusInfo+ $ consumeInput st cmdMasks :: NetworkName -> ConnectionState -> Identifier -> ClientState -> String -> IO CommandResult cmdMasks _ cs _ st rest =
src/Client/Configuration.hs view
@@ -133,6 +133,8 @@ _ssSocksPort <- fieldReq' ssSocksPort (sectionOptNum "socks-port") _ssServerCerts <- fieldReq' ssServerCerts (sectionOptStrings "server-certificates") _ssChanservChannels <- fieldReq' ssChanservChannels (sectionOptIdentifiers "chanserv-channels")+ _ssFloodPenalty <- fieldReq' ssFloodPenalty (sectionOptNum "flood-penalty")+ _ssFloodThreshold <- fieldReq' ssFloodThreshold (sectionOptNum "flood-threshold") return ServerSettings{..} where field l key = field' l (sectionOpt key)
src/Client/ConnectionState.hs view
@@ -19,7 +19,7 @@ module Client.ConnectionState ( -- * Connection state type- ConnectionState+ ConnectionState(..) , csNick , csChannels , csSocket@@ -85,7 +85,7 @@ import LensUtils data ConnectionState = ConnectionState- { _csNetworkId :: NetworkId+ { _csNetworkId :: !NetworkId , _csChannels :: !(HashMap Identifier ChannelState) , _csSocket :: !NetworkConnection , _csModeTypes :: !ModeTypes@@ -233,8 +233,11 @@ $ forgetUser' nick $ overChannel chan (partChannel nick) cs Reply RPL_WELCOME (me:_) -> doWelcome msgWhen (mkId me) cs+ Reply RPL_SASLSUCCESS _ -> ([ircCapEnd], cs)+ Reply RPL_SASLFAIL _ -> ([ircCapEnd], cs) Reply code args -> noReply (doRpl code msgWhen args cs) Cap cmd params -> doCap cmd params cs+ Authenticate param -> doAuthenticate param cs Mode who target (modes:params) -> doMode msgWhen who target modes params cs Topic user chan topic -> noReply (doTopic msgWhen user chan topic cs) _ -> noReply cs@@ -271,7 +274,7 @@ Just $! posixSecondsToUTCTime (fromInteger i) _ -> Nothing -doRpl :: Int -> ZonedTime -> [Text] -> ConnectionState -> ConnectionState+doRpl :: ReplyCode -> ZonedTime -> [Text] -> ConnectionState -> ConnectionState doRpl cmd msgWhen args = case cmd of @@ -301,6 +304,12 @@ overChannel (mkId chan) (set chanCreation (Just when)) _ -> id + RPL_CHANNEL_URL ->+ case args of+ _me:chan:urlTxt:_ ->+ overChannel (mkId chan) (set chanUrl (Just urlTxt))+ _ -> id+ RPL_ISUPPORT -> isupport args RPL_NAMREPLY ->@@ -350,7 +359,7 @@ cs _ -> id - RPL_INVITELIST ->+ RPL_INVEXLIST -> case args of _me:_tgt:mask:who:whenTxt:_ | Just when <- parseTimeParam whenTxt -> over csTransaction $ \t ->@@ -358,7 +367,7 @@ in BanTransaction ((mask,(who,when)):xs) _ -> id - RPL_ENDOFINVITELIST ->+ RPL_ENDOFINVEXLIST -> case args of _me:tgt:_ -> \cs -> set csTransaction NoTransaction@@ -408,15 +417,15 @@ -- | These replies are interpreted by the client and should only be shown -- in the detailed view. Any reply interpreted by 'doRpl' should be -- listed here.-squelchReply :: Int -> Bool+squelchReply :: ReplyCode -> Bool squelchReply rpl = case rpl of RPL_NAMREPLY -> True RPL_ENDOFNAMES -> True RPL_BANLIST -> True RPL_ENDOFBANLIST -> True- RPL_INVITELIST -> True- RPL_ENDOFINVITELIST -> True+ RPL_INVEXLIST -> True+ RPL_ENDOFINVEXLIST -> True RPL_EXCEPTLIST -> True RPL_ENDOFEXCEPTLIST -> True RPL_QUIETLIST -> True@@ -425,6 +434,7 @@ RPL_TOPIC -> True RPL_TOPICWHOTIME -> True RPL_CREATIONTIME -> True+ RPL_CHANNEL_URL -> True RPL_NOTOPIC -> True RPL_WHOREPLY -> True RPL_ENDOFWHO -> True@@ -512,9 +522,23 @@ | otherwise = mode:modes applyOne modes (False, mode, _) = delete mode modes -supportedCaps :: [Text]-supportedCaps = ["multi-prefix", "znc.in/server-time-iso"]+supportedCaps :: ConnectionState -> [Text]+supportedCaps cs = sasl ++ ["multi-prefix", "znc.in/server-time-iso"]+ where+ ss = view csSettings cs+ sasl = ["sasl" | has ssSaslUsername ss+ , has ssSaslPassword ss ] +doAuthenticate :: Text -> ConnectionState -> ([RawIrcMsg], ConnectionState)+doAuthenticate "+" cs+ | Just user <- view ssSaslUsername ss+ , Just pass <- view ssSaslPassword ss+ = ([ircAuthenticate (encodePlainAuthentication user pass)], cs)+ where+ ss = view csSettings cs++doAuthenticate _ cs = ([ircCapEnd], cs)+ doCap :: CapCmd -> [Text] -> ConnectionState -> ([RawIrcMsg], ConnectionState) doCap cmd args cs = case (cmd,args) of@@ -523,12 +547,15 @@ | otherwise -> ([ircCapReq reqCaps], cs) where caps = Text.words capsTxt- reqCaps = intersect supportedCaps caps+ reqCaps = intersect (supportedCaps cs) caps - (CapAck,_) -> ([ircCapEnd], cs)- (CapNak,_) -> ([ircCapEnd], cs)+ (CapAck,[capsTxt])+ | "sasl" `elem` caps ->+ ([ircAuthenticate plainAuthenticationMode], cs)+ where+ caps = Text.words capsTxt - _ -> noReply cs+ _ -> ([ircCapEnd], cs) initialMessages :: ConnectionState -> [RawIrcMsg]
src/Client/Image.hs view
@@ -14,6 +14,7 @@ import Client.ChannelState import Client.ConnectionState import qualified Client.EditBox as Edit+import Client.Image.ChannelInfo import Client.Image.MaskList import Client.Image.Message import Client.Image.UserList@@ -56,6 +57,8 @@ messagePaneImages :: ClientState -> [Image] messagePaneImages !st = case (view clientFocus st, view clientSubfocus st) of+ (ChannelFocus network channel, FocusInfo) ->+ channelInfoImages network channel st (ChannelFocus network channel, FocusUsers) | view clientDetailView st -> userInfoImages network channel st | otherwise -> userListImages network channel st@@ -223,6 +226,7 @@ subfocusName = case view clientSubfocus st of FocusMessages -> Nothing+ FocusInfo -> Just $ string (withForeColor defAttr green) "info" FocusUsers -> Just $ string (withForeColor defAttr green) "users" FocusMasks m -> Just $ horizCat [ string (withForeColor defAttr green) "masks"
+ src/Client/Image/ChannelInfo.hs view
@@ -0,0 +1,75 @@+{-# Language OverloadedStrings #-}+{-# Language BangPatterns #-}++{-|+Module : Client.Image.ChannelInfo+Description : Channel information renderer+Copyright : (c) Eric Mertens, 2016+License : ISC+Maintainer : emertens@gmail.com++This module implements a renderer for the window that shows+channel metadata.++-}+module Client.Image.ChannelInfo+ ( channelInfoImages+ ) where++import Client.ChannelState+import Client.ConnectionState+import Client.Image.Message+import Client.MircFormatting+import Client.State+import Control.Lens+import qualified Data.HashMap.Strict as HashMap+import Data.List+import Data.Ord+import Data.Time+import Graphics.Vty.Image+import Irc.Identifier++-- | Render the lines used in a channel mask list+channelInfoImages :: NetworkName -> Identifier -> ClientState -> [Image]+channelInfoImages network channelId st++ | Just cs <- preview (clientConnection network) st+ , Just channel <- preview (csChannels . ix channelId) cs+ = channelInfoImages' channel cs++ | otherwise = [text' (withForeColor defAttr red) "No channel information"]++channelInfoImages' :: ChannelState -> ConnectionState -> [Image]+channelInfoImages' !channel !cs+ = topicLine+ : provenanceLines+ ++ creationLines+ ++ urlLines++ where+ label = text' (withForeColor defAttr green)++ topicLine = label "Topic: " <|> parseIrcText (view chanTopic channel)++ myNick = view csNick cs++ utcTimeImage = string defAttr . formatTime defaultTimeLocale "%F %T"++ provenanceLines =+ case view chanTopicProvenance channel of+ Nothing -> []+ Just !prov ->+ [ label "Topic set by: " <|> coloredUserInfo DetailedRender [myNick] (view topicAuthor prov)+ , label "Topic set on: " <|> utcTimeImage (view topicTime prov)+ ]++ creationLines =+ case view chanCreation channel of+ Nothing -> []+ Just time -> [label "Created on: " <|> utcTimeImage time]++ urlLines =+ case view chanUrl channel of+ Nothing -> []+ Just url -> [ label "Channel URL: " <|> parseIrcText url ]+
src/Client/Image/Message.hs view
@@ -27,6 +27,7 @@ import Control.Lens import Data.Time import Graphics.Vty.Image+import Irc.Codes import Irc.Identifier import Irc.Message import Irc.RawIrcMsg@@ -42,6 +43,7 @@ { rendStatusMsg :: [Char] -- ^ restricted message sigils , rendUserSigils :: [Char] -- ^ sender sigils , rendNicks :: [Identifier] -- ^ nicknames to highlight+ , rendMyNicks :: [Identifier] -- ^ nicknames to highlight in red } -- | Default 'MessageRenderParams' with no sigils or nicknames specified@@ -50,6 +52,7 @@ { rendStatusMsg = "" , rendUserSigils = "" , rendNicks = []+ , rendMyNicks = [] } -- | Construct a message given the time the message was received and its@@ -60,7 +63,7 @@ msgImage when params body = horizCat [ timeImage when , statusMsgImage (rendStatusMsg params)- , bodyImage NormalRender (rendUserSigils params) (rendNicks params) body+ , bodyImage NormalRender (rendUserSigils params) (rendMyNicks params) (rendNicks params) body ] -- | Construct a message given the time the message was received and its@@ -69,7 +72,7 @@ detailedMsgImage when params body = horizCat [ datetimeImage when , statusMsgImage (rendStatusMsg params)- , bodyImage DetailedRender (rendUserSigils params) (rendNicks params) body+ , bodyImage DetailedRender (rendUserSigils params) (rendMyNicks params) (rendNicks params) body ] -- | Render the sigils for a restricted message.@@ -87,11 +90,12 @@ bodyImage :: RenderMode -> [Char] {- ^ sigils -} ->+ [Identifier] {- ^ my nicknames -} -> [Identifier] {- ^ nicknames to highlight -} -> MessageBody -> Image-bodyImage rm modes nicks body =+bodyImage rm modes myNicks nicks body = case body of- IrcBody irc -> ircLineImage rm modes nicks irc+ IrcBody irc -> ircLineImage rm modes myNicks nicks irc ErrorBody ex -> string defAttr ("Exception: " ++ show ex) ExitBody -> string defAttr "Thread finished" @@ -129,9 +133,10 @@ ircLineImage :: RenderMode -> [Char] {- ^ sigils (e.g. \@+) -} ->+ [Identifier] {- ^ my nicknames to highlight -} -> [Identifier] {- ^ nicknames to highlight -} -> IrcMsg -> Image-ircLineImage rm sigils nicks body =+ircLineImage rm sigils myNicks nicks body = let detail img = case rm of NormalRender -> emptyImage@@ -141,24 +146,24 @@ Nick old new -> detail (string quietAttr "nick ") <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm old <|>+ coloredUserInfo rm myNicks old <|> string defAttr " became " <|>- coloredIdentifier new+ coloredIdentifier myNicks new Join nick _chan -> string quietAttr "join " <|>- coloredUserInfo rm nick+ coloredUserInfo rm myNicks nick Part nick _chan mbreason -> string quietAttr "part " <|>- coloredUserInfo rm nick <|>+ coloredUserInfo rm myNicks nick <|> foldMap (\reason -> string quietAttr " (" <|> parseIrcText reason <|> string quietAttr ")") mbreason Quit nick mbreason -> string quietAttr "quit " <|>- coloredUserInfo rm nick <|>+ coloredUserInfo rm myNicks nick <|> foldMap (\reason -> string quietAttr " (" <|> parseIrcText reason <|> string quietAttr ")") mbreason@@ -166,90 +171,119 @@ Kick kicker _channel kickee reason -> detail (string quietAttr "kick ") <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm kicker <|>+ coloredUserInfo rm myNicks kicker <|> string defAttr " kicked " <|>- coloredIdentifier kickee <|>+ coloredIdentifier myNicks kickee <|> string defAttr ": " <|> parseIrcText reason Topic src _dst txt ->- coloredUserInfo rm src <|>+ coloredUserInfo rm myNicks src <|> string defAttr " changed topic to " <|> parseIrcText txt Notice src _dst txt -> detail (string quietAttr "note ") <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm src <|>+ coloredUserInfo rm myNicks src <|> string (withForeColor defAttr red) ": " <|>- parseIrcTextWithNicks nicks txt+ parseIrcTextWithNicks myNicks nicks txt Privmsg src _dst txt -> detail (string quietAttr "chat ") <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm src <|>+ coloredUserInfo rm myNicks src <|> string defAttr ": " <|>- parseIrcTextWithNicks nicks txt+ parseIrcTextWithNicks myNicks nicks txt Action src _dst txt -> detail (string quietAttr "chat ") <|> string (withForeColor defAttr blue) "* " <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm src <|>+ coloredUserInfo rm myNicks src <|> string defAttr " " <|>- parseIrcTextWithNicks nicks txt+ parseIrcTextWithNicks myNicks nicks txt Ping params ->- string defAttr "PING" <|>- horizCat [char (withForeColor defAttr blue) '·' <|>- parseIrcText p | p <- params]+ string defAttr "PING " <|> separatedParams params Pong params ->- string defAttr "PONG" <|>- horizCat [char (withForeColor defAttr blue) '·' <|>- parseIrcText p | p <- params]+ string defAttr "PONG " <|> separatedParams params Error reason -> string (withForeColor defAttr red) "ERROR " <|> parseIrcText reason Reply code params ->- string defAttr (show code) <|>- horizCat [char (withForeColor defAttr blue) '·' <|>- parseIrcText p | p <- params]+ renderReplyCode rm code <|>+ char defAttr ' ' <|>+ separatedParams (dropFst params)+ where+ dropFst = case rm of+ DetailedRender -> id+ NormalRender -> drop 1 UnknownMsg irc ->- maybe emptyImage (\ui -> coloredUserInfo rm ui <|> char defAttr ' ')+ maybe emptyImage (\ui -> coloredUserInfo rm myNicks ui <|> char defAttr ' ') (view msgPrefix irc) <|> text' defAttr (view msgCommand irc) <|>- horizCat [char (withForeColor defAttr blue) '·' <|>- parseIrcText p | p <- view msgParams irc]+ char defAttr ' ' <|>+ separatedParams (view msgParams irc) Cap cmd args -> string defAttr (show cmd) <|>- horizCat [char (withForeColor defAttr blue) '·' <|>- text' defAttr a | a <- args]+ char defAttr ' ' <|>+ separatedParams args + Authenticate{} -> string defAttr "AUTHENTICATE ***"+ Mode nick _chan params -> detail (string quietAttr "mode ") <|> string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo rm nick <|>+ coloredUserInfo rm myNicks nick <|> string defAttr " set mode: " <|>- horizCat (intersperse (char (withForeColor defAttr blue) '·')- (text' defAttr <$> params))+ separatedParams params +separatorImage :: Image+separatorImage = char (withForeColor defAttr blue) '·'++separatedParams :: [Text] -> Image+separatedParams = horizCat . intersperse separatorImage . map parseIrcText++renderReplyCode :: RenderMode -> ReplyCode -> Image+renderReplyCode rm code@(ReplyCode w) =+ case rm of+ DetailedRender -> string attr (show w)+ NormalRender -> text' attr (Text.toLower (replyCodeText info)) <|>+ char defAttr ':'+ where+ info = replyCodeInfo code++ color = case replyCodeType info of+ ClientServerReply -> magenta+ CommandReply -> green+ ErrorReply -> red+ UnknownReply -> yellow++ attr = withForeColor defAttr color++ -- | Render a nickname in its hash-based color.-coloredIdentifier :: Identifier -> Image-coloredIdentifier ident =- text' (withForeColor defAttr (identifierColor ident)) (idText ident)+coloredIdentifier :: [Identifier] {- ^ my nicknames -} -> Identifier -> Image+coloredIdentifier myNicks ident =+ text' (withForeColor defAttr color) (idText ident)+ where+ color+ | ident `elem` myNicks = red+ | otherwise = identifierColor ident -- | Render an a full user. In normal mode only the nickname will be rendered. -- If detailed mode the full user info including the username and hostname parts -- will be rendered. The nickname will be colored.-coloredUserInfo :: RenderMode -> UserInfo -> Image-coloredUserInfo NormalRender ui = coloredIdentifier (userNick ui)-coloredUserInfo DetailedRender ui = horizCat- [ coloredIdentifier (userNick ui)+coloredUserInfo :: RenderMode -> [Identifier] -> UserInfo -> Image+coloredUserInfo NormalRender myNicks ui = coloredIdentifier myNicks (userNick ui)+coloredUserInfo DetailedRender myNicks ui = horizCat+ [ coloredIdentifier myNicks (userNick ui) , foldMap (\user -> char defAttr '!' <|> text' quietAttr user) (userName ui) , foldMap (\host -> char defAttr '@' <|> text' quietAttr host) (userHost ui) ]@@ -263,20 +297,26 @@ -- control characters in it then the text will be rendered according to -- the formatting codes. Otherwise the nicknames in the message are -- highlighted.-parseIrcTextWithNicks :: [Identifier] -> Text -> Image-parseIrcTextWithNicks nicks txt+parseIrcTextWithNicks ::+ [Identifier] {- ^ my nicks -} ->+ [Identifier] {- ^ other nicks -} ->+ Text -> Image+parseIrcTextWithNicks myNicks nicks txt | Text.any isControl txt = parseIrcText txt- | otherwise = highlightNicks nicks txt+ | otherwise = highlightNicks myNicks nicks txt -- | Given a list of nicknames and a chat message, this will generate -- an image where all of the occurrences of those nicknames are colored.-highlightNicks :: [Identifier] -> Text -> Image-highlightNicks nicks txt = horizCat (highlight1 <$> txtParts)+highlightNicks ::+ [Identifier] {- ^ my nicks -} ->+ [Identifier] {- ^ other nicks -} ->+ Text -> Image+highlightNicks myNicks nicks txt = horizCat (highlight1 <$> txtParts) where nickSet = HashSet.fromList nicks txtParts = nickSplit txt highlight1 part- | HashSet.member partId nickSet = coloredIdentifier partId+ | HashSet.member partId nickSet = coloredIdentifier myNicks partId | otherwise = text' defAttr part where partId = mkId part
src/Client/Image/UserList.hs view
@@ -1,3 +1,4 @@+{-# Language OverloadedStrings #-} {-| Module : Client.Image.UserList Description : Line renderers for channel user list view@@ -28,13 +29,18 @@ Identifier {- ^ Focused channel name -} -> ClientState -> [Image] userListImages network channel st =- [horizCat (intersperse gap (map renderUser usersList))]+ [countImage, horizCat (intersperse gap (map renderUser usersList))] where+ countImage = text' (withForeColor defAttr green) "Users: " <|>+ string defAttr (show (HashMap.size usersHashMap))+ matcher = clientMatcher st + myNicks = toListOf (clientConnection network . csNick) st+ renderUser (ident, sigils) = string (withForeColor defAttr cyan) sigils <|>- coloredIdentifier ident+ coloredIdentifier myNicks ident gap = char defAttr ' ' @@ -58,9 +64,11 @@ where matcher = clientMatcher st + myNicks = toListOf (clientConnection network . csNick) st+ renderEntry (info, sigils) = string (withForeColor defAttr cyan) sigils <|>- coloredUserInfo DetailedRender info+ coloredUserInfo DetailedRender myNicks info matcher' (info,sigils) = matcher (Text.pack sigils `Text.append` renderUserInfo info)
src/Client/NetworkConnection.hs view
@@ -35,6 +35,7 @@ import Control.Concurrent.STM import Control.Concurrent.Async import Control.Exception+import Control.Lens import Control.Monad import Data.ByteString (ByteString) import qualified Data.ByteString as B@@ -126,7 +127,9 @@ TQueue ByteString -> IO () startConnection network cxt settings onInput outQueue =- do rate <- newRateLimitDefault+ do rate <- newRateLimit+ (view ssFloodPenalty settings)+ (view ssFloodThreshold settings) withConnection cxt settings $ \h -> withAsync (sendLoop h outQueue rate) $ \sender -> withAsync (receiveLoop network h onInput) $ \receiver ->
src/Client/ServerSettings.hs view
@@ -34,6 +34,8 @@ , ssSocksPort , ssServerCerts , ssChanservChannels+ , ssFloodPenalty+ , ssFloodThreshold -- * Load function , loadDefaultServerSettings@@ -50,24 +52,26 @@ import Network.Socket (HostName, PortNumber) data ServerSettings = ServerSettings- { _ssNick :: !Text -- ^ connection nickname- , _ssUser :: !Text -- ^ connection username- , _ssReal :: !Text -- ^ connection realname / GECOS- , _ssUserInfo :: !Text -- ^ CTCP userinfo- , _ssPassword :: !(Maybe Text) -- ^ server password- , _ssSaslUsername :: !(Maybe Text) -- ^ SASL username- , _ssSaslPassword :: !(Maybe Text) -- ^ SASL password- , _ssHostName :: !HostName -- ^ server hostname- , _ssPort :: !(Maybe PortNumber) -- ^ server port- , _ssTls :: !Bool -- ^ use TLS to connect- , _ssTlsInsecure :: !Bool -- ^ disable certificate checking- , _ssTlsClientCert :: !(Maybe FilePath) -- ^ path to client TLS certificate- , _ssTlsClientKey :: !(Maybe FilePath) -- ^ path to client TLS key- , _ssConnectCmds :: ![Text] -- ^ raw IRC messages to transmit upon successful connection- , _ssSocksHost :: !(Maybe HostName) -- ^ hostname of SOCKS proxy- , _ssSocksPort :: !PortNumber -- ^ port of SOCKS proxy- , _ssServerCerts :: ![FilePath] -- ^ additional CA certificates for validating server+ { _ssNick :: !Text -- ^ connection nickname+ , _ssUser :: !Text -- ^ connection username+ , _ssReal :: !Text -- ^ connection realname / GECOS+ , _ssUserInfo :: !Text -- ^ CTCP userinfo+ , _ssPassword :: !(Maybe Text) -- ^ server password+ , _ssSaslUsername :: !(Maybe Text) -- ^ SASL username+ , _ssSaslPassword :: !(Maybe Text) -- ^ SASL password+ , _ssHostName :: !HostName -- ^ server hostname+ , _ssPort :: !(Maybe PortNumber) -- ^ server port+ , _ssTls :: !Bool -- ^ use TLS to connect+ , _ssTlsInsecure :: !Bool -- ^ disable certificate checking+ , _ssTlsClientCert :: !(Maybe FilePath) -- ^ path to client TLS certificate+ , _ssTlsClientKey :: !(Maybe FilePath) -- ^ path to client TLS key+ , _ssConnectCmds :: ![Text] -- ^ raw IRC messages to transmit upon successful connection+ , _ssSocksHost :: !(Maybe HostName) -- ^ hostname of SOCKS proxy+ , _ssSocksPort :: !PortNumber -- ^ port of SOCKS proxy+ , _ssServerCerts :: ![FilePath] -- ^ additional CA certificates for validating server , _ssChanservChannels :: ![Identifier] -- ^ Channels with chanserv permissions+ , _ssFloodPenalty :: !Int -- ^ Flood limiter penalty (seconds)+ , _ssFloodThreshold :: !Int -- ^ Flood limited threshold (seconds) } deriving Show @@ -100,4 +104,6 @@ , _ssSocksPort = 1080 , _ssServerCerts = [] , _ssChanservChannels = []+ , _ssFloodPenalty = 2 -- RFC 1459 defaults+ , _ssFloodThreshold = 10 }
src/Client/State.hs view
@@ -83,7 +83,6 @@ import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.ICU as ICU-import Data.Time import Graphics.Vty import Irc.Identifier import Irc.Message@@ -106,6 +105,7 @@ data ClientSubfocus = FocusMessages+ | FocusInfo | FocusUsers | FocusMasks !Char deriving Eq@@ -201,10 +201,12 @@ where focus = ChannelFocus network channel' wl = toWindowLine rendParams msg+ myNicks = toListOf (clientConnection network . csNick) st rendParams = MessageRendererParams { rendStatusMsg = statusModes , rendUserSigils = computeMsgLineModes network channel' msg st , rendNicks = channelUserList network channel' st+ , rendMyNicks = myNicks } -- on failure returns mempty/""@@ -242,7 +244,7 @@ | otherwise -> WLNormal Error{} -> WLImportant Reply cmd _ ->- case replyType cmd of+ case replyCodeType (replyCodeInfo cmd) of ErrorReply -> WLImportant _ -> WLNormal _ -> WLBoring
src/Irc/Codes.hs view
@@ -1,1337 +1,854 @@-{-# Language PatternSynonyms #-}--{-|-Module : Irc.Codes-Description : Helpers for interpreting IRC reply codes-Copyright : (c) Eric Mertens, 2016-License : ISC-Maintainer : emertens@gmail.com--This module defines support for working with IRC's numeric reply-codes. Pattern synonyms are provided for each of the possible IRC reply codes.--Reply code information was extracted from https://www.alien.net.au/irc/irc2numerics.html---}--module Irc.Codes where---- | Categories for reply codes-data ReplyType- = ClientServerReply -- ^ 0-99 Messages between client and server- | CommandReply -- ^ 200-399 Responses to commands- | ErrorReply -- ^ 200-399 Errors- | CustomReply -- ^ Uncategorized---- | Categorize replies according to the ranges provided in RFC 2812-replyType :: Int {- reply code -} -> ReplyType-replyType x- | 000 <= x, x < 100 = ClientServerReply- | 200 <= x, x < 400 = CommandReply- | 400 <= x, x < 600 = ErrorReply- | otherwise = CustomReply--pattern RPL_WELCOME :: Int-pattern RPL_WELCOME = 001--pattern RPL_YOURHOST :: Int-pattern RPL_YOURHOST = 002--pattern RPL_CREATED :: Int-pattern RPL_CREATED = 003--pattern RPL_MYINFO :: Int-pattern RPL_MYINFO = 004--pattern RPL_ISUPPORT :: Int-pattern RPL_ISUPPORT = 005--pattern RPL_SNOMASK :: Int-pattern RPL_SNOMASK = 008--pattern RPL_STATMEMTOT :: Int-pattern RPL_STATMEMTOT = 009--pattern RPL_BOUNCE :: Int-pattern RPL_BOUNCE = 010--pattern RPL_STATMEM :: Int-pattern RPL_STATMEM = 010--pattern RPL_YOURCOOKIE :: Int-pattern RPL_YOURCOOKIE = 014--pattern RPL_YOURID :: Int-pattern RPL_YOURID = 042--pattern RPL_SAVENICK :: Int-pattern RPL_SAVENICK = 043--pattern RPL_ATTEMPTINGJUNC :: Int-pattern RPL_ATTEMPTINGJUNC = 050--pattern RPL_ATTEMPTINGREROUTE :: Int-pattern RPL_ATTEMPTINGREROUTE = 051--pattern RPL_TRACELINK :: Int-pattern RPL_TRACELINK = 200--pattern RPL_TRACECONNECTING :: Int-pattern RPL_TRACECONNECTING = 201--pattern RPL_TRACEHANDSHAKE :: Int-pattern RPL_TRACEHANDSHAKE = 202--pattern RPL_TRACEUNKNOWN :: Int-pattern RPL_TRACEUNKNOWN = 203--pattern RPL_TRACEOPERATOR :: Int-pattern RPL_TRACEOPERATOR = 204--pattern RPL_TRACEUSER :: Int-pattern RPL_TRACEUSER = 205--pattern RPL_TRACESERVER :: Int-pattern RPL_TRACESERVER = 206--pattern RPL_TRACESERVICE :: Int-pattern RPL_TRACESERVICE = 207--pattern RPL_TRACENEWTYPE :: Int-pattern RPL_TRACENEWTYPE = 208--pattern RPL_TRACECLASS :: Int-pattern RPL_TRACECLASS = 209--pattern RPL_TRACERECONNECT :: Int-pattern RPL_TRACERECONNECT = 210--pattern RPL_STATS :: Int-pattern RPL_STATS = 210--pattern RPL_STATSLINKINFO :: Int-pattern RPL_STATSLINKINFO = 211--pattern RPL_STATSCOMMANDS :: Int-pattern RPL_STATSCOMMANDS = 212--pattern RPL_STATSCLINE :: Int-pattern RPL_STATSCLINE = 213--pattern RPL_STATSILINE :: Int-pattern RPL_STATSILINE = 215--pattern RPL_STATSKLINE :: Int-pattern RPL_STATSKLINE = 216--pattern RPL_STATSYLINE :: Int-pattern RPL_STATSYLINE = 218--pattern RPL_ENDOFSTATS :: Int-pattern RPL_ENDOFSTATS = 219--pattern RPL_UMODEIS :: Int-pattern RPL_UMODEIS = 221--pattern RPL_SQLINE_NICK :: Int-pattern RPL_SQLINE_NICK = 222--pattern RPL_STATSDLINE :: Int-pattern RPL_STATSDLINE = 225--pattern RPL_STATSZLINE :: Int-pattern RPL_STATSZLINE = 225--pattern RPL_STATSCOUNT :: Int-pattern RPL_STATSCOUNT = 226--pattern RPL_SERVICEINFO :: Int-pattern RPL_SERVICEINFO = 231--pattern RPL_ENDOFSERVICES :: Int-pattern RPL_ENDOFSERVICES = 232--pattern RPL_SERVICE :: Int-pattern RPL_SERVICE = 233--pattern RPL_SERVLIST :: Int-pattern RPL_SERVLIST = 234--pattern RPL_SERVLISTEND :: Int-pattern RPL_SERVLISTEND = 235--pattern RPL_STATSVERBOSE :: Int-pattern RPL_STATSVERBOSE = 236--pattern RPL_STATSIAUTH :: Int-pattern RPL_STATSIAUTH = 239--pattern RPL_STATSLLINE :: Int-pattern RPL_STATSLLINE = 241--pattern RPL_STATSUPTIME :: Int-pattern RPL_STATSUPTIME = 242--pattern RPL_STATSOLINE :: Int-pattern RPL_STATSOLINE = 243--pattern RPL_STATSHLINE :: Int-pattern RPL_STATSHLINE = 244--pattern RPL_STATSSLINE :: Int-pattern RPL_STATSSLINE = 245--pattern RPL_STATSPING :: Int-pattern RPL_STATSPING = 246--pattern RPL_STATSDEFINE :: Int-pattern RPL_STATSDEFINE = 248--pattern RPL_STATSDEBUG :: Int-pattern RPL_STATSDEBUG = 249--pattern RPL_STATSCONN :: Int-pattern RPL_STATSCONN = 250--pattern RPL_LUSERCLIENT :: Int-pattern RPL_LUSERCLIENT = 251--pattern RPL_LUSEROP :: Int-pattern RPL_LUSEROP = 252--pattern RPL_LUSERUNKNOWN :: Int-pattern RPL_LUSERUNKNOWN = 253--pattern RPL_LUSERCHANNELS :: Int-pattern RPL_LUSERCHANNELS = 254--pattern RPL_LUSERME :: Int-pattern RPL_LUSERME = 255--pattern RPL_ADMINME :: Int-pattern RPL_ADMINME = 256--pattern RPL_ADMINLOC1 :: Int-pattern RPL_ADMINLOC1 = 257--pattern RPL_ADMINLOC2 :: Int-pattern RPL_ADMINLOC2 = 258--pattern RPL_ADMINEMAIL :: Int-pattern RPL_ADMINEMAIL = 259--pattern RPL_TRACELOG :: Int-pattern RPL_TRACELOG = 261--pattern RPL_TRACEPING :: Int-pattern RPL_TRACEPING = 262--pattern RPL_TRACEEND :: Int-pattern RPL_TRACEEND = 262--pattern RPL_TRYAGAIN :: Int-pattern RPL_TRYAGAIN = 263--pattern RPL_LOCALUSERS :: Int-pattern RPL_LOCALUSERS = 265--pattern RPL_GLOBALUSERS :: Int-pattern RPL_GLOBALUSERS = 266--pattern RPL_START_NETSTAT :: Int-pattern RPL_START_NETSTAT = 267--pattern RPL_NETSTAT :: Int-pattern RPL_NETSTAT = 268--pattern RPL_END_NETSTAT :: Int-pattern RPL_END_NETSTAT = 269--pattern RPL_PRIVS :: Int-pattern RPL_PRIVS = 270--pattern RPL_SILELIST :: Int-pattern RPL_SILELIST = 271--pattern RPL_ENDOFSILELIST :: Int-pattern RPL_ENDOFSILELIST = 272--pattern RPL_NOTIFY :: Int-pattern RPL_NOTIFY = 273--pattern RPL_ENDNOTIFY :: Int-pattern RPL_ENDNOTIFY = 274--pattern RPL_STATSDELTA :: Int-pattern RPL_STATSDELTA = 274--pattern RPL_VCHANEXIST :: Int-pattern RPL_VCHANEXIST = 276--pattern RPL_VCHANLIST :: Int-pattern RPL_VCHANLIST = 277--pattern RPL_VCHANHELP :: Int-pattern RPL_VCHANHELP = 278--pattern RPL_GLIST :: Int-pattern RPL_GLIST = 280--pattern RPL_ENDOFGLIST :: Int-pattern RPL_ENDOFGLIST = 281--pattern RPL_ACCEPTLIST :: Int-pattern RPL_ACCEPTLIST = 281--pattern RPL_ENDOFACCEPT :: Int-pattern RPL_ENDOFACCEPT = 282--pattern RPL_JUPELIST :: Int-pattern RPL_JUPELIST = 282--pattern RPL_ENDOFJUPELIST :: Int-pattern RPL_ENDOFJUPELIST = 283--pattern RPL_FEATURE :: Int-pattern RPL_FEATURE = 284--pattern RPL_GLIST_HASH :: Int-pattern RPL_GLIST_HASH = 285--pattern RPL_CHANINFO_HANDLE :: Int-pattern RPL_CHANINFO_HANDLE = 285--pattern RPL_NEWHOSTIS :: Int-pattern RPL_NEWHOSTIS = 285--pattern RPL_CHANINFO_USERS :: Int-pattern RPL_CHANINFO_USERS = 286--pattern RPL_CHKHEAD :: Int-pattern RPL_CHKHEAD = 286--pattern RPL_CHANINFO_CHOPS :: Int-pattern RPL_CHANINFO_CHOPS = 287--pattern RPL_CHANUSER :: Int-pattern RPL_CHANUSER = 287--pattern RPL_CHANINFO_VOICES :: Int-pattern RPL_CHANINFO_VOICES = 288--pattern RPL_PATCHHEAD :: Int-pattern RPL_PATCHHEAD = 288--pattern RPL_CHANINFO_AWAY :: Int-pattern RPL_CHANINFO_AWAY = 289--pattern RPL_PATCHCON :: Int-pattern RPL_PATCHCON = 289--pattern RPL_CHANINFO_OPERS :: Int-pattern RPL_CHANINFO_OPERS = 290--pattern RPL_HELPHDR :: Int-pattern RPL_HELPHDR = 290--pattern RPL_DATASTR :: Int-pattern RPL_DATASTR = 290--pattern RPL_CHANINFO_BANNED :: Int-pattern RPL_CHANINFO_BANNED = 291--pattern RPL_HELPOP :: Int-pattern RPL_HELPOP = 291--pattern RPL_ENDOFCHECK :: Int-pattern RPL_ENDOFCHECK = 291--pattern RPL_CHANINFO_BANS :: Int-pattern RPL_CHANINFO_BANS = 292--pattern RPL_HELPTLR :: Int-pattern RPL_HELPTLR = 292--pattern RPL_CHANINFO_INVITE :: Int-pattern RPL_CHANINFO_INVITE = 293--pattern RPL_HELPHLP :: Int-pattern RPL_HELPHLP = 293--pattern RPL_CHANINFO_INVITES :: Int-pattern RPL_CHANINFO_INVITES = 294--pattern RPL_HELPFWD :: Int-pattern RPL_HELPFWD = 294--pattern RPL_CHANINFO_KICK :: Int-pattern RPL_CHANINFO_KICK = 295--pattern RPL_HELPIGN :: Int-pattern RPL_HELPIGN = 295--pattern RPL_CHANINFO_KICKS :: Int-pattern RPL_CHANINFO_KICKS = 296--pattern RPL_END_CHANINFO :: Int-pattern RPL_END_CHANINFO = 299--pattern RPL_NONE :: Int-pattern RPL_NONE = 300--pattern RPL_AWAY :: Int-pattern RPL_AWAY = 301--pattern RPL_USERHOST :: Int-pattern RPL_USERHOST = 302--pattern RPL_ISON :: Int-pattern RPL_ISON = 303--pattern RPL_TEXT :: Int-pattern RPL_TEXT = 304--pattern RPL_UNAWAY :: Int-pattern RPL_UNAWAY = 305--pattern RPL_NOWAWAY :: Int-pattern RPL_NOWAWAY = 306--pattern RPL_WHOISREGNICK :: Int-pattern RPL_WHOISREGNICK = 307--pattern RPL_SUSERHOST :: Int-pattern RPL_SUSERHOST = 307--pattern RPL_NOTIFYACTION :: Int-pattern RPL_NOTIFYACTION = 308--pattern RPL_WHOISADMIN :: Int-pattern RPL_WHOISADMIN = 308--pattern RPL_NICKTRACE :: Int-pattern RPL_NICKTRACE = 309--pattern RPL_WHOISSADMIN :: Int-pattern RPL_WHOISSADMIN = 309--pattern RPL_WHOISHELPER :: Int-pattern RPL_WHOISHELPER = 309--pattern RPL_WHOISSVCMSG :: Int-pattern RPL_WHOISSVCMSG = 310--pattern RPL_WHOISHELPOP :: Int-pattern RPL_WHOISHELPOP = 310--pattern RPL_WHOISSERVICE :: Int-pattern RPL_WHOISSERVICE = 310--pattern RPL_WHOISUSER :: Int-pattern RPL_WHOISUSER = 311--pattern RPL_WHOISSERVER :: Int-pattern RPL_WHOISSERVER = 312--pattern RPL_WHOISOPERATOR :: Int-pattern RPL_WHOISOPERATOR = 313--pattern RPL_WHOWASUSER :: Int-pattern RPL_WHOWASUSER = 314--pattern RPL_ENDOFWHO :: Int-pattern RPL_ENDOFWHO = 315--pattern RPL_WHOISCHANOP :: Int-pattern RPL_WHOISCHANOP = 316--pattern RPL_WHOISIDLE :: Int-pattern RPL_WHOISIDLE = 317--pattern RPL_ENDOFWHOIS :: Int-pattern RPL_ENDOFWHOIS = 318--pattern RPL_WHOISCHANNELS :: Int-pattern RPL_WHOISCHANNELS = 319--pattern RPL_WHOISVIRT :: Int-pattern RPL_WHOISVIRT = 320--pattern RPL_WHOIS_HIDDEN :: Int-pattern RPL_WHOIS_HIDDEN = 320--pattern RPL_WHOISSPECIAL :: Int-pattern RPL_WHOISSPECIAL = 320--pattern RPL_LISTSTART :: Int-pattern RPL_LISTSTART = 321--pattern RPL_LIST :: Int-pattern RPL_LIST = 322--pattern RPL_LISTEND :: Int-pattern RPL_LISTEND = 323--pattern RPL_CHANNELMODEIS :: Int-pattern RPL_CHANNELMODEIS = 324--pattern RPL_UNIQOPIS :: Int-pattern RPL_UNIQOPIS = 325--pattern RPL_CHANNELPASSIS :: Int-pattern RPL_CHANNELPASSIS = 325--pattern RPL_NOCHANPASS :: Int-pattern RPL_NOCHANPASS = 326--pattern RPL_CHPASSUNKNOWN :: Int-pattern RPL_CHPASSUNKNOWN = 327--pattern RPL_CHANNEL_URL :: Int-pattern RPL_CHANNEL_URL = 328--pattern RPL_CREATIONTIME :: Int-pattern RPL_CREATIONTIME = 329--pattern RPL_WHOWAS_TIME :: Int-pattern RPL_WHOWAS_TIME = 330--pattern RPL_WHOISACCOUNT :: Int-pattern RPL_WHOISACCOUNT = 330--pattern RPL_NOTOPIC :: Int-pattern RPL_NOTOPIC = 331--pattern RPL_TOPIC :: Int-pattern RPL_TOPIC = 332--pattern RPL_TOPICWHOTIME :: Int-pattern RPL_TOPICWHOTIME = 333--pattern RPL_LISTUSAGE :: Int-pattern RPL_LISTUSAGE = 334--pattern RPL_COMMANDSYNTAX :: Int-pattern RPL_COMMANDSYNTAX = 334--pattern RPL_LISTSYNTAX :: Int-pattern RPL_LISTSYNTAX = 334--pattern RPL_CHANPASSOK :: Int-pattern RPL_CHANPASSOK = 338--pattern RPL_WHOISACTUALLY :: Int-pattern RPL_WHOISACTUALLY = 338--pattern RPL_BADCHANPASS :: Int-pattern RPL_BADCHANPASS = 339--pattern RPL_INVITING :: Int-pattern RPL_INVITING = 341--pattern RPL_SUMMONING :: Int-pattern RPL_SUMMONING = 342--pattern RPL_INVITED :: Int-pattern RPL_INVITED = 345--pattern RPL_INVITELIST :: Int-pattern RPL_INVITELIST = 346--pattern RPL_ENDOFINVITELIST :: Int-pattern RPL_ENDOFINVITELIST = 347--pattern RPL_EXCEPTLIST :: Int-pattern RPL_EXCEPTLIST = 348--pattern RPL_ENDOFEXCEPTLIST :: Int-pattern RPL_ENDOFEXCEPTLIST = 349--pattern RPL_VERSION :: Int-pattern RPL_VERSION = 351--pattern RPL_WHOREPLY :: Int-pattern RPL_WHOREPLY = 352--pattern RPL_NAMREPLY :: Int-pattern RPL_NAMREPLY = 353--pattern RPL_WHOSPCRPL :: Int-pattern RPL_WHOSPCRPL = 354--pattern RPL_NAMREPLY_ :: Int-pattern RPL_NAMREPLY_ = 355--pattern RPL_KILLDONE :: Int-pattern RPL_KILLDONE = 361--pattern RPL_CLOSING :: Int-pattern RPL_CLOSING = 362--pattern RPL_CLOSEEND :: Int-pattern RPL_CLOSEEND = 363--pattern RPL_LINKS :: Int-pattern RPL_LINKS = 364--pattern RPL_ENDOFLINKS :: Int-pattern RPL_ENDOFLINKS = 365--pattern RPL_ENDOFNAMES :: Int-pattern RPL_ENDOFNAMES = 366--pattern RPL_BANLIST :: Int-pattern RPL_BANLIST = 367--pattern RPL_ENDOFBANLIST :: Int-pattern RPL_ENDOFBANLIST = 368--pattern RPL_ENDOFWHOWAS :: Int-pattern RPL_ENDOFWHOWAS = 369--pattern RPL_INFO :: Int-pattern RPL_INFO = 371--pattern RPL_MOTD :: Int-pattern RPL_MOTD = 372--pattern RPL_INFOSTART :: Int-pattern RPL_INFOSTART = 373--pattern RPL_ENDOFINFO :: Int-pattern RPL_ENDOFINFO = 374--pattern RPL_MOTDSTART :: Int-pattern RPL_MOTDSTART = 375--pattern RPL_ENDOFMOTD :: Int-pattern RPL_ENDOFMOTD = 376--pattern RPL_KICKEXPIRED :: Int-pattern RPL_KICKEXPIRED = 377--pattern RPL_SPAM :: Int-pattern RPL_SPAM = 377--pattern RPL_BANEXPIRED :: Int-pattern RPL_BANEXPIRED = 378--pattern RPL_WHOISHOST :: Int-pattern RPL_WHOISHOST = 378--pattern RPL_KICKLINKED :: Int-pattern RPL_KICKLINKED = 379--pattern RPL_BANLINKED :: Int-pattern RPL_BANLINKED = 380--pattern RPL_YOURHELPER :: Int-pattern RPL_YOURHELPER = 380--pattern RPL_YOUREOPER :: Int-pattern RPL_YOUREOPER = 381--pattern RPL_REHASHING :: Int-pattern RPL_REHASHING = 382--pattern RPL_YOURESERVICE :: Int-pattern RPL_YOURESERVICE = 383--pattern RPL_MYPORTIS :: Int-pattern RPL_MYPORTIS = 384--pattern RPL_NOTOPERANYMORE :: Int-pattern RPL_NOTOPERANYMORE = 385--pattern RPL_QLIST :: Int-pattern RPL_QLIST = 386--pattern RPL_IRCOPS :: Int-pattern RPL_IRCOPS = 386--pattern RPL_ENDOFQLIST :: Int-pattern RPL_ENDOFQLIST = 387--pattern RPL_ENDOFIRCOPS :: Int-pattern RPL_ENDOFIRCOPS = 387--pattern RPL_TIME :: Int-pattern RPL_TIME = 391--pattern RPL_USERSSTART :: Int-pattern RPL_USERSSTART = 392--pattern RPL_USERS :: Int-pattern RPL_USERS = 393--pattern RPL_ENDOFUSERS :: Int-pattern RPL_ENDOFUSERS = 394--pattern RPL_NOUSERS :: Int-pattern RPL_NOUSERS = 395--pattern RPL_HOSTHIDDEN :: Int-pattern RPL_HOSTHIDDEN = 396--pattern ERR_UNKNOWNERROR :: Int-pattern ERR_UNKNOWNERROR = 400--pattern ERR_NOSUCHNICK :: Int-pattern ERR_NOSUCHNICK = 401--pattern ERR_NOSUCHSERVER :: Int-pattern ERR_NOSUCHSERVER = 402--pattern ERR_NOSUCHCHANNEL :: Int-pattern ERR_NOSUCHCHANNEL = 403--pattern ERR_CANNOTSENDTOCHAN :: Int-pattern ERR_CANNOTSENDTOCHAN = 404--pattern ERR_TOOMANYCHANNELS :: Int-pattern ERR_TOOMANYCHANNELS = 405--pattern ERR_WASNOSUCHNICK :: Int-pattern ERR_WASNOSUCHNICK = 406--pattern ERR_TOOMANYTARGETS :: Int-pattern ERR_TOOMANYTARGETS = 407--pattern ERR_NOSUCHSERVICE :: Int-pattern ERR_NOSUCHSERVICE = 408--pattern ERR_NOCOLORSONCHAN :: Int-pattern ERR_NOCOLORSONCHAN = 408--pattern ERR_NOORIGIN :: Int-pattern ERR_NOORIGIN = 409--pattern ERR_NORECIPIENT :: Int-pattern ERR_NORECIPIENT = 411--pattern ERR_NOTEXTTOSEND :: Int-pattern ERR_NOTEXTTOSEND = 412--pattern ERR_NOTOPLEVEL :: Int-pattern ERR_NOTOPLEVEL = 413--pattern ERR_WILDTOPLEVEL :: Int-pattern ERR_WILDTOPLEVEL = 414--pattern ERR_BADMASK :: Int-pattern ERR_BADMASK = 415--pattern ERR_TOOMANYMATCHES :: Int-pattern ERR_TOOMANYMATCHES = 416--pattern ERR_QUERYTOOLONG :: Int-pattern ERR_QUERYTOOLONG = 416--pattern ERR_LENGTHTRUNCATED :: Int-pattern ERR_LENGTHTRUNCATED = 419--pattern ERR_UNKNOWNCOMMAND :: Int-pattern ERR_UNKNOWNCOMMAND = 421--pattern ERR_NOMOTD :: Int-pattern ERR_NOMOTD = 422--pattern ERR_NOADMININFO :: Int-pattern ERR_NOADMININFO = 423--pattern ERR_FILEERROR :: Int-pattern ERR_FILEERROR = 424--pattern ERR_NOOPERMOTD :: Int-pattern ERR_NOOPERMOTD = 425--pattern ERR_TOOMANYAWAY :: Int-pattern ERR_TOOMANYAWAY = 429--pattern ERR_EVENTNICKCHANGE :: Int-pattern ERR_EVENTNICKCHANGE = 430--pattern ERR_NONICKNAMEGIVEN :: Int-pattern ERR_NONICKNAMEGIVEN = 431--pattern ERR_ERRONEUSNICKNAME :: Int-pattern ERR_ERRONEUSNICKNAME = 432--pattern ERR_NICKNAMEINUSE :: Int-pattern ERR_NICKNAMEINUSE = 433--pattern ERR_SERVICENAMEINUSE :: Int-pattern ERR_SERVICENAMEINUSE = 434--pattern ERR_NORULES :: Int-pattern ERR_NORULES = 434--pattern ERR_SERVICECONFUSED :: Int-pattern ERR_SERVICECONFUSED = 435--pattern ERR_BANONCHAN :: Int-pattern ERR_BANONCHAN = 435--pattern ERR_NICKCOLLISION :: Int-pattern ERR_NICKCOLLISION = 436--pattern ERR_UNAVAILRESOURCE :: Int-pattern ERR_UNAVAILRESOURCE = 437--pattern ERR_BANNICKCHANGE :: Int-pattern ERR_BANNICKCHANGE = 437--pattern ERR_NICKTOOFAST :: Int-pattern ERR_NICKTOOFAST = 438--pattern ERR_DEAD :: Int-pattern ERR_DEAD = 438--pattern ERR_TARGETTOOFAST :: Int-pattern ERR_TARGETTOOFAST = 439--pattern ERR_SERVICESDOWN :: Int-pattern ERR_SERVICESDOWN = 440--pattern ERR_USERNOTINCHANNEL :: Int-pattern ERR_USERNOTINCHANNEL = 441--pattern ERR_NOTONCHANNEL :: Int-pattern ERR_NOTONCHANNEL = 442--pattern ERR_USERONCHANNEL :: Int-pattern ERR_USERONCHANNEL = 443--pattern ERR_NOLOGIN :: Int-pattern ERR_NOLOGIN = 444--pattern ERR_SUMMONDISABLED :: Int-pattern ERR_SUMMONDISABLED = 445--pattern ERR_USERSDISABLED :: Int-pattern ERR_USERSDISABLED = 446--pattern ERR_NONICKCHANGE :: Int-pattern ERR_NONICKCHANGE = 447--pattern ERR_NOTIMPLEMENTED :: Int-pattern ERR_NOTIMPLEMENTED = 449--pattern ERR_NOTREGISTERED :: Int-pattern ERR_NOTREGISTERED = 451--pattern ERR_IDCOLLISION :: Int-pattern ERR_IDCOLLISION = 452--pattern ERR_NICKLOST :: Int-pattern ERR_NICKLOST = 453--pattern ERR_HOSTILENAME :: Int-pattern ERR_HOSTILENAME = 455--pattern ERR_ACCEPTFULL :: Int-pattern ERR_ACCEPTFULL = 456--pattern ERR_ACCEPTEXIST :: Int-pattern ERR_ACCEPTEXIST = 457--pattern ERR_ACCEPTNOT :: Int-pattern ERR_ACCEPTNOT = 458--pattern ERR_NOHIDING :: Int-pattern ERR_NOHIDING = 459--pattern ERR_NOTFORHALFOPS :: Int-pattern ERR_NOTFORHALFOPS = 460--pattern ERR_NEEDMOREPARAMS :: Int-pattern ERR_NEEDMOREPARAMS = 461--pattern ERR_ALREADYREGISTERED :: Int-pattern ERR_ALREADYREGISTERED = 462--pattern ERR_NOPERMFORHOST :: Int-pattern ERR_NOPERMFORHOST = 463--pattern ERR_PASSWDMISMATCH :: Int-pattern ERR_PASSWDMISMATCH = 464--pattern ERR_YOUREBANNEDCREEP :: Int-pattern ERR_YOUREBANNEDCREEP = 465--pattern ERR_YOUWILLBEBANNED :: Int-pattern ERR_YOUWILLBEBANNED = 466--pattern ERR_KEYSET :: Int-pattern ERR_KEYSET = 467--pattern ERR_INVALIDUSERNAME :: Int-pattern ERR_INVALIDUSERNAME = 468--pattern ERR_ONLYSERVERSCANCHANGE :: Int-pattern ERR_ONLYSERVERSCANCHANGE = 468--pattern ERR_LINKSET :: Int-pattern ERR_LINKSET = 469--pattern ERR_LINKCHANNEL :: Int-pattern ERR_LINKCHANNEL = 470--pattern ERR_KICKEDFROMCHAN :: Int-pattern ERR_KICKEDFROMCHAN = 470--pattern ERR_CHANNELISFULL :: Int-pattern ERR_CHANNELISFULL = 471--pattern ERR_UNKNOWNMODE :: Int-pattern ERR_UNKNOWNMODE = 472--pattern ERR_INVITEONLYCHAN :: Int-pattern ERR_INVITEONLYCHAN = 473--pattern ERR_BANNEDFROMCHAN :: Int-pattern ERR_BANNEDFROMCHAN = 474--pattern ERR_BADCHANNELKEY :: Int-pattern ERR_BADCHANNELKEY = 475--pattern ERR_BADCHANMASK :: Int-pattern ERR_BADCHANMASK = 476--pattern ERR_NOCHANMODES :: Int-pattern ERR_NOCHANMODES = 477--pattern ERR_NEEDREGGEDNICK :: Int-pattern ERR_NEEDREGGEDNICK = 477--pattern ERR_BANLISTFULL :: Int-pattern ERR_BANLISTFULL = 478--pattern ERR_BADCHANNAME :: Int-pattern ERR_BADCHANNAME = 479--pattern ERR_LINKFAIL :: Int-pattern ERR_LINKFAIL = 479--pattern ERR_NOULINE :: Int-pattern ERR_NOULINE = 480--pattern ERR_CANNOTKNOCK :: Int-pattern ERR_CANNOTKNOCK = 480--pattern ERR_NOPRIVILEGES :: Int-pattern ERR_NOPRIVILEGES = 481--pattern ERR_CHANOPRIVSNEEDED :: Int-pattern ERR_CHANOPRIVSNEEDED = 482--pattern ERR_CANTKILLSERVER :: Int-pattern ERR_CANTKILLSERVER = 483--pattern ERR_RESTRICTED :: Int-pattern ERR_RESTRICTED = 484--pattern ERR_ISCHANSERVICE :: Int-pattern ERR_ISCHANSERVICE = 484--pattern ERR_DESYNC :: Int-pattern ERR_DESYNC = 484--pattern ERR_ATTACKDENY :: Int-pattern ERR_ATTACKDENY = 484--pattern ERR_UNIQOPRIVSNEEDED :: Int-pattern ERR_UNIQOPRIVSNEEDED = 485--pattern ERR_KILLDENY :: Int-pattern ERR_KILLDENY = 485--pattern ERR_CANTKICKADMIN :: Int-pattern ERR_CANTKICKADMIN = 485--pattern ERR_ISREALSERVICE :: Int-pattern ERR_ISREALSERVICE = 485--pattern ERR_NONONREG :: Int-pattern ERR_NONONREG = 486--pattern ERR_HTMDISABLED :: Int-pattern ERR_HTMDISABLED = 486--pattern ERR_ACCOUNTONLY :: Int-pattern ERR_ACCOUNTONLY = 486--pattern ERR_CHANTOORECENT :: Int-pattern ERR_CHANTOORECENT = 487--pattern ERR_MSGSERVICES :: Int-pattern ERR_MSGSERVICES = 487--pattern ERR_TSLESSCHAN :: Int-pattern ERR_TSLESSCHAN = 488--pattern ERR_VOICENEEDED :: Int-pattern ERR_VOICENEEDED = 489--pattern ERR_SECUREONLYCHAN :: Int-pattern ERR_SECUREONLYCHAN = 489--pattern ERR_NOOPERHOST :: Int-pattern ERR_NOOPERHOST = 491--pattern ERR_NOSERVICEHOST :: Int-pattern ERR_NOSERVICEHOST = 492--pattern ERR_NOFEATURE :: Int-pattern ERR_NOFEATURE = 493--pattern ERR_BADFEATURE :: Int-pattern ERR_BADFEATURE = 494--pattern ERR_BADLOGTYPE :: Int-pattern ERR_BADLOGTYPE = 495--pattern ERR_BADLOGSYS :: Int-pattern ERR_BADLOGSYS = 496--pattern ERR_BADLOGVALUE :: Int-pattern ERR_BADLOGVALUE = 497--pattern ERR_ISOPERLCHAN :: Int-pattern ERR_ISOPERLCHAN = 498--pattern ERR_CHANOWNPRIVNEEDED :: Int-pattern ERR_CHANOWNPRIVNEEDED = 499--pattern ERR_UMODEUNKNOWNFLAG :: Int-pattern ERR_UMODEUNKNOWNFLAG = 501--pattern ERR_USERSDONTMATCH :: Int-pattern ERR_USERSDONTMATCH = 502--pattern ERR_GHOSTEDCLIENT :: Int-pattern ERR_GHOSTEDCLIENT = 503--pattern ERR_VWORLDWARN :: Int-pattern ERR_VWORLDWARN = 503--pattern ERR_USERNOTONSERV :: Int-pattern ERR_USERNOTONSERV = 504--pattern ERR_SILELISTFULL :: Int-pattern ERR_SILELISTFULL = 511--pattern ERR_TOOMANYWATCH :: Int-pattern ERR_TOOMANYWATCH = 512--pattern ERR_BADPING :: Int-pattern ERR_BADPING = 513--pattern ERR_INVALID_ERROR :: Int-pattern ERR_INVALID_ERROR = 514--pattern ERR_TOOMANYDCC :: Int-pattern ERR_TOOMANYDCC = 514--pattern ERR_BADEXPIRE :: Int-pattern ERR_BADEXPIRE = 515--pattern ERR_DONTCHEAT :: Int-pattern ERR_DONTCHEAT = 516--pattern ERR_DISABLED :: Int-pattern ERR_DISABLED = 517--pattern ERR_NOINVITE :: Int-pattern ERR_NOINVITE = 518--pattern ERR_LONGMASK :: Int-pattern ERR_LONGMASK = 518--pattern ERR_ADMONLY :: Int-pattern ERR_ADMONLY = 519--pattern ERR_TOOMANYUSERS :: Int-pattern ERR_TOOMANYUSERS = 519--pattern ERR_OPERONLY :: Int-pattern ERR_OPERONLY = 520--pattern ERR_MASKTOOWIDE :: Int-pattern ERR_MASKTOOWIDE = 520--pattern ERR_WHOTRUNC :: Int-pattern ERR_WHOTRUNC = 520--pattern ERR_LISTSYNTAX :: Int-pattern ERR_LISTSYNTAX = 521--pattern ERR_WHOSYNTAX :: Int-pattern ERR_WHOSYNTAX = 522--pattern ERR_WHOLIMEXCEED :: Int-pattern ERR_WHOLIMEXCEED = 523--pattern ERR_QUARANTINED :: Int-pattern ERR_QUARANTINED = 524--pattern ERR_OPERSPVERIFY :: Int-pattern ERR_OPERSPVERIFY = 524--pattern ERR_REMOTEPFX :: Int-pattern ERR_REMOTEPFX = 525--pattern ERR_PFXUNROUTABLE :: Int-pattern ERR_PFXUNROUTABLE = 526--pattern ERR_BADHOSTMASK :: Int-pattern ERR_BADHOSTMASK = 550--pattern ERR_HOSTUNAVAIL :: Int-pattern ERR_HOSTUNAVAIL = 551--pattern ERR_USINGSLINE :: Int-pattern ERR_USINGSLINE = 552--pattern ERR_STATSSLINE :: Int-pattern ERR_STATSSLINE = 553--pattern RPL_LOGON :: Int-pattern RPL_LOGON = 600--pattern RPL_LOGOFF :: Int-pattern RPL_LOGOFF = 601--pattern RPL_WATCHOFF :: Int-pattern RPL_WATCHOFF = 602--pattern RPL_WATCHSTAT :: Int-pattern RPL_WATCHSTAT = 603--pattern RPL_NOWON :: Int-pattern RPL_NOWON = 604--pattern RPL_NOWOFF :: Int-pattern RPL_NOWOFF = 605--pattern RPL_WATCHLIST :: Int-pattern RPL_WATCHLIST = 606--pattern RPL_ENDOFWATCHLIST :: Int-pattern RPL_ENDOFWATCHLIST = 607--pattern RPL_WATCHCLEAR :: Int-pattern RPL_WATCHCLEAR = 608--pattern RPL_ISOPER :: Int-pattern RPL_ISOPER = 610--pattern RPL_ISLOCOP :: Int-pattern RPL_ISLOCOP = 611--pattern RPL_ISNOTOPER :: Int-pattern RPL_ISNOTOPER = 612--pattern RPL_ENDOFISOPER :: Int-pattern RPL_ENDOFISOPER = 613--pattern RPL_DCCSTATUS :: Int-pattern RPL_DCCSTATUS = 617--pattern RPL_DCCLIST :: Int-pattern RPL_DCCLIST = 618--pattern RPL_ENDOFDCCLIST :: Int-pattern RPL_ENDOFDCCLIST = 619--pattern RPL_WHOWASHOST :: Int-pattern RPL_WHOWASHOST = 619--pattern RPL_DCCINFO :: Int-pattern RPL_DCCINFO = 620--pattern RPL_RULES :: Int-pattern RPL_RULES = 621--pattern RPL_ENDOFO :: Int-pattern RPL_ENDOFO = 626--pattern RPL_SETTINGS :: Int-pattern RPL_SETTINGS = 630--pattern RPL_ENDOFSETTINGS :: Int-pattern RPL_ENDOFSETTINGS = 631--pattern RPL_DUMPING :: Int-pattern RPL_DUMPING = 640--pattern RPL_DUMPRPL :: Int-pattern RPL_DUMPRPL = 641--pattern RPL_EODUMP :: Int-pattern RPL_EODUMP = 642--pattern RPL_TRACEROUTE_HOP :: Int-pattern RPL_TRACEROUTE_HOP = 660--pattern RPL_TRACEROUTE_START :: Int-pattern RPL_TRACEROUTE_START = 661--pattern RPL_MODECHANGEWARN :: Int-pattern RPL_MODECHANGEWARN = 662--pattern RPL_CHANREDIR :: Int-pattern RPL_CHANREDIR = 663--pattern RPL_SERVMODEIS :: Int-pattern RPL_SERVMODEIS = 664--pattern RPL_OTHERUMODEIS :: Int-pattern RPL_OTHERUMODEIS = 665--pattern RPL_ENDOF_GENERIC :: Int-pattern RPL_ENDOF_GENERIC = 666--pattern RPL_WHOWASDETAILS :: Int-pattern RPL_WHOWASDETAILS = 670--pattern RPL_WHOISSECURE :: Int-pattern RPL_WHOISSECURE = 671--pattern RPL_UNKNOWNMODES :: Int-pattern RPL_UNKNOWNMODES = 672--pattern RPL_CANNOTSETMODES :: Int-pattern RPL_CANNOTSETMODES = 673--pattern RPL_LUSERSTAFF :: Int-pattern RPL_LUSERSTAFF = 678--pattern RPL_TIMEONSERVERIS :: Int-pattern RPL_TIMEONSERVERIS = 679--pattern RPL_NETWORKS :: Int-pattern RPL_NETWORKS = 682--pattern RPL_YOURLANGUAGEIS :: Int-pattern RPL_YOURLANGUAGEIS = 687--pattern RPL_LANGUAGE :: Int-pattern RPL_LANGUAGE = 688--pattern RPL_WHOISSTAFF :: Int-pattern RPL_WHOISSTAFF = 689--pattern RPL_WHOISLANGUAGE :: Int-pattern RPL_WHOISLANGUAGE = 690--pattern RPL_ENDOFMODLIST :: Int-pattern RPL_ENDOFMODLIST = 703--pattern RPL_HELPSTART :: Int-pattern RPL_HELPSTART = 704--pattern RPL_HELPTXT :: Int-pattern RPL_HELPTXT = 705--pattern RPL_ENDOFHELP :: Int-pattern RPL_ENDOFHELP = 706--pattern RPL_ETRACEFULL :: Int-pattern RPL_ETRACEFULL = 708--pattern RPL_ETRACE :: Int-pattern RPL_ETRACE = 709--pattern RPL_KNOCK :: Int-pattern RPL_KNOCK = 710--pattern RPL_KNOCKDLVR :: Int-pattern RPL_KNOCKDLVR = 711--pattern ERR_TOOMANYKNOCK :: Int-pattern ERR_TOOMANYKNOCK = 712--pattern ERR_CHANOPEN :: Int-pattern ERR_CHANOPEN = 713--pattern ERR_KNOCKONCHAN :: Int-pattern ERR_KNOCKONCHAN = 714--pattern ERR_KNOCKDISABLED :: Int-pattern ERR_KNOCKDISABLED = 715--pattern RPL_TARGUMODEG :: Int-pattern RPL_TARGUMODEG = 716--pattern RPL_TARGNOTIFY :: Int-pattern RPL_TARGNOTIFY = 717--pattern RPL_UMODEGMSG :: Int-pattern RPL_UMODEGMSG = 718--pattern RPL_ENDOFOMOTD :: Int-pattern RPL_ENDOFOMOTD = 722--pattern ERR_NOPRIVS :: Int-pattern ERR_NOPRIVS = 723--pattern RPL_TESTMARK :: Int-pattern RPL_TESTMARK = 724--pattern RPL_TESTLINE :: Int-pattern RPL_TESTLINE = 725--pattern RPL_NOTESTLINE :: Int-pattern RPL_NOTESTLINE = 726--pattern RPL_QUIETLIST :: Int-pattern RPL_QUIETLIST = 728--pattern RPL_ENDOFQUIETLIST :: Int-pattern RPL_ENDOFQUIETLIST = 729--pattern RPL_XINFO :: Int-pattern RPL_XINFO = 771--pattern RPL_XINFOSTART :: Int-pattern RPL_XINFOSTART = 773--pattern RPL_XINFOEND :: Int-pattern RPL_XINFOEND = 774--pattern ERR_CANNOTDOCOMMAND :: Int-pattern ERR_CANNOTDOCOMMAND = 972--pattern ERR_CANNOTCHANGEUMODE :: Int-pattern ERR_CANNOTCHANGEUMODE = 973--pattern ERR_CANNOTCHANGECHANMODE :: Int-pattern ERR_CANNOTCHANGECHANMODE = 974--pattern ERR_CANNOTCHANGESERVERMODE :: Int-pattern ERR_CANNOTCHANGESERVERMODE = 975--pattern ERR_CANNOTSENDTONICK :: Int-pattern ERR_CANNOTSENDTONICK = 976--pattern ERR_UNKNOWNSERVERMODE :: Int-pattern ERR_UNKNOWNSERVERMODE = 977--pattern ERR_SERVERMODELOCK :: Int-pattern ERR_SERVERMODELOCK = 979--pattern ERR_BADCHARENCODING :: Int-pattern ERR_BADCHARENCODING = 980--pattern ERR_TOOMANYLANGUAGES :: Int-pattern ERR_TOOMANYLANGUAGES = 981--pattern ERR_NOLANGUAGE :: Int-pattern ERR_NOLANGUAGE = 982--pattern ERR_TEXTTOOSHORT :: Int-pattern ERR_TEXTTOOSHORT = 983--pattern ERR_NUMERIC_ERR :: Int-pattern ERR_NUMERIC_ERR = 999+{-# Language PatternSynonyms, OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}++{-|+Module : Irc.Codes+Description : Helpers for interpreting IRC reply codes+Copyright : (c) Eric Mertens, 2016+License : ISC+Maintainer : emertens@gmail.com++This module defines support for working with IRC's numeric reply+codes. Pattern synonyms are provided for each of the possible IRC reply codes.++Reply code information was extracted from https://www.alien.net.au/irc/irc2numerics.html++-}++module Irc.Codes where++import Data.Vector (Vector)+import qualified Data.Vector as Vector+import Data.Text (Text)+import qualified Data.Text as Text++-- | Type of numeric reply codes+newtype ReplyCode = ReplyCode Word++instance Show ReplyCode where+ showsPrec p (ReplyCode x) = showsPrec p x++-- | Categories for reply codes+data ReplyType+ = ClientServerReply -- ^ 0-99 Messages between client and server+ | CommandReply -- ^ 200-399 Responses to commands+ | ErrorReply -- ^ 200-399 Errors+ | UnknownReply -- ^ Uncategorized++pattern RPL_WELCOME = ReplyCode 001+pattern RPL_YOURHOST = ReplyCode 002+pattern RPL_CREATED = ReplyCode 003+pattern RPL_MYINFO = ReplyCode 004+pattern RPL_ISUPPORT = ReplyCode 005+pattern RPL_SNOMASK = ReplyCode 008+pattern RPL_STATMEMTOT = ReplyCode 009+pattern RPL_REDIR = ReplyCode 010+pattern RPL_YOURCOOKIE = ReplyCode 014+pattern RPL_MAP = ReplyCode 015+pattern RPL_MAPEND = ReplyCode 017+pattern RPL_YOURID = ReplyCode 042+pattern RPL_SAVENICK = ReplyCode 043+pattern RPL_ATTEMPTINGJUNC = ReplyCode 050+pattern RPL_ATTEMPTINGREROUTE = ReplyCode 051+pattern RPL_TRACELINK = ReplyCode 200+pattern RPL_TRACECONNECTING = ReplyCode 201+pattern RPL_TRACEHANDSHAKE = ReplyCode 202+pattern RPL_TRACEUNKNOWN = ReplyCode 203+pattern RPL_TRACEOPERATOR = ReplyCode 204+pattern RPL_TRACEUSER = ReplyCode 205+pattern RPL_TRACESERVER = ReplyCode 206+pattern RPL_TRACESERVICE = ReplyCode 207+pattern RPL_TRACENEWTYPE = ReplyCode 208+pattern RPL_TRACECLASS = ReplyCode 209+pattern RPL_TRACERECONNECT = ReplyCode 210+pattern RPL_STATS = ReplyCode 210+pattern RPL_STATSLINKINFO = ReplyCode 211+pattern RPL_STATSCOMMANDS = ReplyCode 212+pattern RPL_STATSCLINE = ReplyCode 213+pattern RPL_STATSNLINE = ReplyCode 214+pattern RPL_STATSILINE = ReplyCode 215+pattern RPL_STATSKLINE = ReplyCode 216+pattern RPL_STATSQLINE = ReplyCode 217+pattern RPL_STATSYLINE = ReplyCode 218+pattern RPL_ENDOFSTATS = ReplyCode 219+pattern RPL_STATSPLINE = ReplyCode 220+pattern RPL_UMODEIS = ReplyCode 221+pattern RPL_SQLINE_NICK = ReplyCode 222+pattern RPL_STATSDLINE = ReplyCode 225+pattern RPL_STATSZLINE = ReplyCode 225+pattern RPL_STATSCOUNT = ReplyCode 226+pattern RPL_SERVICEINFO = ReplyCode 231+pattern RPL_ENDOFSERVICES = ReplyCode 232+pattern RPL_SERVICE = ReplyCode 233+pattern RPL_SERVLIST = ReplyCode 234+pattern RPL_SERVLISTEND = ReplyCode 235+pattern RPL_STATSVERBOSE = ReplyCode 236+pattern RPL_STATSIAUTH = ReplyCode 239+pattern RPL_STATSLLINE = ReplyCode 241+pattern RPL_STATSUPTIME = ReplyCode 242+pattern RPL_STATSOLINE = ReplyCode 243+pattern RPL_STATSHLINE = ReplyCode 244+pattern RPL_STATSSLINE = ReplyCode 245+pattern RPL_STATSPING = ReplyCode 246+pattern RPL_STATSXLINE = ReplyCode 247+pattern RPL_STATSULINE = ReplyCode 248+pattern RPL_STATSDEBUG = ReplyCode 249+pattern RPL_STATSCONN = ReplyCode 250+pattern RPL_LUSERCLIENT = ReplyCode 251+pattern RPL_LUSEROP = ReplyCode 252+pattern RPL_LUSERUNKNOWN = ReplyCode 253+pattern RPL_LUSERCHANNELS = ReplyCode 254+pattern RPL_LUSERME = ReplyCode 255+pattern RPL_ADMINME = ReplyCode 256+pattern RPL_ADMINLOC1 = ReplyCode 257+pattern RPL_ADMINLOC2 = ReplyCode 258+pattern RPL_ADMINEMAIL = ReplyCode 259+pattern RPL_TRACELOG = ReplyCode 261+pattern RPL_ENDOFTRACE = ReplyCode 262+pattern RPL_LOAD2HI = ReplyCode 263+pattern RPL_LOCALUSERS = ReplyCode 265+pattern RPL_GLOBALUSERS = ReplyCode 266+pattern RPL_START_NETSTAT = ReplyCode 267+pattern RPL_NETSTAT = ReplyCode 268+pattern RPL_END_NETSTAT = ReplyCode 269+pattern RPL_PRIVS = ReplyCode 270+pattern RPL_SILELIST = ReplyCode 271+pattern RPL_ENDOFSILELIST = ReplyCode 272+pattern RPL_NOTIFY = ReplyCode 273+pattern RPL_ENDNOTIFY = ReplyCode 274+pattern RPL_STATSDELTA = ReplyCode 274+pattern RPL_WHOISCERTFP = ReplyCode 276+pattern RPL_VCHANLIST = ReplyCode 277+pattern RPL_VCHANHELP = ReplyCode 278+pattern RPL_GLIST = ReplyCode 280+pattern RPL_ACCEPTLIST = ReplyCode 281+pattern RPL_ENDOFACCEPT = ReplyCode 282+pattern RPL_ENDOFJUPELIST = ReplyCode 283+pattern RPL_FEATURE = ReplyCode 284+pattern RPL_DATASTR = ReplyCode 290+pattern RPL_END_CHANINFO = ReplyCode 299+pattern RPL_NONE = ReplyCode 300+pattern RPL_AWAY = ReplyCode 301+pattern RPL_USERHOST = ReplyCode 302+pattern RPL_ISON = ReplyCode 303+pattern RPL_TEXT = ReplyCode 304+pattern RPL_UNAWAY = ReplyCode 305+pattern RPL_NOWAWAY = ReplyCode 306+pattern RPL_WHOISREGNICK = ReplyCode 307+pattern RPL_SUSERHOST = ReplyCode 307+pattern RPL_NOTIFYACTION = ReplyCode 308+pattern RPL_WHOISADMIN = ReplyCode 308+pattern RPL_NICKTRACE = ReplyCode 309+pattern RPL_WHOISSADMIN = ReplyCode 309+pattern RPL_WHOISHELPER = ReplyCode 309+pattern RPL_WHOISUSER = ReplyCode 311+pattern RPL_WHOISSERVER = ReplyCode 312+pattern RPL_WHOISOPERATOR = ReplyCode 313+pattern RPL_WHOWASUSER = ReplyCode 314+pattern RPL_ENDOFWHO = ReplyCode 315+pattern RPL_WHOISCHANOP = ReplyCode 316+pattern RPL_WHOISIDLE = ReplyCode 317+pattern RPL_ENDOFWHOIS = ReplyCode 318+pattern RPL_WHOISCHANNELS = ReplyCode 319+pattern RPL_WHOISSPECIAL = ReplyCode 320+pattern RPL_LISTSTART = ReplyCode 321+pattern RPL_LIST = ReplyCode 322+pattern RPL_LISTEND = ReplyCode 323+pattern RPL_CHANNELMODEIS = ReplyCode 324+pattern RPL_CHANNELMLOCKIS = ReplyCode 325+pattern RPL_NOCHANPASS = ReplyCode 326+pattern RPL_CHPASSUNKNOWN = ReplyCode 327+pattern RPL_CHANNEL_URL = ReplyCode 328+pattern RPL_CREATIONTIME = ReplyCode 329+pattern RPL_WHOWAS_TIME = ReplyCode 330+pattern RPL_WHOISACCOUNT = ReplyCode 330+pattern RPL_NOTOPIC = ReplyCode 331+pattern RPL_TOPIC = ReplyCode 332+pattern RPL_TOPICWHOTIME = ReplyCode 333+pattern RPL_LISTUSAGE = ReplyCode 334+pattern RPL_COMMANDSYNTAX = ReplyCode 334+pattern RPL_LISTSYNTAX = ReplyCode 334+pattern RPL_WHOISACTUALLY = ReplyCode 338+pattern RPL_BADCHANPASS = ReplyCode 339+pattern RPL_INVITING = ReplyCode 341+pattern RPL_SUMMONING = ReplyCode 342+pattern RPL_INVITED = ReplyCode 345+pattern RPL_INVEXLIST = ReplyCode 346+pattern RPL_ENDOFINVEXLIST = ReplyCode 347+pattern RPL_EXCEPTLIST = ReplyCode 348+pattern RPL_ENDOFEXCEPTLIST = ReplyCode 349+pattern RPL_VERSION = ReplyCode 351+pattern RPL_WHOREPLY = ReplyCode 352+pattern RPL_NAMREPLY = ReplyCode 353+pattern RPL_WHOSPCRPL = ReplyCode 354+pattern RPL_NAMREPLY_ = ReplyCode 355+pattern RPL_WHOWASREAL = ReplyCode 360+pattern RPL_KILLDONE = ReplyCode 361+pattern RPL_CLOSING = ReplyCode 362+pattern RPL_CLOSEEND = ReplyCode 363+pattern RPL_LINKS = ReplyCode 364+pattern RPL_ENDOFLINKS = ReplyCode 365+pattern RPL_ENDOFNAMES = ReplyCode 366+pattern RPL_BANLIST = ReplyCode 367+pattern RPL_ENDOFBANLIST = ReplyCode 368+pattern RPL_ENDOFWHOWAS = ReplyCode 369+pattern RPL_INFO = ReplyCode 371+pattern RPL_MOTD = ReplyCode 372+pattern RPL_INFOSTART = ReplyCode 373+pattern RPL_ENDOFINFO = ReplyCode 374+pattern RPL_MOTDSTART = ReplyCode 375+pattern RPL_ENDOFMOTD = ReplyCode 376+pattern RPL_WHOISHOST = ReplyCode 378+pattern RPL_KICKLINKED = ReplyCode 379+pattern RPL_YOUREOPER = ReplyCode 381+pattern RPL_REHASHING = ReplyCode 382+pattern RPL_YOURESERVICE = ReplyCode 383+pattern RPL_MYPORTIS = ReplyCode 384+pattern RPL_NOTOPERANYMORE = ReplyCode 385+pattern RPL_RSACHALLENGE = ReplyCode 386+pattern RPL_TIME = ReplyCode 391+pattern RPL_USERSSTART = ReplyCode 392+pattern RPL_USERS = ReplyCode 393+pattern RPL_ENDOFUSERS = ReplyCode 394+pattern RPL_NOUSERS = ReplyCode 395+pattern RPL_HOSTHIDDEN = ReplyCode 396+pattern ERR_UNKNOWNERROR = ReplyCode 400+pattern ERR_NOSUCHNICK = ReplyCode 401+pattern ERR_NOSUCHSERVER = ReplyCode 402+pattern ERR_NOSUCHCHANNEL = ReplyCode 403+pattern ERR_CANNOTSENDTOCHAN = ReplyCode 404+pattern ERR_TOOMANYCHANNELS = ReplyCode 405+pattern ERR_WASNOSUCHNICK = ReplyCode 406+pattern ERR_TOOMANYTARGETS = ReplyCode 407+pattern ERR_NOORIGIN = ReplyCode 409+pattern ERR_NORECIPIENT = ReplyCode 411+pattern ERR_NOTEXTTOSEND = ReplyCode 412+pattern ERR_NOTOPLEVEL = ReplyCode 413+pattern ERR_WILDTOPLEVEL = ReplyCode 414+pattern ERR_BADMASK = ReplyCode 415+pattern ERR_TOOMANYMATCHES = ReplyCode 416+pattern ERR_LENGTHTRUNCATED = ReplyCode 419+pattern ERR_UNKNOWNCOMMAND = ReplyCode 421+pattern ERR_NOMOTD = ReplyCode 422+pattern ERR_NOADMININFO = ReplyCode 423+pattern ERR_FILEERROR = ReplyCode 424+pattern ERR_NOOPERMOTD = ReplyCode 425+pattern ERR_TOOMANYAWAY = ReplyCode 429+pattern ERR_EVENTNICKCHANGE = ReplyCode 430+pattern ERR_NONICKNAMEGIVEN = ReplyCode 431+pattern ERR_ERRONEUSNICKNAME = ReplyCode 432+pattern ERR_NICKNAMEINUSE = ReplyCode 433+pattern ERR_SERVICENAMEINUSE = ReplyCode 434+pattern ERR_NORULES = ReplyCode 434+pattern ERR_BANNICKCHANGE = ReplyCode 435+pattern ERR_NICKCOLLISION = ReplyCode 436+pattern ERR_UNAVAILRESOURCE = ReplyCode 437+pattern ERR_NICKTOOFAST = ReplyCode 438+pattern ERR_TARGETTOOFAST = ReplyCode 439+pattern ERR_SERVICESDOWN = ReplyCode 440+pattern ERR_USERNOTINCHANNEL = ReplyCode 441+pattern ERR_NOTONCHANNEL = ReplyCode 442+pattern ERR_USERONCHANNEL = ReplyCode 443+pattern ERR_NOLOGIN = ReplyCode 444+pattern ERR_SUMMONDISABLED = ReplyCode 445+pattern ERR_USERSDISABLED = ReplyCode 446+pattern ERR_NONICKCHANGE = ReplyCode 447+pattern ERR_NOTIMPLEMENTED = ReplyCode 449+pattern ERR_NOTREGISTERED = ReplyCode 451+pattern ERR_IDCOLLISION = ReplyCode 452+pattern ERR_NICKLOST = ReplyCode 453+pattern ERR_HOSTILENAME = ReplyCode 455+pattern ERR_ACCEPTFULL = ReplyCode 456+pattern ERR_ACCEPTEXIST = ReplyCode 457+pattern ERR_ACCEPTNOT = ReplyCode 458+pattern ERR_NOHIDING = ReplyCode 459+pattern ERR_NOTFORHALFOPS = ReplyCode 460+pattern ERR_NEEDMOREPARAMS = ReplyCode 461+pattern ERR_ALREADYREGISTERED = ReplyCode 462+pattern ERR_NOPERMFORHOST = ReplyCode 463+pattern ERR_PASSWDMISMATCH = ReplyCode 464+pattern ERR_YOUREBANNEDCREEP = ReplyCode 465+pattern ERR_YOUWILLBEBANNED = ReplyCode 466+pattern ERR_KEYSET = ReplyCode 467+pattern ERR_INVALIDUSERNAME = ReplyCode 468+pattern ERR_ONLYSERVERSCANCHANGE = ReplyCode 468+pattern ERR_LINKSET = ReplyCode 469+pattern ERR_LINKCHANNEL = ReplyCode 470+pattern ERR_CHANNELISFULL = ReplyCode 471+pattern ERR_UNKNOWNMODE = ReplyCode 472+pattern ERR_INVITEONLYCHAN = ReplyCode 473+pattern ERR_BANNEDFROMCHAN = ReplyCode 474+pattern ERR_BADCHANNELKEY = ReplyCode 475+pattern ERR_BADCHANMASK = ReplyCode 476+pattern ERR_NEEDREGGEDNICK = ReplyCode 477+pattern ERR_BANLISTFULL = ReplyCode 478+pattern ERR_BADCHANNAME = ReplyCode 479+pattern ERR_THROTTLE = ReplyCode 480+pattern ERR_NOPRIVILEGES = ReplyCode 481+pattern ERR_CHANOPRIVSNEEDED = ReplyCode 482+pattern ERR_CANTKILLSERVER = ReplyCode 483+pattern ERR_ISCHANSERVICE = ReplyCode 484+pattern ERR_BANNEDNICK = ReplyCode 485+pattern ERR_NONONREG = ReplyCode 486+pattern ERR_TSLESSCHAN = ReplyCode 488+pattern ERR_VOICENEEDED = ReplyCode 489+pattern ERR_NOOPERHOST = ReplyCode 491+pattern ERR_NOSERVICEHOST = ReplyCode 492+pattern ERR_NOFEATURE = ReplyCode 493+pattern ERR_OWNMODE = ReplyCode 494+pattern ERR_BADLOGTYPE = ReplyCode 495+pattern ERR_BADLOGSYS = ReplyCode 496+pattern ERR_BADLOGVALUE = ReplyCode 497+pattern ERR_ISOPERLCHAN = ReplyCode 498+pattern ERR_CHANOWNPRIVNEEDED = ReplyCode 499+pattern ERR_UMODEUNKNOWNFLAG = ReplyCode 501+pattern ERR_USERSDONTMATCH = ReplyCode 502+pattern ERR_GHOSTEDCLIENT = ReplyCode 503+pattern ERR_USERNOTONSERV = ReplyCode 504+pattern ERR_SILELISTFULL = ReplyCode 511+pattern ERR_TOOMANYWATCH = ReplyCode 512+pattern ERR_WRONGPONG = ReplyCode 513+pattern ERR_BADEXPIRE = ReplyCode 515+pattern ERR_DONTCHEAT = ReplyCode 516+pattern ERR_DISABLED = ReplyCode 517+pattern ERR_NOINVITE = ReplyCode 518+pattern ERR_LONGMASK = ReplyCode 518+pattern ERR_ADMONLY = ReplyCode 519+pattern ERR_TOOMANYUSERS = ReplyCode 519+pattern ERR_OPERONLY = ReplyCode 520+pattern ERR_MASKTOOWIDE = ReplyCode 520+pattern ERR_WHOTRUNC = ReplyCode 520+pattern ERR_LISTSYNTAX = ReplyCode 521+pattern ERR_WHOSYNTAX = ReplyCode 522+pattern ERR_WHOLIMEXCEED = ReplyCode 523+pattern ERR_HELPNOTFOUND = ReplyCode 524+pattern ERR_REMOTEPFX = ReplyCode 525+pattern ERR_PFXUNROUTABLE = ReplyCode 526+pattern ERR_BADHOSTMASK = ReplyCode 550+pattern ERR_HOSTUNAVAIL = ReplyCode 551+pattern ERR_USINGSLINE = ReplyCode 552+pattern ERR_STATSSLINE = ReplyCode 553+pattern RPL_LOGON = ReplyCode 600+pattern RPL_LOGOFF = ReplyCode 601+pattern RPL_WATCHOFF = ReplyCode 602+pattern RPL_WATCHSTAT = ReplyCode 603+pattern RPL_NOWON = ReplyCode 604+pattern RPL_NOWOFF = ReplyCode 605+pattern RPL_WATCHLIST = ReplyCode 606+pattern RPL_ENDOFWATCHLIST = ReplyCode 607+pattern RPL_WATCHCLEAR = ReplyCode 608+pattern RPL_ISOPER = ReplyCode 610+pattern RPL_ISLOCOP = ReplyCode 611+pattern RPL_ISNOTOPER = ReplyCode 612+pattern RPL_ENDOFISOPER = ReplyCode 613+pattern RPL_DCCSTATUS = ReplyCode 617+pattern RPL_DCCLIST = ReplyCode 618+pattern RPL_ENDOFDCCLIST = ReplyCode 619+pattern RPL_WHOWASHOST = ReplyCode 619+pattern RPL_DCCINFO = ReplyCode 620+pattern RPL_RULES = ReplyCode 621+pattern RPL_ENDOFO = ReplyCode 626+pattern RPL_SETTINGS = ReplyCode 630+pattern RPL_ENDOFSETTINGS = ReplyCode 631+pattern RPL_DUMPING = ReplyCode 640+pattern RPL_DUMPRPL = ReplyCode 641+pattern RPL_EODUMP = ReplyCode 642+pattern RPL_TRACEROUTE_HOP = ReplyCode 660+pattern RPL_TRACEROUTE_START = ReplyCode 661+pattern RPL_MODECHANGEWARN = ReplyCode 662+pattern RPL_CHANREDIR = ReplyCode 663+pattern RPL_SERVMODEIS = ReplyCode 664+pattern RPL_OTHERUMODEIS = ReplyCode 665+pattern RPL_ENDOF_GENERIC = ReplyCode 666+pattern RPL_WHOWASDETAILS = ReplyCode 670+pattern RPL_WHOISSECURE = ReplyCode 671+pattern RPL_UNKNOWNMODES = ReplyCode 672+pattern RPL_CANNOTSETMODES = ReplyCode 673+pattern RPL_LUSERSTAFF = ReplyCode 678+pattern RPL_TIMEONSERVERIS = ReplyCode 679+pattern RPL_NETWORKS = ReplyCode 682+pattern RPL_YOURLANGUAGEIS = ReplyCode 687+pattern RPL_LANGUAGE = ReplyCode 688+pattern RPL_WHOISSTAFF = ReplyCode 689+pattern RPL_WHOISLANGUAGE = ReplyCode 690+pattern RPL_MODLIST = ReplyCode 702+pattern RPL_ENDOFMODLIST = ReplyCode 703+pattern RPL_HELPSTART = ReplyCode 704+pattern RPL_HELPTXT = ReplyCode 705+pattern RPL_ENDOFHELP = ReplyCode 706+pattern ERR_TARGCHANGE = ReplyCode 707+pattern RPL_ETRACEFULL = ReplyCode 708+pattern RPL_ETRACE = ReplyCode 709+pattern RPL_KNOCK = ReplyCode 710+pattern RPL_KNOCKDLVR = ReplyCode 711+pattern ERR_TOOMANYKNOCK = ReplyCode 712+pattern ERR_CHANOPEN = ReplyCode 713+pattern ERR_KNOCKONCHAN = ReplyCode 714+pattern ERR_KNOCKDISABLED = ReplyCode 715+pattern RPL_TARGUMODEG = ReplyCode 716+pattern RPL_TARGNOTIFY = ReplyCode 717+pattern RPL_UMODEGMSG = ReplyCode 718+pattern RPL_OMOTDSTART = ReplyCode 720+pattern RPL_OMOTD = ReplyCode 721+pattern RPL_ENDOFOMOTD = ReplyCode 722+pattern ERR_NOPRIVS = ReplyCode 723+pattern RPL_TESTMASK = ReplyCode 724+pattern RPL_TESTLINE = ReplyCode 725+pattern RPL_NOTESTLINE = ReplyCode 726+pattern RPL_QUIETLIST = ReplyCode 728+pattern RPL_ENDOFQUIETLIST = ReplyCode 729+pattern RPL_MONONLINE = ReplyCode 730+pattern RPL_MONOFFLINE = ReplyCode 731+pattern RPL_MONLIST = ReplyCode 732+pattern RPL_ENDOFMONLIST = ReplyCode 733+pattern ERR_MONLISTFULL = ReplyCode 734+pattern RPL_RSACHALLENGE2 = ReplyCode 740+pattern RPL_ENDOFRSACHALLENGE2 = ReplyCode 741+pattern ERR_MLOCKRESTRICTED = ReplyCode 742+pattern RPL_SCANMATCHED = ReplyCode 750+pattern RPL_SCANUMODES = ReplyCode 751+pattern RPL_XINFO = ReplyCode 771+pattern RPL_XINFOSTART = ReplyCode 773+pattern RPL_XINFOEND = ReplyCode 774+pattern RPL_LOGGEDIN = ReplyCode 900+pattern RPL_LOGGEDOUT = ReplyCode 901+pattern RPL_NICKLOCKED = ReplyCode 902+pattern RPL_SASLSUCCESS = ReplyCode 903+pattern RPL_SASLFAIL = ReplyCode 904+pattern RPL_SASLTOOLONG = ReplyCode 905+pattern RPL_SASLABORTED = ReplyCode 906+pattern RPL_SASLALREADY = ReplyCode 907+pattern RPL_SASLMECHS = ReplyCode 908+pattern ERR_CANNOTDOCOMMAND = ReplyCode 972+pattern ERR_CANNOTCHANGEUMODE = ReplyCode 973+pattern ERR_CANNOTCHANGECHANMODE = ReplyCode 974+pattern ERR_CANNOTCHANGESERVERMODE = ReplyCode 975+pattern ERR_CANNOTSENDTONICK = ReplyCode 976+pattern ERR_UNKNOWNSERVERMODE = ReplyCode 977+pattern ERR_SERVERMODELOCK = ReplyCode 979+pattern ERR_BADCHARENCODING = ReplyCode 980+pattern ERR_TOOMANYLANGUAGES = ReplyCode 981+pattern ERR_NOLANGUAGE = ReplyCode 982+pattern ERR_TEXTTOOSHORT = ReplyCode 983+pattern ERR_NUMERIC_ERR = ReplyCode 999++data ReplyCodeInfo = ReplyCodeInfo+ { replyCodeType :: !ReplyType+ , replyCodeText :: !Text+ }++replyCodeInfo :: ReplyCode -> ReplyCodeInfo+replyCodeInfo (ReplyCode w) =+ case replyCodeInfoTable Vector.!? i of+ Nothing -> defaultReplyCodeInfo i+ Just info -> info+ where+ i = fromIntegral w++defaultReplyCodeInfo :: Int -> ReplyCodeInfo+defaultReplyCodeInfo = ReplyCodeInfo UnknownReply . Text.pack . show++replyCodeInfoTable :: Vector ReplyCodeInfo+replyCodeInfoTable+ = Vector.accumulate+ (\_def new -> new)+ (Vector.generate 1000 defaultReplyCodeInfo)+ $ fmap (\(ReplyCode code,info) -> (fromIntegral code, info))+ $ Vector.fromList+ [ (RPL_WELCOME , ReplyCodeInfo ClientServerReply "WELCOME")+ , (RPL_YOURHOST , ReplyCodeInfo ClientServerReply "YOURHOST")+ , (RPL_CREATED , ReplyCodeInfo ClientServerReply "CREATED")+ , (RPL_MYINFO , ReplyCodeInfo ClientServerReply "MYINFO")+ , (RPL_ISUPPORT , ReplyCodeInfo ClientServerReply "ISUPPORT")+ , (RPL_SNOMASK , ReplyCodeInfo ClientServerReply "SNOMASK")+ , (RPL_STATMEMTOT , ReplyCodeInfo ClientServerReply "STATMEMTOT")+ , (RPL_REDIR , ReplyCodeInfo ClientServerReply "REDIR")+ , (RPL_YOURCOOKIE , ReplyCodeInfo ClientServerReply "YOURCOOKIE")+ , (RPL_MAP , ReplyCodeInfo ClientServerReply "MAP")+ , (RPL_MAPEND , ReplyCodeInfo ClientServerReply "MAPEND")+ , (RPL_YOURID , ReplyCodeInfo ClientServerReply "YOURID")+ , (RPL_SAVENICK , ReplyCodeInfo ClientServerReply "SAVENICK")+ , (RPL_ATTEMPTINGJUNC , ReplyCodeInfo ClientServerReply "ATTEMPTINGJUNC")+ , (RPL_ATTEMPTINGREROUTE , ReplyCodeInfo ClientServerReply "ATTEMPTINGREROUTE")+ , (RPL_TRACELINK , ReplyCodeInfo CommandReply "TRACELINK")+ , (RPL_TRACECONNECTING , ReplyCodeInfo CommandReply "TRACECONNECTING")+ , (RPL_TRACEHANDSHAKE , ReplyCodeInfo CommandReply "TRACEHANDSHAKE")+ , (RPL_TRACEUNKNOWN , ReplyCodeInfo CommandReply "TRACEUNKNOWN")+ , (RPL_TRACEOPERATOR , ReplyCodeInfo CommandReply "TRACEOPERATOR")+ , (RPL_TRACEUSER , ReplyCodeInfo CommandReply "TRACEUSER")+ , (RPL_TRACESERVER , ReplyCodeInfo CommandReply "TRACESERVER")+ , (RPL_TRACESERVICE , ReplyCodeInfo CommandReply "TRACESERVICE")+ , (RPL_TRACENEWTYPE , ReplyCodeInfo CommandReply "TRACENEWTYPE")+ , (RPL_TRACECLASS , ReplyCodeInfo CommandReply "TRACECLASS")+ , (RPL_TRACERECONNECT , ReplyCodeInfo CommandReply "TRACERECONNECT")+ , (RPL_STATS , ReplyCodeInfo CommandReply "STATS")+ , (RPL_STATSLINKINFO , ReplyCodeInfo CommandReply "STATSLINKINFO")+ , (RPL_STATSCOMMANDS , ReplyCodeInfo CommandReply "STATSCOMMANDS")+ , (RPL_STATSCLINE , ReplyCodeInfo CommandReply "STATSCLINE")+ , (RPL_STATSNLINE , ReplyCodeInfo CommandReply "STATSNLINE")+ , (RPL_STATSILINE , ReplyCodeInfo CommandReply "STATSILINE")+ , (RPL_STATSKLINE , ReplyCodeInfo CommandReply "STATSKLINE")+ , (RPL_STATSQLINE , ReplyCodeInfo CommandReply "STATSQLINE")+ , (RPL_STATSYLINE , ReplyCodeInfo CommandReply "STATSYLINE")+ , (RPL_ENDOFSTATS , ReplyCodeInfo CommandReply "ENDOFSTATS")+ , (RPL_STATSPLINE , ReplyCodeInfo CommandReply "STATSPLINE")+ , (RPL_UMODEIS , ReplyCodeInfo CommandReply "UMODEIS")+ , (RPL_SQLINE_NICK , ReplyCodeInfo CommandReply "SQLINE_NICK")+ , (RPL_STATSDLINE , ReplyCodeInfo CommandReply "STATSDLINE")+ , (RPL_STATSZLINE , ReplyCodeInfo CommandReply "STATSZLINE")+ , (RPL_STATSCOUNT , ReplyCodeInfo CommandReply "STATSCOUNT")+ , (RPL_SERVICEINFO , ReplyCodeInfo CommandReply "SERVICEINFO")+ , (RPL_ENDOFSERVICES , ReplyCodeInfo CommandReply "ENDOFSERVICES")+ , (RPL_SERVICE , ReplyCodeInfo CommandReply "SERVICE")+ , (RPL_SERVLIST , ReplyCodeInfo CommandReply "SERVLIST")+ , (RPL_SERVLISTEND , ReplyCodeInfo CommandReply "SERVLISTEND")+ , (RPL_STATSVERBOSE , ReplyCodeInfo CommandReply "STATSVERBOSE")+ , (RPL_STATSIAUTH , ReplyCodeInfo CommandReply "STATSIAUTH")+ , (RPL_STATSLLINE , ReplyCodeInfo CommandReply "STATSLLINE")+ , (RPL_STATSUPTIME , ReplyCodeInfo CommandReply "STATSUPTIME")+ , (RPL_STATSOLINE , ReplyCodeInfo CommandReply "STATSOLINE")+ , (RPL_STATSHLINE , ReplyCodeInfo CommandReply "STATSHLINE")+ , (RPL_STATSSLINE , ReplyCodeInfo CommandReply "STATSSLINE")+ , (RPL_STATSPING , ReplyCodeInfo CommandReply "STATSPING")+ , (RPL_STATSXLINE , ReplyCodeInfo CommandReply "STATSXLINE")+ , (RPL_STATSULINE , ReplyCodeInfo CommandReply "STATSULINE")+ , (RPL_STATSDEBUG , ReplyCodeInfo CommandReply "STATSDEBUG")+ , (RPL_STATSCONN , ReplyCodeInfo CommandReply "STATSCONN")+ , (RPL_LUSERCLIENT , ReplyCodeInfo CommandReply "LUSERCLIENT")+ , (RPL_LUSEROP , ReplyCodeInfo CommandReply "LUSEROP")+ , (RPL_LUSERUNKNOWN , ReplyCodeInfo CommandReply "LUSERUNKNOWN")+ , (RPL_LUSERCHANNELS , ReplyCodeInfo CommandReply "LUSERCHANNELS")+ , (RPL_LUSERME , ReplyCodeInfo CommandReply "LUSERME")+ , (RPL_ADMINME , ReplyCodeInfo CommandReply "ADMINME")+ , (RPL_ADMINLOC1 , ReplyCodeInfo CommandReply "ADMINLOC1")+ , (RPL_ADMINLOC2 , ReplyCodeInfo CommandReply "ADMINLOC2")+ , (RPL_ADMINEMAIL , ReplyCodeInfo CommandReply "ADMINEMAIL")+ , (RPL_TRACELOG , ReplyCodeInfo CommandReply "TRACELOG")+ , (RPL_ENDOFTRACE , ReplyCodeInfo CommandReply "ENDOFTRACE")+ , (RPL_LOAD2HI , ReplyCodeInfo CommandReply "LOAD2HI")+ , (RPL_LOCALUSERS , ReplyCodeInfo CommandReply "LOCALUSERS")+ , (RPL_GLOBALUSERS , ReplyCodeInfo CommandReply "GLOBALUSERS")+ , (RPL_START_NETSTAT , ReplyCodeInfo CommandReply "START_NETSTAT")+ , (RPL_NETSTAT , ReplyCodeInfo CommandReply "NETSTAT")+ , (RPL_END_NETSTAT , ReplyCodeInfo CommandReply "END_NETSTAT")+ , (RPL_PRIVS , ReplyCodeInfo CommandReply "PRIVS")+ , (RPL_SILELIST , ReplyCodeInfo CommandReply "SILELIST")+ , (RPL_ENDOFSILELIST , ReplyCodeInfo CommandReply "ENDOFSILELIST")+ , (RPL_NOTIFY , ReplyCodeInfo CommandReply "NOTIFY")+ , (RPL_ENDNOTIFY , ReplyCodeInfo CommandReply "ENDNOTIFY")+ , (RPL_STATSDELTA , ReplyCodeInfo CommandReply "STATSDELTA")+ , (RPL_WHOISCERTFP , ReplyCodeInfo CommandReply "WHOISCERTFP")+ , (RPL_VCHANLIST , ReplyCodeInfo CommandReply "VCHANLIST")+ , (RPL_VCHANHELP , ReplyCodeInfo CommandReply "VCHANHELP")+ , (RPL_GLIST , ReplyCodeInfo CommandReply "GLIST")+ , (RPL_ACCEPTLIST , ReplyCodeInfo CommandReply "ACCEPTLIST")+ , (RPL_ENDOFACCEPT , ReplyCodeInfo CommandReply "ENDOFACCEPT")+ , (RPL_ENDOFJUPELIST , ReplyCodeInfo CommandReply "ENDOFJUPELIST")+ , (RPL_FEATURE , ReplyCodeInfo CommandReply "FEATURE")+ , (RPL_DATASTR , ReplyCodeInfo CommandReply "DATASTR")+ , (RPL_END_CHANINFO , ReplyCodeInfo CommandReply "END_CHANINFO")+ , (RPL_NONE , ReplyCodeInfo CommandReply "NONE")+ , (RPL_AWAY , ReplyCodeInfo CommandReply "AWAY")+ , (RPL_USERHOST , ReplyCodeInfo CommandReply "USERHOST")+ , (RPL_ISON , ReplyCodeInfo CommandReply "ISON")+ , (RPL_TEXT , ReplyCodeInfo CommandReply "TEXT")+ , (RPL_UNAWAY , ReplyCodeInfo CommandReply "UNAWAY")+ , (RPL_NOWAWAY , ReplyCodeInfo CommandReply "NOWAWAY")+ , (RPL_WHOISREGNICK , ReplyCodeInfo CommandReply "WHOISREGNICK")+ , (RPL_SUSERHOST , ReplyCodeInfo CommandReply "SUSERHOST")+ , (RPL_NOTIFYACTION , ReplyCodeInfo CommandReply "NOTIFYACTION")+ , (RPL_WHOISADMIN , ReplyCodeInfo CommandReply "WHOISADMIN")+ , (RPL_NICKTRACE , ReplyCodeInfo CommandReply "NICKTRACE")+ , (RPL_WHOISSADMIN , ReplyCodeInfo CommandReply "WHOISSADMIN")+ , (RPL_WHOISHELPER , ReplyCodeInfo CommandReply "WHOISHELPER")+ , (RPL_WHOISUSER , ReplyCodeInfo CommandReply "WHOISUSER")+ , (RPL_WHOISSERVER , ReplyCodeInfo CommandReply "WHOISSERVER")+ , (RPL_WHOISOPERATOR , ReplyCodeInfo CommandReply "WHOISOPERATOR")+ , (RPL_WHOWASUSER , ReplyCodeInfo CommandReply "WHOWASUSER")+ , (RPL_ENDOFWHO , ReplyCodeInfo CommandReply "ENDOFWHO")+ , (RPL_WHOISCHANOP , ReplyCodeInfo CommandReply "WHOISCHANOP")+ , (RPL_WHOISIDLE , ReplyCodeInfo CommandReply "WHOISIDLE")+ , (RPL_ENDOFWHOIS , ReplyCodeInfo CommandReply "ENDOFWHOIS")+ , (RPL_WHOISCHANNELS , ReplyCodeInfo CommandReply "WHOISCHANNELS")+ , (RPL_WHOISSPECIAL , ReplyCodeInfo CommandReply "WHOISSPECIAL")+ , (RPL_LISTSTART , ReplyCodeInfo CommandReply "LISTSTART")+ , (RPL_LIST , ReplyCodeInfo CommandReply "LIST")+ , (RPL_LISTEND , ReplyCodeInfo CommandReply "LISTEND")+ , (RPL_CHANNELMODEIS , ReplyCodeInfo CommandReply "CHANNELMODEIS")+ , (RPL_CHANNELMLOCKIS , ReplyCodeInfo CommandReply "CHANNELMLOCKIS")+ , (RPL_NOCHANPASS , ReplyCodeInfo CommandReply "NOCHANPASS")+ , (RPL_CHPASSUNKNOWN , ReplyCodeInfo CommandReply "CHPASSUNKNOWN")+ , (RPL_CHANNEL_URL , ReplyCodeInfo CommandReply "CHANNEL_URL")+ , (RPL_CREATIONTIME , ReplyCodeInfo CommandReply "CREATIONTIME")+ , (RPL_WHOWAS_TIME , ReplyCodeInfo CommandReply "WHOWAS_TIME")+ , (RPL_WHOISACCOUNT , ReplyCodeInfo CommandReply "WHOISACCOUNT")+ , (RPL_NOTOPIC , ReplyCodeInfo CommandReply "NOTOPIC")+ , (RPL_TOPIC , ReplyCodeInfo CommandReply "TOPIC")+ , (RPL_TOPICWHOTIME , ReplyCodeInfo CommandReply "TOPICWHOTIME")+ , (RPL_LISTUSAGE , ReplyCodeInfo CommandReply "LISTUSAGE")+ , (RPL_COMMANDSYNTAX , ReplyCodeInfo CommandReply "COMMANDSYNTAX")+ , (RPL_LISTSYNTAX , ReplyCodeInfo CommandReply "LISTSYNTAX")+ , (RPL_WHOISACTUALLY , ReplyCodeInfo CommandReply "WHOISACTUALLY")+ , (RPL_BADCHANPASS , ReplyCodeInfo CommandReply "BADCHANPASS")+ , (RPL_INVITING , ReplyCodeInfo CommandReply "INVITING")+ , (RPL_SUMMONING , ReplyCodeInfo CommandReply "SUMMONING")+ , (RPL_INVITED , ReplyCodeInfo CommandReply "INVITED")+ , (RPL_INVEXLIST , ReplyCodeInfo CommandReply "INVEXLIST")+ , (RPL_ENDOFINVEXLIST , ReplyCodeInfo CommandReply "ENDOFINVEXLIST")+ , (RPL_EXCEPTLIST , ReplyCodeInfo CommandReply "EXCEPTLIST")+ , (RPL_ENDOFEXCEPTLIST , ReplyCodeInfo CommandReply "ENDOFEXCEPTLIST")+ , (RPL_VERSION , ReplyCodeInfo CommandReply "VERSION")+ , (RPL_WHOREPLY , ReplyCodeInfo CommandReply "WHOREPLY")+ , (RPL_NAMREPLY , ReplyCodeInfo CommandReply "NAMREPLY")+ , (RPL_WHOSPCRPL , ReplyCodeInfo CommandReply "WHOSPCRPL")+ , (RPL_NAMREPLY_ , ReplyCodeInfo CommandReply "NAMREPLY_")+ , (RPL_WHOWASREAL , ReplyCodeInfo CommandReply "WHOWASREAL")+ , (RPL_KILLDONE , ReplyCodeInfo CommandReply "KILLDONE")+ , (RPL_CLOSING , ReplyCodeInfo CommandReply "CLOSING")+ , (RPL_CLOSEEND , ReplyCodeInfo CommandReply "CLOSEEND")+ , (RPL_LINKS , ReplyCodeInfo CommandReply "LINKS")+ , (RPL_ENDOFLINKS , ReplyCodeInfo CommandReply "ENDOFLINKS")+ , (RPL_ENDOFNAMES , ReplyCodeInfo CommandReply "ENDOFNAMES")+ , (RPL_BANLIST , ReplyCodeInfo CommandReply "BANLIST")+ , (RPL_ENDOFBANLIST , ReplyCodeInfo CommandReply "ENDOFBANLIST")+ , (RPL_ENDOFWHOWAS , ReplyCodeInfo CommandReply "ENDOFWHOWAS")+ , (RPL_INFO , ReplyCodeInfo CommandReply "INFO")+ , (RPL_MOTD , ReplyCodeInfo CommandReply "MOTD")+ , (RPL_INFOSTART , ReplyCodeInfo CommandReply "INFOSTART")+ , (RPL_ENDOFINFO , ReplyCodeInfo CommandReply "ENDOFINFO")+ , (RPL_MOTDSTART , ReplyCodeInfo CommandReply "MOTDSTART")+ , (RPL_ENDOFMOTD , ReplyCodeInfo CommandReply "ENDOFMOTD")+ , (RPL_WHOISHOST , ReplyCodeInfo CommandReply "WHOISHOST")+ , (RPL_KICKLINKED , ReplyCodeInfo CommandReply "KICKLINKED")+ , (RPL_YOUREOPER , ReplyCodeInfo CommandReply "YOUREOPER")+ , (RPL_REHASHING , ReplyCodeInfo CommandReply "REHASHING")+ , (RPL_YOURESERVICE , ReplyCodeInfo CommandReply "YOURESERVICE")+ , (RPL_MYPORTIS , ReplyCodeInfo CommandReply "MYPORTIS")+ , (RPL_NOTOPERANYMORE , ReplyCodeInfo CommandReply "NOTOPERANYMORE")+ , (RPL_RSACHALLENGE , ReplyCodeInfo CommandReply "RSACHALLENGE")+ , (RPL_TIME , ReplyCodeInfo CommandReply "TIME")+ , (RPL_USERSSTART , ReplyCodeInfo CommandReply "USERSSTART")+ , (RPL_USERS , ReplyCodeInfo CommandReply "USERS")+ , (RPL_ENDOFUSERS , ReplyCodeInfo CommandReply "ENDOFUSERS")+ , (RPL_NOUSERS , ReplyCodeInfo CommandReply "NOUSERS")+ , (RPL_HOSTHIDDEN , ReplyCodeInfo CommandReply "HOSTHIDDEN")+ , (ERR_UNKNOWNERROR , ReplyCodeInfo ErrorReply "UNKNOWNERROR")+ , (ERR_NOSUCHNICK , ReplyCodeInfo ErrorReply "NOSUCHNICK")+ , (ERR_NOSUCHSERVER , ReplyCodeInfo ErrorReply "NOSUCHSERVER")+ , (ERR_NOSUCHCHANNEL , ReplyCodeInfo ErrorReply "NOSUCHCHANNEL")+ , (ERR_CANNOTSENDTOCHAN , ReplyCodeInfo ErrorReply "CANNOTSENDTOCHAN")+ , (ERR_TOOMANYCHANNELS , ReplyCodeInfo ErrorReply "TOOMANYCHANNELS")+ , (ERR_WASNOSUCHNICK , ReplyCodeInfo ErrorReply "WASNOSUCHNICK")+ , (ERR_TOOMANYTARGETS , ReplyCodeInfo ErrorReply "TOOMANYTARGETS")+ , (ERR_NOORIGIN , ReplyCodeInfo ErrorReply "NOORIGIN")+ , (ERR_NORECIPIENT , ReplyCodeInfo ErrorReply "NORECIPIENT")+ , (ERR_NOTEXTTOSEND , ReplyCodeInfo ErrorReply "NOTEXTTOSEND")+ , (ERR_NOTOPLEVEL , ReplyCodeInfo ErrorReply "NOTOPLEVEL")+ , (ERR_WILDTOPLEVEL , ReplyCodeInfo ErrorReply "WILDTOPLEVEL")+ , (ERR_BADMASK , ReplyCodeInfo ErrorReply "BADMASK")+ , (ERR_TOOMANYMATCHES , ReplyCodeInfo ErrorReply "TOOMANYMATCHES")+ , (ERR_LENGTHTRUNCATED , ReplyCodeInfo ErrorReply "LENGTHTRUNCATED")+ , (ERR_UNKNOWNCOMMAND , ReplyCodeInfo ErrorReply "UNKNOWNCOMMAND")+ , (ERR_NOMOTD , ReplyCodeInfo ErrorReply "NOMOTD")+ , (ERR_NOADMININFO , ReplyCodeInfo ErrorReply "NOADMININFO")+ , (ERR_FILEERROR , ReplyCodeInfo ErrorReply "FILEERROR")+ , (ERR_NOOPERMOTD , ReplyCodeInfo ErrorReply "NOOPERMOTD")+ , (ERR_TOOMANYAWAY , ReplyCodeInfo ErrorReply "TOOMANYAWAY")+ , (ERR_EVENTNICKCHANGE , ReplyCodeInfo ErrorReply "EVENTNICKCHANGE")+ , (ERR_NONICKNAMEGIVEN , ReplyCodeInfo ErrorReply "NONICKNAMEGIVEN")+ , (ERR_ERRONEUSNICKNAME , ReplyCodeInfo ErrorReply "ERRONEUSNICKNAME")+ , (ERR_NICKNAMEINUSE , ReplyCodeInfo ErrorReply "NICKNAMEINUSE")+ , (ERR_SERVICENAMEINUSE , ReplyCodeInfo ErrorReply "SERVICENAMEINUSE")+ , (ERR_NORULES , ReplyCodeInfo ErrorReply "NORULES")+ , (ERR_BANNICKCHANGE , ReplyCodeInfo ErrorReply "BANNICKCHANGE")+ , (ERR_NICKCOLLISION , ReplyCodeInfo ErrorReply "NICKCOLLISION")+ , (ERR_UNAVAILRESOURCE , ReplyCodeInfo ErrorReply "UNAVAILRESOURCE")+ , (ERR_NICKTOOFAST , ReplyCodeInfo ErrorReply "NICKTOOFAST")+ , (ERR_TARGETTOOFAST , ReplyCodeInfo ErrorReply "TARGETTOOFAST")+ , (ERR_SERVICESDOWN , ReplyCodeInfo ErrorReply "SERVICESDOWN")+ , (ERR_USERNOTINCHANNEL , ReplyCodeInfo ErrorReply "USERNOTINCHANNEL")+ , (ERR_NOTONCHANNEL , ReplyCodeInfo ErrorReply "NOTONCHANNEL")+ , (ERR_USERONCHANNEL , ReplyCodeInfo ErrorReply "USERONCHANNEL")+ , (ERR_NOLOGIN , ReplyCodeInfo ErrorReply "NOLOGIN")+ , (ERR_SUMMONDISABLED , ReplyCodeInfo ErrorReply "SUMMONDISABLED")+ , (ERR_USERSDISABLED , ReplyCodeInfo ErrorReply "USERSDISABLED")+ , (ERR_NONICKCHANGE , ReplyCodeInfo ErrorReply "NONICKCHANGE")+ , (ERR_NOTIMPLEMENTED , ReplyCodeInfo ErrorReply "NOTIMPLEMENTED")+ , (ERR_NOTREGISTERED , ReplyCodeInfo ErrorReply "NOTREGISTERED")+ , (ERR_IDCOLLISION , ReplyCodeInfo ErrorReply "IDCOLLISION")+ , (ERR_NICKLOST , ReplyCodeInfo ErrorReply "NICKLOST")+ , (ERR_HOSTILENAME , ReplyCodeInfo ErrorReply "HOSTILENAME")+ , (ERR_ACCEPTFULL , ReplyCodeInfo ErrorReply "ACCEPTFULL")+ , (ERR_ACCEPTEXIST , ReplyCodeInfo ErrorReply "ACCEPTEXIST")+ , (ERR_ACCEPTNOT , ReplyCodeInfo ErrorReply "ACCEPTNOT")+ , (ERR_NOHIDING , ReplyCodeInfo ErrorReply "NOHIDING")+ , (ERR_NOTFORHALFOPS , ReplyCodeInfo ErrorReply "NOTFORHALFOPS")+ , (ERR_NEEDMOREPARAMS , ReplyCodeInfo ErrorReply "NEEDMOREPARAMS")+ , (ERR_ALREADYREGISTERED , ReplyCodeInfo ErrorReply "ALREADYREGISTERED")+ , (ERR_NOPERMFORHOST , ReplyCodeInfo ErrorReply "NOPERMFORHOST")+ , (ERR_PASSWDMISMATCH , ReplyCodeInfo ErrorReply "PASSWDMISMATCH")+ , (ERR_YOUREBANNEDCREEP , ReplyCodeInfo ErrorReply "YOUREBANNEDCREEP")+ , (ERR_YOUWILLBEBANNED , ReplyCodeInfo ErrorReply "YOUWILLBEBANNED")+ , (ERR_KEYSET , ReplyCodeInfo ErrorReply "KEYSET")+ , (ERR_INVALIDUSERNAME , ReplyCodeInfo ErrorReply "INVALIDUSERNAME")+ , (ERR_ONLYSERVERSCANCHANGE , ReplyCodeInfo ErrorReply "ONLYSERVERSCANCHANGE")+ , (ERR_LINKSET , ReplyCodeInfo ErrorReply "LINKSET")+ , (ERR_LINKCHANNEL , ReplyCodeInfo ErrorReply "LINKCHANNEL")+ , (ERR_CHANNELISFULL , ReplyCodeInfo ErrorReply "CHANNELISFULL")+ , (ERR_UNKNOWNMODE , ReplyCodeInfo ErrorReply "UNKNOWNMODE")+ , (ERR_INVITEONLYCHAN , ReplyCodeInfo ErrorReply "INVITEONLYCHAN")+ , (ERR_BANNEDFROMCHAN , ReplyCodeInfo ErrorReply "BANNEDFROMCHAN")+ , (ERR_BADCHANNELKEY , ReplyCodeInfo ErrorReply "BADCHANNELKEY")+ , (ERR_BADCHANMASK , ReplyCodeInfo ErrorReply "BADCHANMASK")+ , (ERR_NEEDREGGEDNICK , ReplyCodeInfo ErrorReply "NEEDREGGEDNICK")+ , (ERR_BANLISTFULL , ReplyCodeInfo ErrorReply "BANLISTFULL")+ , (ERR_BADCHANNAME , ReplyCodeInfo ErrorReply "BADCHANNAME")+ , (ERR_THROTTLE , ReplyCodeInfo ErrorReply "THROTTLE")+ , (ERR_NOPRIVILEGES , ReplyCodeInfo ErrorReply "NOPRIVILEGES")+ , (ERR_CHANOPRIVSNEEDED , ReplyCodeInfo ErrorReply "CHANOPRIVSNEEDED")+ , (ERR_CANTKILLSERVER , ReplyCodeInfo ErrorReply "CANTKILLSERVER")+ , (ERR_ISCHANSERVICE , ReplyCodeInfo ErrorReply "ISCHANSERVICE")+ , (ERR_BANNEDNICK , ReplyCodeInfo ErrorReply "BANNEDNICK")+ , (ERR_NONONREG , ReplyCodeInfo ErrorReply "NONONREG")+ , (ERR_TSLESSCHAN , ReplyCodeInfo ErrorReply "TSLESSCHAN")+ , (ERR_VOICENEEDED , ReplyCodeInfo ErrorReply "VOICENEEDED")+ , (ERR_NOOPERHOST , ReplyCodeInfo ErrorReply "NOOPERHOST")+ , (ERR_NOSERVICEHOST , ReplyCodeInfo ErrorReply "NOSERVICEHOST")+ , (ERR_NOFEATURE , ReplyCodeInfo ErrorReply "NOFEATURE")+ , (ERR_OWNMODE , ReplyCodeInfo ErrorReply "OWNMODE")+ , (ERR_BADLOGTYPE , ReplyCodeInfo ErrorReply "BADLOGTYPE")+ , (ERR_BADLOGSYS , ReplyCodeInfo ErrorReply "BADLOGSYS")+ , (ERR_BADLOGVALUE , ReplyCodeInfo ErrorReply "BADLOGVALUE")+ , (ERR_ISOPERLCHAN , ReplyCodeInfo ErrorReply "ISOPERLCHAN")+ , (ERR_CHANOWNPRIVNEEDED , ReplyCodeInfo ErrorReply "CHANOWNPRIVNEEDED")+ , (ERR_UMODEUNKNOWNFLAG , ReplyCodeInfo ErrorReply "UMODEUNKNOWNFLAG")+ , (ERR_USERSDONTMATCH , ReplyCodeInfo ErrorReply "USERSDONTMATCH")+ , (ERR_GHOSTEDCLIENT , ReplyCodeInfo ErrorReply "GHOSTEDCLIENT")+ , (ERR_USERNOTONSERV , ReplyCodeInfo ErrorReply "USERNOTONSERV")+ , (ERR_SILELISTFULL , ReplyCodeInfo ErrorReply "SILELISTFULL")+ , (ERR_TOOMANYWATCH , ReplyCodeInfo ErrorReply "TOOMANYWATCH")+ , (ERR_WRONGPONG , ReplyCodeInfo ErrorReply "WRONGPONG")+ , (ERR_BADEXPIRE , ReplyCodeInfo ErrorReply "BADEXPIRE")+ , (ERR_DONTCHEAT , ReplyCodeInfo ErrorReply "DONTCHEAT")+ , (ERR_DISABLED , ReplyCodeInfo ErrorReply "DISABLED")+ , (ERR_NOINVITE , ReplyCodeInfo ErrorReply "NOINVITE")+ , (ERR_LONGMASK , ReplyCodeInfo ErrorReply "LONGMASK")+ , (ERR_ADMONLY , ReplyCodeInfo ErrorReply "ADMONLY")+ , (ERR_TOOMANYUSERS , ReplyCodeInfo ErrorReply "TOOMANYUSERS")+ , (ERR_OPERONLY , ReplyCodeInfo ErrorReply "OPERONLY")+ , (ERR_MASKTOOWIDE , ReplyCodeInfo ErrorReply "MASKTOOWIDE")+ , (ERR_WHOTRUNC , ReplyCodeInfo ErrorReply "WHOTRUNC")+ , (ERR_LISTSYNTAX , ReplyCodeInfo ErrorReply "LISTSYNTAX")+ , (ERR_WHOSYNTAX , ReplyCodeInfo ErrorReply "WHOSYNTAX")+ , (ERR_WHOLIMEXCEED , ReplyCodeInfo ErrorReply "WHOLIMEXCEED")+ , (ERR_HELPNOTFOUND , ReplyCodeInfo ErrorReply "HELPNOTFOUND")+ , (ERR_REMOTEPFX , ReplyCodeInfo ErrorReply "REMOTEPFX")+ , (ERR_PFXUNROUTABLE , ReplyCodeInfo ErrorReply "PFXUNROUTABLE")+ , (ERR_BADHOSTMASK , ReplyCodeInfo ErrorReply "BADHOSTMASK")+ , (ERR_HOSTUNAVAIL , ReplyCodeInfo ErrorReply "HOSTUNAVAIL")+ , (ERR_USINGSLINE , ReplyCodeInfo ErrorReply "USINGSLINE")+ , (ERR_STATSSLINE , ReplyCodeInfo ErrorReply "STATSSLINE")+ , (RPL_LOGON , ReplyCodeInfo CommandReply "LOGON")+ , (RPL_LOGOFF , ReplyCodeInfo CommandReply "LOGOFF")+ , (RPL_WATCHOFF , ReplyCodeInfo CommandReply "WATCHOFF")+ , (RPL_WATCHSTAT , ReplyCodeInfo CommandReply "WATCHSTAT")+ , (RPL_NOWON , ReplyCodeInfo CommandReply "NOWON")+ , (RPL_NOWOFF , ReplyCodeInfo CommandReply "NOWOFF")+ , (RPL_WATCHLIST , ReplyCodeInfo CommandReply "WATCHLIST")+ , (RPL_ENDOFWATCHLIST , ReplyCodeInfo CommandReply "ENDOFWATCHLIST")+ , (RPL_WATCHCLEAR , ReplyCodeInfo CommandReply "WATCHCLEAR")+ , (RPL_ISOPER , ReplyCodeInfo CommandReply "ISOPER")+ , (RPL_ISLOCOP , ReplyCodeInfo CommandReply "ISLOCOP")+ , (RPL_ISNOTOPER , ReplyCodeInfo CommandReply "ISNOTOPER")+ , (RPL_ENDOFISOPER , ReplyCodeInfo CommandReply "ENDOFISOPER")+ , (RPL_DCCSTATUS , ReplyCodeInfo CommandReply "DCCSTATUS")+ , (RPL_DCCLIST , ReplyCodeInfo CommandReply "DCCLIST")+ , (RPL_ENDOFDCCLIST , ReplyCodeInfo CommandReply "ENDOFDCCLIST")+ , (RPL_WHOWASHOST , ReplyCodeInfo CommandReply "WHOWASHOST")+ , (RPL_DCCINFO , ReplyCodeInfo CommandReply "DCCINFO")+ , (RPL_RULES , ReplyCodeInfo CommandReply "RULES")+ , (RPL_ENDOFO , ReplyCodeInfo CommandReply "ENDOFO")+ , (RPL_SETTINGS , ReplyCodeInfo CommandReply "SETTINGS")+ , (RPL_ENDOFSETTINGS , ReplyCodeInfo CommandReply "ENDOFSETTINGS")+ , (RPL_DUMPING , ReplyCodeInfo CommandReply "DUMPING")+ , (RPL_DUMPRPL , ReplyCodeInfo CommandReply "DUMPRPL")+ , (RPL_EODUMP , ReplyCodeInfo CommandReply "EODUMP")+ , (RPL_TRACEROUTE_HOP , ReplyCodeInfo CommandReply "TRACEROUTE_HOP")+ , (RPL_TRACEROUTE_START , ReplyCodeInfo CommandReply "TRACEROUTE_START")+ , (RPL_MODECHANGEWARN , ReplyCodeInfo CommandReply "MODECHANGEWARN")+ , (RPL_CHANREDIR , ReplyCodeInfo CommandReply "CHANREDIR")+ , (RPL_SERVMODEIS , ReplyCodeInfo CommandReply "SERVMODEIS")+ , (RPL_OTHERUMODEIS , ReplyCodeInfo CommandReply "OTHERUMODEIS")+ , (RPL_ENDOF_GENERIC , ReplyCodeInfo CommandReply "ENDOF_GENERIC")+ , (RPL_WHOWASDETAILS , ReplyCodeInfo CommandReply "WHOWASDETAILS")+ , (RPL_WHOISSECURE , ReplyCodeInfo CommandReply "WHOISSECURE")+ , (RPL_UNKNOWNMODES , ReplyCodeInfo CommandReply "UNKNOWNMODES")+ , (RPL_CANNOTSETMODES , ReplyCodeInfo CommandReply "CANNOTSETMODES")+ , (RPL_LUSERSTAFF , ReplyCodeInfo CommandReply "LUSERSTAFF")+ , (RPL_TIMEONSERVERIS , ReplyCodeInfo CommandReply "TIMEONSERVERIS")+ , (RPL_NETWORKS , ReplyCodeInfo CommandReply "NETWORKS")+ , (RPL_YOURLANGUAGEIS , ReplyCodeInfo CommandReply "YOURLANGUAGEIS")+ , (RPL_LANGUAGE , ReplyCodeInfo CommandReply "LANGUAGE")+ , (RPL_WHOISSTAFF , ReplyCodeInfo CommandReply "WHOISSTAFF")+ , (RPL_WHOISLANGUAGE , ReplyCodeInfo CommandReply "WHOISLANGUAGE")+ , (RPL_MODLIST , ReplyCodeInfo CommandReply "MODLIST")+ , (RPL_ENDOFMODLIST , ReplyCodeInfo CommandReply "ENDOFMODLIST")+ , (RPL_HELPSTART , ReplyCodeInfo CommandReply "HELPSTART")+ , (RPL_HELPTXT , ReplyCodeInfo CommandReply "HELPTXT")+ , (RPL_ENDOFHELP , ReplyCodeInfo CommandReply "ENDOFHELP")+ , (ERR_TARGCHANGE , ReplyCodeInfo ErrorReply "TARGCHANGE")+ , (RPL_ETRACEFULL , ReplyCodeInfo CommandReply "ETRACEFULL")+ , (RPL_ETRACE , ReplyCodeInfo CommandReply "ETRACE")+ , (RPL_KNOCK , ReplyCodeInfo CommandReply "KNOCK")+ , (RPL_KNOCKDLVR , ReplyCodeInfo CommandReply "KNOCKDLVR")+ , (ERR_TOOMANYKNOCK , ReplyCodeInfo ErrorReply "TOOMANYKNOCK")+ , (ERR_CHANOPEN , ReplyCodeInfo ErrorReply "CHANOPEN")+ , (ERR_KNOCKONCHAN , ReplyCodeInfo ErrorReply "KNOCKONCHAN")+ , (ERR_KNOCKDISABLED , ReplyCodeInfo ErrorReply "KNOCKDISABLED")+ , (RPL_TARGUMODEG , ReplyCodeInfo CommandReply "TARGUMODEG")+ , (RPL_TARGNOTIFY , ReplyCodeInfo CommandReply "TARGNOTIFY")+ , (RPL_UMODEGMSG , ReplyCodeInfo CommandReply "UMODEGMSG")+ , (RPL_OMOTDSTART , ReplyCodeInfo CommandReply "OMOTDSTART")+ , (RPL_OMOTD , ReplyCodeInfo CommandReply "OMOTD")+ , (RPL_ENDOFOMOTD , ReplyCodeInfo CommandReply "ENDOFOMOTD")+ , (ERR_NOPRIVS , ReplyCodeInfo ErrorReply "NOPRIVS")+ , (RPL_TESTMASK , ReplyCodeInfo CommandReply "TESTMASK")+ , (RPL_TESTLINE , ReplyCodeInfo CommandReply "TESTLINE")+ , (RPL_NOTESTLINE , ReplyCodeInfo CommandReply "NOTESTLINE")+ , (RPL_QUIETLIST , ReplyCodeInfo CommandReply "QUIETLIST")+ , (RPL_ENDOFQUIETLIST , ReplyCodeInfo CommandReply "ENDOFQUIETLIST")+ , (RPL_MONONLINE , ReplyCodeInfo CommandReply "MONONLINE")+ , (RPL_MONOFFLINE , ReplyCodeInfo CommandReply "MONOFFLINE")+ , (RPL_MONLIST , ReplyCodeInfo CommandReply "MONLIST")+ , (RPL_ENDOFMONLIST , ReplyCodeInfo CommandReply "ENDOFMONLIST")+ , (ERR_MONLISTFULL , ReplyCodeInfo ErrorReply "MONLISTFULL")+ , (RPL_RSACHALLENGE2 , ReplyCodeInfo CommandReply "RSACHALLENGE2")+ , (RPL_ENDOFRSACHALLENGE2 , ReplyCodeInfo CommandReply "ENDOFRSACHALLENGE2")+ , (ERR_MLOCKRESTRICTED , ReplyCodeInfo ErrorReply "MLOCKRESTRICTED")+ , (RPL_SCANMATCHED , ReplyCodeInfo CommandReply "SCANMATCHED")+ , (RPL_SCANUMODES , ReplyCodeInfo CommandReply "SCANUMODES")+ , (RPL_XINFO , ReplyCodeInfo CommandReply "XINFO")+ , (RPL_XINFOSTART , ReplyCodeInfo CommandReply "XINFOSTART")+ , (RPL_XINFOEND , ReplyCodeInfo CommandReply "XINFOEND")+ , (RPL_LOGGEDIN , ReplyCodeInfo CommandReply "LOGGEDIN")+ , (RPL_LOGGEDOUT , ReplyCodeInfo CommandReply "LOGGEDOUT")+ , (RPL_NICKLOCKED , ReplyCodeInfo CommandReply "NICKLOCKED")+ , (RPL_SASLSUCCESS , ReplyCodeInfo CommandReply "SASLSUCCESS")+ , (RPL_SASLFAIL , ReplyCodeInfo CommandReply "SASLFAIL")+ , (RPL_SASLTOOLONG , ReplyCodeInfo CommandReply "SASLTOOLONG")+ , (RPL_SASLABORTED , ReplyCodeInfo CommandReply "SASLABORTED")+ , (RPL_SASLALREADY , ReplyCodeInfo CommandReply "SASLALREADY")+ , (RPL_SASLMECHS , ReplyCodeInfo CommandReply "SASLMECHS")+ , (ERR_CANNOTDOCOMMAND , ReplyCodeInfo ErrorReply "CANNOTDOCOMMAND")+ , (ERR_CANNOTCHANGEUMODE , ReplyCodeInfo ErrorReply "CANNOTCHANGEUMODE")+ , (ERR_CANNOTCHANGECHANMODE , ReplyCodeInfo ErrorReply "CANNOTCHANGECHANMODE")+ , (ERR_CANNOTCHANGESERVERMODE, ReplyCodeInfo ErrorReply "CANNOTCHANGESERVERMODE")+ , (ERR_CANNOTSENDTONICK , ReplyCodeInfo ErrorReply "CANNOTSENDTONICK")+ , (ERR_UNKNOWNSERVERMODE , ReplyCodeInfo ErrorReply "UNKNOWNSERVERMODE")+ , (ERR_SERVERMODELOCK , ReplyCodeInfo ErrorReply "SERVERMODELOCK")+ , (ERR_BADCHARENCODING , ReplyCodeInfo ErrorReply "BADCHARENCODING")+ , (ERR_TOOMANYLANGUAGES , ReplyCodeInfo ErrorReply "TOOMANYLANGUAGES")+ , (ERR_NOLANGUAGE , ReplyCodeInfo ErrorReply "NOLANGUAGE")+ , (ERR_TEXTTOOSHORT , ReplyCodeInfo ErrorReply "TEXTTOOSHORT")+ , (ERR_NUMERIC_ERR , ReplyCodeInfo ErrorReply "NUMERIC_ERR")+ ]
src/Irc/Commands.hs view
@@ -28,12 +28,19 @@ , ircWho , ircWhois , ircWhowas++ -- * SASL support+ , ircAuthenticate+ , plainAuthenticationMode+ , encodePlainAuthentication ) where import Irc.RawIrcMsg import Irc.Identifier import Data.Text (Text) import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.ByteArray.Encoding as Enc -- | PRIVMSG command ircPrivmsg ::@@ -167,3 +174,19 @@ -- | CAP LS command ircCapLs :: RawIrcMsg ircCapLs = rawIrcMsg "CAP" ["LS"]++ircAuthenticate :: Text -> RawIrcMsg+ircAuthenticate msg = rawIrcMsg "AUTHENTICATE" [msg]++plainAuthenticationMode :: Text+plainAuthenticationMode = "PLAIN"++encodePlainAuthentication ::+ Text {- ^ username -} ->+ Text {- ^ password -} ->+ Text+encodePlainAuthentication user pass+ = Text.decodeUtf8+ $ Enc.convertToBase Enc.Base64+ $ Text.encodeUtf8+ $ Text.intercalate "\0" [user,user,pass]
src/Irc/Message.hs view
@@ -39,10 +39,11 @@ import Irc.Identifier import Irc.RawIrcMsg import Irc.UserInfo+import Irc.Codes data IrcMsg = UnknownMsg RawIrcMsg- | Reply Int [Text]+ | Reply ReplyCode [Text] | Nick UserInfo Identifier | Join UserInfo Identifier | Part UserInfo Identifier (Maybe Text)@@ -53,6 +54,7 @@ | Action UserInfo Identifier Text -- ^ source target txt | Notice UserInfo Identifier Text -- ^ source target txt | Mode UserInfo Identifier [Text] -- ^ source target txt+ | Authenticate Text | Cap CapCmd [Text] | Ping [Text] | Pong [Text]@@ -81,11 +83,14 @@ cookIrcMsg msg = case view msgCommand msg of cmd | Right (n,"") <- decimal cmd ->- Reply n (view msgParams msg)+ Reply (ReplyCode n) (view msgParams msg) "CAP" | _target:cmdTxt:rest <- view msgParams msg , Just cmd <- cookCapCmd cmdTxt -> Cap cmd rest + "AUTHENTICATE" | x:_ <- view msgParams msg ->+ Authenticate x+ "PING" -> Ping (view msgParams msg) "PONG" -> Pong (view msgParams msg) @@ -161,6 +166,7 @@ | otherwise -> TargetWindow tgt Notice src tgt _ | tgt == me -> TargetWindow (userNick src) | otherwise -> TargetWindow tgt+ Authenticate{} -> TargetHidden Ping{} -> TargetHidden Pong{} -> TargetHidden Error{} -> TargetNetwork@@ -183,6 +189,7 @@ Action x _ _ -> Just x Notice x _ _ -> Just x Mode x _ _ -> Just x+ Authenticate{}-> Nothing Ping{} -> Nothing Pong{} -> Nothing Error{} -> Nothing@@ -194,7 +201,7 @@ ircMsgText msg = case msg of UnknownMsg raw -> Text.unwords (view msgCommand raw : view msgParams raw)- Reply n xs -> Text.unwords (Text.pack (show n) : xs)+ Reply (ReplyCode n) xs -> Text.unwords (Text.pack (show n) : xs) Nick x y -> Text.unwords [renderUserInfo x, idText y] Join x _ -> renderUserInfo x Part x _ mb -> Text.unwords (renderUserInfo x : maybeToList mb)@@ -209,6 +216,7 @@ Pong xs -> Text.unwords xs Cap _ xs -> Text.unwords xs Error t -> t+ Authenticate{} -> "" -- nickname = ( letter / special ) *8( letter / digit / special / "-" ) -- letter = %x41-5A / %x61-7A ; A-Z / a-z
src/Irc/RateLimit.hs view
@@ -18,7 +18,6 @@ module Irc.RateLimit ( RateLimit , newRateLimit- , newRateLimitDefault , tickRateLimit ) where @@ -33,11 +32,6 @@ , rateThreshold :: !Int -- ^ seconds , ratePenalty :: !Int -- ^ seconds }---- | Construct a new rate limit with the RFC 2813 specified--- 2 second penalty and 10 second threshold-newRateLimitDefault :: IO RateLimit-newRateLimitDefault = newRateLimit 2 12 -- | Construct a new rate limit with the given penalty and threshold. newRateLimit ::