diff --git a/cmd/neoirc-cli/api/client.go b/cmd/neoirc-cli/api/client.go index 8f7fdcf..ce94518 100644 --- a/cmd/neoirc-cli/api/client.go +++ b/cmd/neoirc-cli/api/client.go @@ -14,7 +14,7 @@ import ( "strings" "time" - "git.eeqj.de/sneak/neoirc/internal/irc" + "git.eeqj.de/sneak/neoirc/pkg/irc" ) const ( diff --git a/cmd/neoirc-cli/main.go b/cmd/neoirc-cli/main.go index 4000e01..28401d0 100644 --- a/cmd/neoirc-cli/main.go +++ b/cmd/neoirc-cli/main.go @@ -9,7 +9,7 @@ import ( "time" api "git.eeqj.de/sneak/neoirc/cmd/neoirc-cli/api" - "git.eeqj.de/sneak/neoirc/internal/irc" + "git.eeqj.de/sneak/neoirc/pkg/irc" ) const ( diff --git a/internal/db/queries.go b/internal/db/queries.go index 50686d3..52d9761 100644 --- a/internal/db/queries.go +++ b/internal/db/queries.go @@ -11,7 +11,7 @@ import ( "strconv" "time" - "git.eeqj.de/sneak/neoirc/internal/irc" + "git.eeqj.de/sneak/neoirc/pkg/irc" "github.com/google/uuid" ) diff --git a/internal/handlers/api.go b/internal/handlers/api.go index fce5101..c5a5592 100644 --- a/internal/handlers/api.go +++ b/internal/handlers/api.go @@ -11,7 +11,7 @@ import ( "time" "git.eeqj.de/sneak/neoirc/internal/db" - "git.eeqj.de/sneak/neoirc/internal/irc" + "git.eeqj.de/sneak/neoirc/pkg/irc" "github.com/go-chi/chi" ) diff --git a/internal/irc/numerics.go b/internal/irc/numerics.go deleted file mode 100644 index 510925b..0000000 --- a/internal/irc/numerics.go +++ /dev/null @@ -1,150 +0,0 @@ -// Package irc provides constants and utilities for the -// IRC protocol, including numeric reply codes from -// RFC 1459 and RFC 2812, and standard command names. -package irc - -// Connection registration replies (001-005). -const ( - RplWelcome = 1 - RplYourHost = 2 - RplCreated = 3 - RplMyInfo = 4 - RplIsupport = 5 -) - -// Command responses (200-399). -const ( - RplUmodeIs = 221 - RplLuserClient = 251 - RplLuserOp = 252 - RplLuserUnknown = 253 - RplLuserChannels = 254 - RplLuserMe = 255 - RplAway = 301 - RplUserHost = 302 - RplIson = 303 - RplUnaway = 305 - RplNowAway = 306 - RplWhoisUser = 311 - RplWhoisServer = 312 - RplWhoisOperator = 313 - RplEndOfWho = 315 - RplWhoisIdle = 317 - RplEndOfWhois = 318 - RplWhoisChannels = 319 - RplList = 322 - RplListEnd = 323 - RplChannelModeIs = 324 - RplCreationTime = 329 - RplNoTopic = 331 - RplTopic = 332 - RplTopicWhoTime = 333 - RplInviting = 341 - RplWhoReply = 352 - RplNamReply = 353 - RplEndOfNames = 366 - RplBanList = 367 - RplEndOfBanList = 368 - RplMotd = 372 - RplMotdStart = 375 - RplEndOfMotd = 376 -) - -// Error replies (400-599). -const ( - ErrNoSuchNick = 401 - ErrNoSuchServer = 402 - ErrNoSuchChannel = 403 - ErrCannotSendToChan = 404 - ErrTooManyChannels = 405 - ErrNoRecipient = 411 - ErrNoTextToSend = 412 - ErrUnknownCommand = 421 - ErrNoNicknameGiven = 431 - ErrErroneusNickname = 432 - ErrNicknameInUse = 433 - ErrUserNotInChannel = 441 - ErrNotOnChannel = 442 - ErrNotRegistered = 451 - ErrNeedMoreParams = 461 - ErrAlreadyRegistered = 462 - ErrChannelIsFull = 471 - ErrInviteOnlyChan = 473 - ErrBannedFromChan = 474 - ErrBadChannelKey = 475 - ErrChanOpPrivsNeeded = 482 -) - -// names maps numeric codes to their standard IRC names. -// -//nolint:gochecknoglobals -var names = map[int]string{ - RplWelcome: "RPL_WELCOME", - RplYourHost: "RPL_YOURHOST", - RplCreated: "RPL_CREATED", - RplMyInfo: "RPL_MYINFO", - RplIsupport: "RPL_ISUPPORT", - RplUmodeIs: "RPL_UMODEIS", - RplLuserClient: "RPL_LUSERCLIENT", - RplLuserOp: "RPL_LUSEROP", - RplLuserUnknown: "RPL_LUSERUNKNOWN", - RplLuserChannels: "RPL_LUSERCHANNELS", - RplLuserMe: "RPL_LUSERME", - RplAway: "RPL_AWAY", - RplUserHost: "RPL_USERHOST", - RplIson: "RPL_ISON", - RplUnaway: "RPL_UNAWAY", - RplNowAway: "RPL_NOWAWAY", - RplWhoisUser: "RPL_WHOISUSER", - RplWhoisServer: "RPL_WHOISSERVER", - RplWhoisOperator: "RPL_WHOISOPERATOR", - RplEndOfWho: "RPL_ENDOFWHO", - RplWhoisIdle: "RPL_WHOISIDLE", - RplEndOfWhois: "RPL_ENDOFWHOIS", - RplWhoisChannels: "RPL_WHOISCHANNELS", - RplList: "RPL_LIST", - RplListEnd: "RPL_LISTEND", //nolint:misspell - RplChannelModeIs: "RPL_CHANNELMODEIS", - RplCreationTime: "RPL_CREATIONTIME", - RplNoTopic: "RPL_NOTOPIC", - RplTopic: "RPL_TOPIC", - RplTopicWhoTime: "RPL_TOPICWHOTIME", - RplInviting: "RPL_INVITING", - RplWhoReply: "RPL_WHOREPLY", - RplNamReply: "RPL_NAMREPLY", - RplEndOfNames: "RPL_ENDOFNAMES", - RplBanList: "RPL_BANLIST", - RplEndOfBanList: "RPL_ENDOFBANLIST", - RplMotd: "RPL_MOTD", - RplMotdStart: "RPL_MOTDSTART", - RplEndOfMotd: "RPL_ENDOFMOTD", - - ErrNoSuchNick: "ERR_NOSUCHNICK", - ErrNoSuchServer: "ERR_NOSUCHSERVER", - ErrNoSuchChannel: "ERR_NOSUCHCHANNEL", - ErrCannotSendToChan: "ERR_CANNOTSENDTOCHAN", - ErrTooManyChannels: "ERR_TOOMANYCHANNELS", - ErrNoRecipient: "ERR_NORECIPIENT", - ErrNoTextToSend: "ERR_NOTEXTTOSEND", - ErrUnknownCommand: "ERR_UNKNOWNCOMMAND", - ErrNoNicknameGiven: "ERR_NONICKNAMEGIVEN", - ErrErroneusNickname: "ERR_ERRONEUSNICKNAME", - ErrNicknameInUse: "ERR_NICKNAMEINUSE", - ErrUserNotInChannel: "ERR_USERNOTINCHANNEL", - ErrNotOnChannel: "ERR_NOTONCHANNEL", - ErrNotRegistered: "ERR_NOTREGISTERED", - ErrNeedMoreParams: "ERR_NEEDMOREPARAMS", - ErrAlreadyRegistered: "ERR_ALREADYREGISTERED", - ErrChannelIsFull: "ERR_CHANNELISFULL", - ErrInviteOnlyChan: "ERR_INVITEONLYCHAN", - ErrBannedFromChan: "ERR_BANNEDFROMCHAN", - ErrBadChannelKey: "ERR_BADCHANNELKEY", - ErrChanOpPrivsNeeded: "ERR_CHANOPRIVSNEEDED", -} - -// Name returns the standard IRC name for a numeric code -// (e.g., Name(2) returns "RPL_YOURHOST"). Returns an -// empty string if the code is unknown. -func Name(code int) string { - return names[code] -} diff --git a/internal/irc/commands.go b/pkg/irc/commands.go similarity index 100% rename from internal/irc/commands.go rename to pkg/irc/commands.go diff --git a/pkg/irc/numerics.go b/pkg/irc/numerics.go new file mode 100644 index 0000000..4c3c484 --- /dev/null +++ b/pkg/irc/numerics.go @@ -0,0 +1,331 @@ +// Package irc provides constants and utilities for the +// IRC protocol, including numeric reply codes from +// RFC 1459 and RFC 2812, and standard command names. +package irc + +// Connection registration replies (001-005). +const ( + RplWelcome = 1 + RplYourHost = 2 + RplCreated = 3 + RplMyInfo = 4 + RplBounce = 5 // RFC 2812; also known as RPL_ISUPPORT in practice + RplIsupport = 5 // De-facto standard (same numeric as RplBounce) +) + +// Command responses (200-399). +const ( + // RFC 2812 trace/stats/links replies (200-219). + RplTraceLink = 200 + RplTraceConnecting = 201 + RplTraceHandshake = 202 + RplTraceUnknown = 203 + RplTraceOperator = 204 + RplTraceUser = 205 + RplTraceServer = 206 + RplTraceService = 207 + RplTraceNewType = 208 + RplTraceClass = 209 + RplStatsLinkInfo = 211 + RplStatsCommands = 212 + RplStatsCLine = 213 + RplStatsNLine = 214 + RplStatsILine = 215 + RplStatsKLine = 216 + RplStatsYLine = 218 + RplEndOfStats = 219 + + RplUmodeIs = 221 + RplServList = 234 + RplServListEnd = 235 + RplStatsUptime = 242 + RplStatsOLine = 243 + RplLuserClient = 251 + RplLuserOp = 252 + RplLuserUnknown = 253 + + RplLuserChannels = 254 + RplLuserMe = 255 + RplAdminMe = 256 + RplAdminLoc1 = 257 + RplAdminLoc2 = 258 + RplAdminEmail = 259 + RplTraceLog = 261 + RplTraceEnd = 262 + RplTryAgain = 263 + + RplAway = 301 + RplUserHost = 302 + RplIson = 303 + RplUnaway = 305 + RplNowAway = 306 + RplWhoisUser = 311 + RplWhoisServer = 312 + RplWhoisOperator = 313 + RplWhoWasUser = 314 + RplEndOfWho = 315 + RplWhoisIdle = 317 + RplEndOfWhois = 318 + RplWhoisChannels = 319 + RplListStart = 321 + RplList = 322 + RplListEnd = 323 + RplChannelModeIs = 324 + + RplUniqOpIs = 325 + RplCreationTime = 329 + RplNoTopic = 331 + RplTopic = 332 + RplTopicWhoTime = 333 + RplInviting = 341 + RplSummoning = 342 + RplInviteList = 346 + RplEndOfInviteList = 347 + RplExceptList = 348 + RplEndOfExceptList = 349 + RplVersion = 351 + RplWhoReply = 352 + RplNamReply = 353 + RplLinks = 364 + RplEndOfLinks = 365 + RplEndOfNames = 366 + RplBanList = 367 + RplEndOfBanList = 368 + RplEndOfWhowas = 369 + RplInfo = 371 + RplMotd = 372 + RplEndOfInfo = 374 + RplMotdStart = 375 + RplEndOfMotd = 376 + RplYoureOper = 381 + RplRehashing = 382 + RplYoureService = 383 + RplTime = 391 + RplUsersStart = 392 + RplUsers = 393 + RplEndOfUsers = 394 + RplNoUsers = 395 +) + +// Error replies (400-599). +const ( + ErrNoSuchNick = 401 + ErrNoSuchServer = 402 + ErrNoSuchChannel = 403 + ErrCannotSendToChan = 404 + ErrTooManyChannels = 405 + ErrWasNoSuchNick = 406 + ErrTooManyTargets = 407 + ErrNoSuchService = 408 + ErrNoOrigin = 409 + ErrNoRecipient = 411 + ErrNoTextToSend = 412 + ErrNoTopLevel = 413 + ErrWildTopLevel = 414 + ErrBadMask = 415 + ErrUnknownCommand = 421 + ErrNoMotd = 422 + ErrNoAdminInfo = 423 + ErrFileError = 424 + ErrNoNicknameGiven = 431 + ErrErroneusNickname = 432 + ErrNicknameInUse = 433 + ErrNickCollision = 436 + ErrUnavailResource = 437 + + ErrUserNotInChannel = 441 + ErrNotOnChannel = 442 + ErrUserOnChannel = 443 + ErrNoLogin = 444 + ErrSummonDisabled = 445 + ErrUsersDisabled = 446 + ErrNotRegistered = 451 + ErrNeedMoreParams = 461 + ErrAlreadyRegistered = 462 + ErrNoPermForHost = 463 + ErrPasswdMismatch = 464 + ErrYoureBannedCreep = 465 + ErrYouWillBeBanned = 466 + ErrKeySet = 467 + ErrChannelIsFull = 471 + ErrUnknownMode = 472 + ErrInviteOnlyChan = 473 + ErrBannedFromChan = 474 + ErrBadChannelKey = 475 + ErrBadChanMask = 476 + ErrNoChanModes = 477 + ErrBanListFull = 478 + ErrNoPrivileges = 481 + ErrChanOpPrivsNeeded = 482 + ErrCantKillServer = 483 + ErrRestricted = 484 + ErrUniqOpPrivsNeeded = 485 + ErrNoOperHost = 491 + + ErrUmodeUnknownFlag = 501 + ErrUsersDoNotMatch = 502 +) + +// names maps numeric codes to their standard IRC names. +// +//nolint:gochecknoglobals +var names = map[int]string{ + RplWelcome: "RPL_WELCOME", + RplYourHost: "RPL_YOURHOST", + RplCreated: "RPL_CREATED", + RplMyInfo: "RPL_MYINFO", + RplBounce: "RPL_BOUNCE", + + RplTraceLink: "RPL_TRACELINK", + RplTraceConnecting: "RPL_TRACECONNECTING", + RplTraceHandshake: "RPL_TRACEHANDSHAKE", + RplTraceUnknown: "RPL_TRACEUNKNOWN", + RplTraceOperator: "RPL_TRACEOPERATOR", + RplTraceUser: "RPL_TRACEUSER", + RplTraceServer: "RPL_TRACESERVER", + RplTraceService: "RPL_TRACESERVICE", + RplTraceNewType: "RPL_TRACENEWTYPE", + RplTraceClass: "RPL_TRACECLASS", + RplStatsLinkInfo: "RPL_STATSLINKINFO", + RplStatsCommands: "RPL_STATSCOMMANDS", + RplStatsCLine: "RPL_STATSCLINE", + RplStatsNLine: "RPL_STATSNLINE", + RplStatsILine: "RPL_STATSILINE", + RplStatsKLine: "RPL_STATSKLINE", + RplStatsYLine: "RPL_STATSYLINE", + RplEndOfStats: "RPL_ENDOFSTATS", + + RplUmodeIs: "RPL_UMODEIS", + RplServList: "RPL_SERVLIST", + RplServListEnd: "RPL_SERVLISTEND", + RplStatsUptime: "RPL_STATSUPTIME", + RplStatsOLine: "RPL_STATSOLINE", + RplLuserClient: "RPL_LUSERCLIENT", + RplLuserOp: "RPL_LUSEROP", + RplLuserUnknown: "RPL_LUSERUNKNOWN", + + RplLuserChannels: "RPL_LUSERCHANNELS", + RplLuserMe: "RPL_LUSERME", + RplAdminMe: "RPL_ADMINME", + RplAdminLoc1: "RPL_ADMINLOC1", + RplAdminLoc2: "RPL_ADMINLOC2", + RplAdminEmail: "RPL_ADMINEMAIL", + RplTraceLog: "RPL_TRACELOG", + RplTraceEnd: "RPL_TRACEEND", + RplTryAgain: "RPL_TRYAGAIN", + + RplAway: "RPL_AWAY", + RplUserHost: "RPL_USERHOST", + RplIson: "RPL_ISON", + RplUnaway: "RPL_UNAWAY", + RplNowAway: "RPL_NOWAWAY", + RplWhoisUser: "RPL_WHOISUSER", + RplWhoisServer: "RPL_WHOISSERVER", + RplWhoisOperator: "RPL_WHOISOPERATOR", + RplWhoWasUser: "RPL_WHOWASUSER", + RplEndOfWho: "RPL_ENDOFWHO", + RplWhoisIdle: "RPL_WHOISIDLE", + RplEndOfWhois: "RPL_ENDOFWHOIS", + RplWhoisChannels: "RPL_WHOISCHANNELS", + RplListStart: "RPL_LISTSTART", + RplList: "RPL_LIST", + RplListEnd: "RPL_LISTEND", //nolint:misspell + RplChannelModeIs: "RPL_CHANNELMODEIS", + + RplUniqOpIs: "RPL_UNIQOPIS", + RplCreationTime: "RPL_CREATIONTIME", + RplNoTopic: "RPL_NOTOPIC", + RplTopic: "RPL_TOPIC", + RplTopicWhoTime: "RPL_TOPICWHOTIME", + RplInviting: "RPL_INVITING", + RplSummoning: "RPL_SUMMONING", + RplInviteList: "RPL_INVITELIST", + RplEndOfInviteList: "RPL_ENDOFINVITELIST", + RplExceptList: "RPL_EXCEPTLIST", + RplEndOfExceptList: "RPL_ENDOFEXCEPTLIST", + RplVersion: "RPL_VERSION", + RplWhoReply: "RPL_WHOREPLY", + RplNamReply: "RPL_NAMREPLY", + RplLinks: "RPL_LINKS", + RplEndOfLinks: "RPL_ENDOFLINKS", + RplEndOfNames: "RPL_ENDOFNAMES", + RplBanList: "RPL_BANLIST", + RplEndOfBanList: "RPL_ENDOFBANLIST", + RplEndOfWhowas: "RPL_ENDOFWHOWAS", + RplInfo: "RPL_INFO", + RplMotd: "RPL_MOTD", + RplEndOfInfo: "RPL_ENDOFINFO", + RplMotdStart: "RPL_MOTDSTART", + RplEndOfMotd: "RPL_ENDOFMOTD", + RplYoureOper: "RPL_YOUREOPER", + RplRehashing: "RPL_REHASHING", + RplYoureService: "RPL_YOURESERVICE", + RplTime: "RPL_TIME", + RplUsersStart: "RPL_USERSSTART", + RplUsers: "RPL_USERS", + RplEndOfUsers: "RPL_ENDOFUSERS", + RplNoUsers: "RPL_NOUSERS", + + ErrNoSuchNick: "ERR_NOSUCHNICK", + ErrNoSuchServer: "ERR_NOSUCHSERVER", + ErrNoSuchChannel: "ERR_NOSUCHCHANNEL", + ErrCannotSendToChan: "ERR_CANNOTSENDTOCHAN", + ErrTooManyChannels: "ERR_TOOMANYCHANNELS", + ErrWasNoSuchNick: "ERR_WASNOSUCHNICK", + ErrTooManyTargets: "ERR_TOOMANYTARGETS", + ErrNoSuchService: "ERR_NOSUCHSERVICE", + ErrNoOrigin: "ERR_NOORIGIN", + ErrNoRecipient: "ERR_NORECIPIENT", + ErrNoTextToSend: "ERR_NOTEXTTOSEND", + ErrNoTopLevel: "ERR_NOTOPLEVEL", + ErrWildTopLevel: "ERR_WILDTOPLEVEL", + ErrBadMask: "ERR_BADMASK", + ErrUnknownCommand: "ERR_UNKNOWNCOMMAND", + ErrNoMotd: "ERR_NOMOTD", + ErrNoAdminInfo: "ERR_NOADMININFO", + ErrFileError: "ERR_FILEERROR", + ErrNoNicknameGiven: "ERR_NONICKNAMEGIVEN", + ErrErroneusNickname: "ERR_ERRONEUSNICKNAME", + ErrNicknameInUse: "ERR_NICKNAMEINUSE", + ErrNickCollision: "ERR_NICKCOLLISION", + ErrUnavailResource: "ERR_UNAVAILRESOURCE", + + ErrUserNotInChannel: "ERR_USERNOTINCHANNEL", + ErrNotOnChannel: "ERR_NOTONCHANNEL", + ErrUserOnChannel: "ERR_USERONCHANNEL", + ErrNoLogin: "ERR_NOLOGIN", + ErrSummonDisabled: "ERR_SUMMONDISABLED", + ErrUsersDisabled: "ERR_USERSDISABLED", + ErrNotRegistered: "ERR_NOTREGISTERED", + ErrNeedMoreParams: "ERR_NEEDMOREPARAMS", + ErrAlreadyRegistered: "ERR_ALREADYREGISTERED", + ErrNoPermForHost: "ERR_NOPERMFORHOST", + ErrPasswdMismatch: "ERR_PASSWDMISMATCH", + ErrYoureBannedCreep: "ERR_YOUREBANNEDCREEP", + ErrYouWillBeBanned: "ERR_YOUWILLBEBANNED", + ErrKeySet: "ERR_KEYSET", + ErrChannelIsFull: "ERR_CHANNELISFULL", + ErrUnknownMode: "ERR_UNKNOWNMODE", + ErrInviteOnlyChan: "ERR_INVITEONLYCHAN", + ErrBannedFromChan: "ERR_BANNEDFROMCHAN", + ErrBadChannelKey: "ERR_BADCHANNELKEY", + ErrBadChanMask: "ERR_BADCHANMASK", + ErrNoChanModes: "ERR_NOCHANMODES", + ErrBanListFull: "ERR_BANLISTFULL", + ErrNoPrivileges: "ERR_NOPRIVILEGES", + ErrChanOpPrivsNeeded: "ERR_CHANOPRIVSNEEDED", + ErrCantKillServer: "ERR_CANTKILLSERVER", + ErrRestricted: "ERR_RESTRICTED", + ErrUniqOpPrivsNeeded: "ERR_UNIQOPPRIVSNEEDED", + ErrNoOperHost: "ERR_NOOPERHOST", + + ErrUmodeUnknownFlag: "ERR_UMODEUNKNOWNFLAG", + ErrUsersDoNotMatch: "ERR_USERSDONTMATCH", +} + +// Name returns the standard IRC name for a numeric code +// (e.g., Name(2) returns "RPL_YOURHOST"). Returns an +// empty string if the code is unknown. +func Name(code int) string { + return names[code] +}