diff --git a/client/client.go b/client/client.go index 65598f1..6dd55bb 100644 --- a/client/client.go +++ b/client/client.go @@ -68,7 +68,7 @@ type Client struct { ActiveChannel string // Active channel index - ChannelIndex int + ActiveChannelIndex int // Reference to the bubbletea program Tea *tea.Program @@ -136,7 +136,7 @@ func (c *Client) Register(nick string, password string, channel string) { Name: c.ActiveChannel, Users: make(map[string]User), }) - c.ChannelIndex = 1 + c.ActiveChannelIndex = 1 } } diff --git a/commands/commands.go b/commands/commands.go index 4c7d43f..7fb96a5 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -116,114 +116,260 @@ var UserPrefixes = map[string]bool{ /* --- Numeric Replies --- */ const ( - RPL_WELCOME = "001" - RPL_YOURHOST = "002" - RPL_CREATED = "003" - RPL_MYINFO = "004" - RPL_ISUPPORT = "005" - RPL_BOUNCE = "010" - RPL_UMODEIS = "221" - RPL_LUSERCLIENT = "251" - RPL_LUSEROP = "252" - RPL_LUSERUNKNOWN = "253" - RPL_LUSERCHANNELS = "254" - RPL_LUSERME = "255" - RPL_ADMINME = "256" - RPL_ADMINLOC1 = "257" - RPL_ADMINLOC2 = "258" - RPL_ADMINEMAIL = "259" - RPL_TRYAGAIN = "263" - RPL_LOCALUSERS = "265" - RPL_GLOBALUSERS = "266" - RPL_WHOISCERTFP = "276" - RPL_NONE = "300" - RPL_AWAY = "301" - RPL_USERHOST = "302" - RPL_ISON = "303" - RPL_UNAWAY = "305" - RPL_NOWAWAY = "306" - RPL_WHOISUSER = "311" - RPL_WHOISSERVER = "312" - RPL_WHOISOPERATOR = "313" - RPL_WHOWASUSER = "314" - RPL_WHOISIDLE = "317" - RPL_ENDOFWHOIS = "318" - RPL_WHOISCHANNELS = "319" - RPL_LISTSTART = "321" - RPL_LIST = "322" - RPL_LISTEND = "323" - RPL_CHANNELMODEIS = "324" - RPL_CREATIONTIME = "329" - RPL_NOTOPIC = "331" - RPL_TOPIC = "332" - RPL_TOPICWHOTIME = "333" - RPL_INVITING = "341" - RPL_INVITELIST = "346" - RPL_ENDOFINVITELIST = "347" - RPL_EXCEPTLIST = "348" - RPL_ENDOFEXCEPTLIST = "349" - RPL_VERSION = "351" - RPL_NAMREPLY = "353" - RPL_ENDOFNAMES = "366" - RPL_BANLIST = "367" - RPL_ENDOFBANLIST = "368" - RPL_ENDOFWHOWAS = "369" - RPL_MOTDSTART = "375" - RPL_MOTD = "372" - RPL_ENDOFMOTD = "376" - RPL_YOUREOPER = "381" - RPL_REHASHING = "382" + RPL_WELCOME = "001" // RFC2812 - Implemented + RPL_YOURHOST = "002" // RFC2812 - Implemented + RPL_CREATED = "003" // RFC2812 - Implemented + RPL_MYINFO = "004" // RFC2812 - Implemented + RPL_ISUPPORT = "005" // ??????? - Not Implemented (TODO:) + RPL_BOUNCE = "010" // ??????? - Not Implemented (TODO:) + RPL_TRACELINK = "200" // RFC1459 - Not Implemented (TODO:) + RPL_TRACECONNECTING = "201" // RFC1459 - Not Implemented (TODO:) + RPL_TRACEHANDSHAKE = "202" // RFC1459 - Not Implemented (TODO:) + RPL_TRACEUNKNOWN = "203" // RFC1459 - Not Implemented (TODO:) + RPL_TRACEOPERATOR = "204" // RFC1459 - Not Implemented (TODO:) + RPL_TRACEUSER = "205" // RFC1459 - Not Implemented (TODO:) + RPL_TRACESERVER = "206" // RFC1459 - Not Implemented (TODO:) + RPL_TRACESERVICE = "207" // RFC2812 - Not Implemented (TODO:) + RPL_TRACENEWTYPE = "208" // RFC1459 - Not Implemented (TODO:) + RPL_TRACECLASS = "209" // RFC2812 - Not Implemented (TODO:) + RPL_TRACERECONNECT = "210" // RFC2812 - Not Implemented - Deprecated - Has Conflicts (TODO:) + RPL_STATSLINKINFO = "211" // RFC1459 - Not Implemented (TODO:) + RPL_STATSCOMMANDS = "212" // RFC1459 - Not Implemented (TODO:) + RPL_STATSCLINE = "213" // RFC1459 - Not Implemented (TODO:) + RPL_STATSNLINE = "214" // RFC1459 - Not Implemented - Has Conflicts (TODO:) + RPL_STATSILINE = "215" // RFC1459 - Not Implemented (TODO:) + RPL_STATSKLINE = "216" // RFC1459 - Not Implemented (TODO:) + RPL_STATSQLINE = "217" // RFC1459 - Not Implemented - Has Conflicts (TODO:) + RPL_STATSYLINE = "218" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFSTATS = "219" // RFC1459 - Not Implemented (TODO:) + RPL_UMODEIS = "221" // RFC1459 - Not Implemented (TODO:) + RPL_SERVICEINFO = "231" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_ENDOFSERVICES = "232" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_SERVICE = "233" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_SERVLIST = "234" // RFC2812 - Not Implemented (TODO:) replaces 231 and 233 + RPL_SERVLISTEND = "235" // RFC2812 - Not Implemented (TODO:) replaces 232 + RPL_STATSVLINE = "240" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + RPL_STATSLLINE = "241" // RFC1459 - Not Implemented (TODO:) + RPL_STATSUPTIME = "242" // RFC1459 - Not Implemented (TODO:) + RPL_STATSOLINE = "243" // RFC1459 - Not Implemented (TODO:) + RPL_STATSHLINE = "244" // RFC1459 - Not Implemented (TODO:) + RPL_STATSPING = "246" // RFC2812 - Not Implemented - Deprecated (TODO:) + RPL_STATSBLINE = "247" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + RPL_STATSDLINE = "250" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + RPL_LUSERCLIENT = "251" // RFC1459 - Implemented + RPL_LUSEROP = "252" // RFC1459 - Implemented + RPL_LUSERUNKNOWN = "253" // RFC1459 - Implemented + RPL_LUSERCHANNELS = "254" // RFC1459 - Implemented + RPL_LUSERME = "255" // RFC1459 - Implemented + RPL_ADMINME = "256" // RFC1459 - Not Implemented (TODO:) + RPL_ADMINLOC1 = "257" // RFC1459 - Not Implemented (TODO:) + RPL_ADMINLOC2 = "258" // RFC1459 - Not Implemented (TODO:) + RPL_ADMINEMAIL = "259" // RFC1459 - Not Implemented (TODO:) + RPL_TRACELOG = "261" // RFC1459 - Not Implemented (TODO:) + RPL_TRACEEND = "262" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + RPL_TRYAGAIN = "263" // RFC2812 - Not Implemented (TODO:) + RPL_LOCALUSERS = "265" // aircd, Hybrid, Bahamut - Implemented + RPL_GLOBALUSERS = "266" // aircd, Hybird, Bahamut - Implemented + RPL_WHOISCERTFP = "276" // oftc-hybrid - Not Implemented - Has Conflicts (TODO:) + RPL_NONE = "300" // RFC1459 - Not Implemented (TODO:) + RPL_AWAY = "301" // RFC1459 - Not Implemented (TODO:) + RPL_USERHOST = "302" // RFC1459 - Not Implemented (TODO:) + RPL_ISON = "303" // RFC1459 - Not Implemented (TODO:) + RPL_TEXT = "304" // irc2 - Not Implemented (TODO:) + RPL_UNAWAY = "305" // RFC1459 - Not Implemented (TODO:) + RPL_NOWAWAY = "306" // RFC1459 - Not Implemented (TODO:) + RPL_WHOISUSER = "311" // RFC1459 - Not Implemented (TODO:) + RPL_WHOISSERVER = "312" // RFC1459 - Not Implemented (TODO:) + RPL_WHOISOPERATOR = "313" // RFC1459 - Not Implemented (TODO:) + RPL_WHOWASUSER = "314" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFWHO = "315" // RFC1459 - Not Implemented (TODO:) + RPL_WHOISIDLE = "317" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFWHOIS = "318" // RFC1459 - Not Implemented (TODO:) + RPL_WHOISCHANNELS = "319" // RFC1459 - Not Implemented (TODO:) + RPL_LISTSTART = "321" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_LIST = "322" // RFC1459 - Not Implemented (TODO:) + RPL_LISTEND = "323" // RFC1459 - Not Implemented (TODO:) + RPL_CHANNELMODEIS = "324" // RFC1459 - Not Implemented (TODO:) + RPL_UNIQOPIS = "325" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + RPL_CREATIONTIME = "329" // Bahamut,InspIRCd - Not Implemented (TODO:) + RPL_NOTOPIC = "331" // RFC1459 - Not Implemented (TODO:) + RPL_TOPIC = "332" // RFC1459 - Not Implemented (TODO:) + RPL_TOPICWHOTIME = "333" // ircu,InspIRCd - Not Implemented (TODO:) + RPL_INVITING = "341" // RFC1459 - Not Implemented (TODO:) + RPL_SUMMONING = "342" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_INVITELIST = "346" // RFC2812 - Not Implemented (TODO:) + RPL_ENDOFINVITELIST = "347" // RFC2812 - Not Implemented (TODO:) + RPL_EXCEPTLIST = "348" // RFC2812 - Not Implemented (TODO:) + RPL_ENDOFEXCEPTLIST = "349" // RFC2812 - Not Implemented (TODO:) + RPL_WHOISGATEWAY = "350" // InspIRCd - Not Implemented (TODO:) + RPL_VERSION = "351" // RFC1459 - Not Implemented (TODO:) + RPL_WHOREPLY = "352" // RFC1459 - Not Implemented (TODO:) + RPL_NAMREPLY = "353" // RFC1459 - Implemented + RPL_KILLDONE = "361" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_CLOSING = "362" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_CLOSEEND = "363" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_LINKS = "364" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFLINKS = "365" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFNAMES = "366" // RFC1459 - Not Implemented (TODO:) + RPL_BANLIST = "367" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFBANLIST = "368" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFWHOWAS = "369" // RFC1459 - Not Implemented (TODO:) + RPL_INFO = "371" // RFC1459 - Not Implemented (TODO:) + RPL_MOTD = "372" // RFC1459 - Implemented + RPL_INFOSTART = "373" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_ENDOFINFO = "374" // RFC1459 - Not Implemented (TODO:) + RPL_MOTDSTART = "375" // RFC1459 - Implemented + RPL_ENDOFMOTD = "376" // RFC1459 - Not Implemented (TODO:) + RPL_YOUREOPER = "381" // RFC1459 - Not Implemented (TODO:) + RPL_REHASHING = "382" // RFC1459 - Not Implemented (TODO:) + RPL_YOURSERVICE = "383" // RFC2812 - Not Implemented (TODO:) + RPL_MYPORTIS = "384" // RFC1459 - Not Implemented - Deprecated (TODO:) + RPL_TIME = "391" // RFC1459 - Not Implemented - Has Conflicts (TODO:) + RPL_USERSSTART = "392" // RFC1459 - Not Implemented (TODO:) + RPL_USERS = "393" // RFC1459 - Not Implemented (TODO:) + RPL_ENDOFUSERS = "394" // RFC1459 - Not Implemented (TODO:) + RPL_NOUSERS = "395" // RFC1459 - Not Implemented (TODO:) - ERR_UNKNOWNERROR = "400" - ERR_NOSUCHNICK = "401" - ERR_NOSUCHSERVER = "402" - ERR_NOSUCHCHANNEL = "403" - ERR_CANNOTSENDTOCHAN = "404" - ERR_TOOMANYCHANNELS = "405" - ERR_UNKNOWNCOMMAND = "421" - ERR_NOMOTD = "422" - ERR_ERRONUSNICKNAME = "432" - ERR_NICKNAMEINUSE = "433" - ERR_USERNOTINCHANNEL = "441" - ERR_NOTONCHANNEL = "442" - ERR_USERONCHANNEL = "443" - ERR_NOTREGISTERED = "451" - ERR_NEEDMOREPARAMS = "461" - ERR_ALREADYREGISTERED = "462" - ERR_PASSWDMISMATCH = "464" - ERR_YOUREBANNEDCREEP = "465" - ERR_CHANNELISFULL = "471" - ERR_UNKNOWNMODE = "472" - ERR_INVITEONLYCHAN = "473" - ERR_BANNEDFROMCHAN = "474" - ERR_BADCHANNELKEY = "475" - ERR_BADCHANMASK = "476" - ERR_NOPRIVILEGES = "481" - ERR_CHANOPRIVSNEEDED = "482" - ERR_CANTKILLSERVER = "483" - ERR_NOOPERHOST = "491" - ERR_UMODEUNKNOWNFLAG = "501" - ERR_USERSDONTMATCH = "502" - RPL_STARTTLS = "670" - ERR_STARTTLS = "691" - ERR_NOPRIVS = "723" - RPL_LOGGEDIN = "900" - RPL_LOGGEDOUT = "901" - ERR_NICKLOCKED = "902" - RPL_SASLSUCCESS = "903" - ERR_SASLFAIL = "904" - ERR_SASLTOOLONG = "905" - ERR_SASLABORTED = "906" - ERR_SASLALREADY = "907" - RPL_SASLMECHS = "908" + ERR_UNKNOWNERROR = "400" // ??????? - Not Implemented (TODO:) + ERR_NOSUCHNICK = "401" // RFC1459 - Not Implemented (TODO:) + ERR_NOSUCHSERVER = "402" // RFC1459 - Not Implemented (TODO:) + ERR_NOSUCHCHANNEL = "403" // RFC1459 - Not Implemented (TODO:) + ERR_CANNOTSENDTOCHAN = "404" // RFC1459 - Not Implemented (TODO:) + ERR_TOOMANYCHANNELS = "405" // RFC1459 - Not Implemented (TODO:) + ERR_WASNOSUCHNICK = "406" // RFC1459 - Not Implemented (TODO:) + ERR_NOSUCHSERVICE = "408" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + ERR_NOORIGIN = "409" // RFC1459 - Not Implemented (TODO:) + ERR_NORECIPIENT = "411" // RFC1459 - Not Implemented (TODO:) + ERR_NOTEXTTOSEND = "412" // RFC1459 - Not Implemented (TODO:) + ERR_NOTOPLEVEL = "413" // RFC1459 - Not Implemented (TODO:) + ERR_WILDTOPLEVEL = "414" // RFC1459 - Not Implemented (TODO:) + ERR_BADMASK = "415" // RFC2812 - Not Implemented (TODO:) + ERR_UNKNOWNCOMMAND = "421" // RFC1459 - Not Implemented (TODO:) + ERR_NOMOTD = "422" // RFC1459 - Not Implemented (TODO:) + ERR_NOADMININFO = "423" // RFC1459 - Not Implemented (TODO:) + ERR_FILEERROR = "424" // RFC1459 - Not Implemented (TODO:) + ERR_NONICKNAMEGIVEN = "431" // RFC1459 - Not Implemented (TODO:) + ERR_ERRONEUSNICKNAME = "432" // RFC1459 - Not Implemented (TODO:) + ERR_NICKNAMEINUSE = "433" // RFC1459 - Not Implemented (TODO:) + ERR_NICKCOLLISION = "436" // RFC1459 - Not Implemented (TODO:) + ERR_UNAVAILRESOURCE = "437" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + ERR_USERNOTINCHANNEL = "441" // RFC1459 - Not Implemented (TODO:) + ERR_NOTONCHANNEL = "442" // RFC1459 - Not Implemented (TODO:) + ERR_USERONCHANNEL = "443" // RFC1459 - Not Implemented (TODO:) + ERR_NOLOGIN = "444" // RFC1459 - Not Implemented (TODO:) + ERR_SUMMONDISABLED = "445" // RFC1459 - Not Implemented (TODO:) + ERR_USERSDISABLED = "446" // RFC1459 - Not Implemented (TODO:) + ERR_NOTREGISTERED = "451" // RFC1459 - Not Implemented (TODO:) + ERR_NEEDMOREPARAMS = "461" // RFC1459 - Not Implemented (TODO:) + ERR_ALREADYREGISTERED = "462" // RFC1459 - Not Implemented (TODO:) + ERR_NOPERMFORHOST = "463" // RFC1459 - Not Implemented (TODO:) + ERR_PASSWDMISMATCH = "464" // RFC1459 - Not Implemented (TODO:) + ERR_YOUREBANNEDCREEP = "465" // RFC1459 - Not Implemented (TODO:) + ERR_YOUWILLBEBANNED = "466" // RFC1459 - Not Implemented - Deprecated (TODO:) + ERR_KEYSET = "467" // RFC1459 - Not Implemented (TODO:) + ERR_CHANNELISFULL = "471" // RFC1459 - Not Implemented (TODO:) + ERR_UNKNOWNMODE = "472" // RFC1459 - Not Implemented (TODO:) + ERR_INVITEONLYCHAN = "473" // RFC1459 - Not Implemented (TODO:) + ERR_BANNEDFROMCHAN = "474" // RFC1459 - Not Implemented (TODO:) + ERR_BADCHANNELKEY = "475" // RFC1459 - Not Implemented (TODO:) + ERR_BADCHANMASK = "476" // RFC2812 - Not Implemented (TODO:) + ERR_BANLISTFULL = "478" // RFC2812 - Not Implemented (TODO:) + ERR_NOPRIVILEGES = "481" // RFC1459 - Not Implemented (TODO:) + ERR_CHANOPRIVSNEEDED = "482" // RFC1459 - Not Implemented (TODO:) + ERR_CANTKILLSERVER = "483" // RFC1459 - Not Implemented (TODO:) + ERR_RESTRICTED = "484" // RFC2812 - Not Implemented - Has Conflicts (TODO:) + ERR_UNIQOPRIVSNEEDED = "485" // RFC2812 - Not Implemented (TODO:) + ERR_NOOPERHOST = "491" // RFC1459 - Not Implemented (TODO:) + ERR_NOSERVICEHOST = "492" // RFC1459 - Not Implemented - Deprecated - Has Conflicts (TODO:) + ERR_UMODEUNKNOWNFLAG = "501" // RFC1459 - Not Implemented - Has Conflicts (TODO:) + ERR_USERSDONTMATCH = "502" // RFC1459 - Not Implemented (TODO:) + RPL_STARTTLS = "670" // IRCv3 - Not Implemented (TODO:) + ERR_STARTTLS = "691" // IRCv3 - Not Implemented (TODO:) + ERR_NOPRIVS = "723" // RatBox - Not Implemented (TODO:) + RPL_WHOISKEYVALUE = "760" // IRCv3 - Not Implemented (TODO:) + RPL_KEYVALUE = "761" // IRCv3 - Not Implemented (TODO:) + RPL_METADATAEND = "762" // IRCv3 - Not Implemented (TODO:) + ERR_METADATALIMIT = "764" // IRCv3 - Not Implemented (TODO:) + ERR_TARGETINVALID = "765" // IRCv3 - Not Implemented (TODO:) + ERR_NOMATCHINGKEY = "766" // IRCv3 - Not Implemented (TODO:) + ERR_KEYINVALID = "767" // IRCv3 - Not Implemented (TODO:) + ERR_KEYNOTSET = "768" // IRCv3 - Not Implemented (TODO:) + ERR_KEYNOPERMISSION = "769" // IRCv3 - Not Implemented (TODO:) + RPL_LOGGEDIN = "900" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + RPL_LOGGEDOUT = "901" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + ERR_NICKLOCKED = "902" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + RPL_SASLSUCCESS = "903" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + ERR_SASLFAIL = "904" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + ERR_SASLTOOLONG = "905" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + ERR_SASLABORTED = "906" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + ERR_SASLALREADY = "907" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) + RPL_SASLMECHS = "908" // Charybdis/Atheme,IRCv3 - Not Implemented (TODO:) ) /* --- RPL_ISUPPORT Parameters --- */ -// TODO: + +var Features = map[string]bool{ + "ACCEPT": true, + "AWAYLEN": true, + "BOT": true, + "CALLERID": true, + "CASEMAPPING": true, + "CHANLIMIT": true, + "CHANMODES": true, + "CHANNELLEN": true, + "CHANTYPES": true, + "CHARSET": true, // Deprecated but might still be used + "CLIENTVER": true, // Deprecated but might still be used + "CNOTICE": true, + "CPRIVMSG": true, + "DEAF": true, + "ELIST": true, + "ESILENCE": true, + "ETRACE": true, + "EXCEPTS": true, + "EXTBAN": true, + "FNC": true, // Deprecated but might still be used + "INVEX": true, + "KEYLEN": true, + "KICKLEN": true, + "KNOCK": true, + "LINELEN": true, // Proposed + "MAP": true, // Deprecated but might still be used + "MAXBANS": true, // Deprecated but might still be used + "MAXCHANNELS": true, // Deprecated but might still be used + "MAXLIST": true, + "MAXNICKLEN": true, + "MAXPARA": true, // Deprecated but might still be used + "MAXTARGETS": true, + "METADATA": true, + "MODES": true, + "MONITOR": true, + "NAMESX": true, // Deprecated but might still be used + "NETWORK": true, + "NICKLEN": true, + "OVERRIDE": true, + "PREFIX": true, + "SAFELIST": true, + "SECURELIST": true, + "SILENCE": true, + "SSL": true, // Deprecated but might still be used + "STARTTLS": true, // Deprecated but might still be used + "STATUSMSG": true, + "STD": true, // Deprecated but might still be used + "TARGMAX": true, + "TOPICLEN": true, + "UHNAMES": true, // Deprecated but might still be used + "USERIP": true, + "USERLEN": true, // Proposed + "VBANLIST": true, // Deprecared but might still be used + "VLIST": true, + "WALLCHOPS": true, // Deprecated but might still be used + "WALLVOICES": true, // Deprecated but might still be used + "WATCH": true, + "WHOX": true, +} // Messages MUST end in CRLF and SHOULD be encoded and decoded using UTF-8 (with fallbacks such as Latin-1). // Names are casemapped, read the casemapping from the RPL_ISUPPORT the server sends when registration is completed. -// Silently ignore empty messages and only parse messages when you encounter a CRLF. -// Client SHOULD NOT include a source when sending a message, but if included it MUST be the nickname of the client. // When receiving a numeric reply, client MUST be able to handle any number of parameters on a numeric reply. diff --git a/ui/mainscreen/handler.go b/ui/mainscreen/handler.go index 1444c5d..1cab6ff 100644 --- a/ui/mainscreen/handler.go +++ b/ui/mainscreen/handler.go @@ -245,13 +245,21 @@ func (s *State) HandleCommand(msg parser.IRCMessage) { case commands.RPL_NAMREPLY: s.handleNAMREPLY(msg) case commands.RPL_ENDOFNAMES: - // TODO: what do i do here lol + // TODO: toggle a flag on the channel to indicate + // it received all the names correctly. + + // start a timeout and update said timeout on every RPL_NAMREPLY + // and log an error if timeout ends without receiving this command. case commands.RPL_MOTDSTART: s.handleMOTDStart(msg) case commands.RPL_MOTD: s.handleMOTD(msg) case commands.RPL_ENDOFMOTD: - // TODO: what do i do here lol + // TODO: toggle a flag on the client/server to indicate + // it received all the MOTD correctly + + // start a timeout and update said timeout on every RPL_MOTD + // and log an error if timeout ends without receiving this command. default: fullMsg := fmt.Sprintf("%s %s %s %s", msg.Tags, msg.Source, msg.Command, strings.Join(msg.Parameters, " ")) diff --git a/ui/mainscreen/mainscreen.go b/ui/mainscreen/mainscreen.go index 01cd07a..02b3291 100644 --- a/ui/mainscreen/mainscreen.go +++ b/ui/mainscreen/mainscreen.go @@ -82,7 +82,7 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) { switch msg := msg.(type) { case ReceivedIRCMsgMsg: wasAtBottom := s.Viewport.AtBottom() - s.Viewport.SetContent(s.Client.Channels[s.Client.ChannelIndex].History) + s.Viewport.SetContent(s.Client.Channels[s.Client.ActiveChannelIndex].History) if wasAtBottom { s.Viewport.GotoBottom() @@ -105,14 +105,14 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) { s.Client.ActiveChannel = channel for i, c := range s.Client.Channels { if c.Name == channel { - s.Client.ChannelIndex = i + s.Client.ActiveChannelIndex = i break } else if i == len(s.Client.Channels)-1 { s.Client.Channels = append(s.Client.Channels, client.Channel{ Name: channel, Users: make(map[string]client.User), }) - s.Client.ChannelIndex = len(s.Client.Channels) - 1 + s.Client.ActiveChannelIndex = len(s.Client.Channels) - 1 LastTabIndexInTabBar = len(s.Client.Channels) - 1 s.TabRenderingDirection = Left } @@ -124,17 +124,17 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) { } else { if s.Client.ActiveChannel != s.Client.Host { fullMsg := s.Client.Nickname + ": " + msg.Msg - s.Client.Channels[s.Client.ChannelIndex].History += fullMsg + client.CRLF + s.Client.Channels[s.Client.ActiveChannelIndex].History += fullMsg + client.CRLF // TODO: make sure to only append the message to the history if server sends back no errors s.Client.SendCommand(commands.PRIVMSG, s.Client.ActiveChannel, msg.Msg) - s.Viewport.SetContent(s.Client.Channels[s.Client.ChannelIndex].History) + s.Viewport.SetContent(s.Client.Channels[s.Client.ActiveChannelIndex].History) s.Viewport.GotoBottom() } } return s, nil case SwitchChannelsMsg: - s.Viewport.SetContent(s.Client.Channels[s.Client.ChannelIndex].History) + s.Viewport.SetContent(s.Client.Channels[s.Client.ActiveChannelIndex].History) s.Viewport.GotoBottom() *s.SidePanel, cmd = s.SidePanel.Update(msg) @@ -181,26 +181,26 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) { } if key == "right" { - s.Client.ChannelIndex++ + s.Client.ActiveChannelIndex++ } else { - s.Client.ChannelIndex-- + s.Client.ActiveChannelIndex-- } - if s.Client.ChannelIndex >= len(s.Client.Channels) { - s.Client.ChannelIndex = 0 - } else if s.Client.ChannelIndex < 0 { - s.Client.ChannelIndex = len(s.Client.Channels) - 1 + if s.Client.ActiveChannelIndex >= len(s.Client.Channels) { + s.Client.ActiveChannelIndex = 0 + } else if s.Client.ActiveChannelIndex < 0 { + s.Client.ActiveChannelIndex = len(s.Client.Channels) - 1 } - if s.Client.ChannelIndex > LastTabIndexInTabBar { + if s.Client.ActiveChannelIndex > LastTabIndexInTabBar { s.TabRenderingDirection = Left - LastTabIndexInTabBar = s.Client.ChannelIndex - } else if s.Client.ChannelIndex < FirstTabIndexInTabBar { - FirstTabIndexInTabBar = s.Client.ChannelIndex + LastTabIndexInTabBar = s.Client.ActiveChannelIndex + } else if s.Client.ActiveChannelIndex < FirstTabIndexInTabBar { + FirstTabIndexInTabBar = s.Client.ActiveChannelIndex s.TabRenderingDirection = Right } - s.Client.ActiveChannel = s.Client.Channels[s.Client.ChannelIndex].Name + s.Client.ActiveChannel = s.Client.Channels[s.Client.ActiveChannelIndex].Name return s, SwitchChannels case "g": if s.FocusIndex == Viewport { @@ -268,7 +268,7 @@ func (s *State) SetSize(width, height int) { // we need this to render an empty viewport history := "" if len(s.Client.Channels) != 0 { - history = s.Client.Channels[s.Client.ChannelIndex].History + history = s.Client.Channels[s.Client.ActiveChannelIndex].History } // we need to re-set the content because words wrap differently on different sizes diff --git a/ui/mainscreen/sidepanel.go b/ui/mainscreen/sidepanel.go index d3c6063..623b8e0 100644 --- a/ui/mainscreen/sidepanel.go +++ b/ui/mainscreen/sidepanel.go @@ -36,7 +36,7 @@ type SidePanelState struct { func (s *SidePanelState) getHeader() string { usersCount := 0 if len(s.Client.Channels) != 0 { - usersCount = len(s.Client.Channels[s.Client.ChannelIndex].Users) + usersCount = len(s.Client.Channels[s.Client.ActiveChannelIndex].Users) } separator := strings.Repeat("—", s.Viewport.Width) + "\n" header := fmt.Sprintf("Users in this channel (%d)\n", usersCount) + separator @@ -48,7 +48,7 @@ func (s *SidePanelState) getLatestNicks() []string { nicks := make([]string, 0) if len(s.Client.Channels) != 0 { - for nick, user := range s.Client.Channels[s.Client.ChannelIndex].Users { + for nick, user := range s.Client.Channels[s.Client.ActiveChannelIndex].Users { _nick := user.Prefix + nick nicks = append(nicks, _nick) }