diff --git a/internal/db/queries.go b/internal/db/queries.go index 52d9761..0698ef0 100644 --- a/internal/db/queries.go +++ b/internal/db/queries.go @@ -746,7 +746,7 @@ func scanMessages( code, _ := strconv.Atoi(msg.Command) msg.Code = code - if name := irc.Name(code); name != "" { + if name := irc.Name(irc.MessageType(code)); name != "" { msg.Command = name } } diff --git a/internal/handlers/api.go b/internal/handlers/api.go index c5a5592..3762cf8 100644 --- a/internal/handlers/api.go +++ b/internal/handlers/api.go @@ -398,12 +398,12 @@ func (hdlr *Handlers) serverName() string { func (hdlr *Handlers) enqueueNumeric( ctx context.Context, clientID int64, - code int, + code irc.MessageType, nick string, params []string, text string, ) { - command := fmt.Sprintf("%03d", code) + command := code.String() body, err := json.Marshal([]string{text}) if err != nil { @@ -969,7 +969,7 @@ func (hdlr *Handlers) respondIRCError( writer http.ResponseWriter, request *http.Request, clientID, sessionID int64, - code int, + code irc.MessageType, nick string, params []string, text string, diff --git a/pkg/irc/numerics.go b/pkg/irc/numerics.go index 636049b..73d3bc2 100644 --- a/pkg/irc/numerics.go +++ b/pkg/irc/numerics.go @@ -3,176 +3,194 @@ // RFC 1459 and RFC 2812, and standard command names. package irc +import "fmt" + +// MessageType represents an IRC numeric reply or error code. +type MessageType int + +// Name returns the standard IRC name for this numeric code +// (e.g., MessageType(2).Name() returns "RPL_YOURHOST"). +// Returns an empty string if the code is unknown. +func (t MessageType) Name() string { + return names[t] +} + +// String returns the three-digit zero-padded string representation +// of the numeric code (e.g., MessageType(1).String() returns "001"). +func (t MessageType) String() string { + return fmt.Sprintf("%03d", int(t)) +} + // 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) + RplWelcome MessageType = 1 + RplYourHost MessageType = 2 + RplCreated MessageType = 3 + RplMyInfo MessageType = 4 + RplBounce MessageType = 5 // RFC 2812; also known as RPL_ISUPPORT in practice + RplIsupport MessageType = 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 - RplStatsQLine = 217 - RplStatsYLine = 218 - RplEndOfStats = 219 + RplTraceLink MessageType = 200 + RplTraceConnecting MessageType = 201 + RplTraceHandshake MessageType = 202 + RplTraceUnknown MessageType = 203 + RplTraceOperator MessageType = 204 + RplTraceUser MessageType = 205 + RplTraceServer MessageType = 206 + RplTraceService MessageType = 207 + RplTraceNewType MessageType = 208 + RplTraceClass MessageType = 209 + RplStatsLinkInfo MessageType = 211 + RplStatsCommands MessageType = 212 + RplStatsCLine MessageType = 213 + RplStatsNLine MessageType = 214 + RplStatsILine MessageType = 215 + RplStatsKLine MessageType = 216 + RplStatsQLine MessageType = 217 + RplStatsYLine MessageType = 218 + RplEndOfStats MessageType = 219 - RplUmodeIs = 221 - RplServList = 234 - RplServListEnd = 235 - RplStatsLLine = 241 - RplStatsUptime = 242 - RplStatsOLine = 243 - RplStatsHLine = 244 - RplLuserClient = 251 - RplLuserOp = 252 - RplLuserUnknown = 253 + RplUmodeIs MessageType = 221 + RplServList MessageType = 234 + RplServListEnd MessageType = 235 + RplStatsLLine MessageType = 241 + RplStatsUptime MessageType = 242 + RplStatsOLine MessageType = 243 + RplStatsHLine MessageType = 244 + RplLuserClient MessageType = 251 + RplLuserOp MessageType = 252 + RplLuserUnknown MessageType = 253 - RplLuserChannels = 254 - RplLuserMe = 255 - RplAdminMe = 256 - RplAdminLoc1 = 257 - RplAdminLoc2 = 258 - RplAdminEmail = 259 - RplTraceLog = 261 - RplTraceEnd = 262 - RplTryAgain = 263 + RplLuserChannels MessageType = 254 + RplLuserMe MessageType = 255 + RplAdminMe MessageType = 256 + RplAdminLoc1 MessageType = 257 + RplAdminLoc2 MessageType = 258 + RplAdminEmail MessageType = 259 + RplTraceLog MessageType = 261 + RplTraceEnd MessageType = 262 + RplTryAgain MessageType = 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 + RplAway MessageType = 301 + RplUserHost MessageType = 302 + RplIson MessageType = 303 + RplUnaway MessageType = 305 + RplNowAway MessageType = 306 + RplWhoisUser MessageType = 311 + RplWhoisServer MessageType = 312 + RplWhoisOperator MessageType = 313 + RplWhoWasUser MessageType = 314 + RplEndOfWho MessageType = 315 + RplWhoisIdle MessageType = 317 + RplEndOfWhois MessageType = 318 + RplWhoisChannels MessageType = 319 + RplListStart MessageType = 321 + RplList MessageType = 322 + RplListEnd MessageType = 323 + RplChannelModeIs MessageType = 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 + RplUniqOpIs MessageType = 325 + RplCreationTime MessageType = 329 + RplNoTopic MessageType = 331 + RplTopic MessageType = 332 + RplTopicWhoTime MessageType = 333 + RplInviting MessageType = 341 + RplSummoning MessageType = 342 + RplInviteList MessageType = 346 + RplEndOfInviteList MessageType = 347 + RplExceptList MessageType = 348 + RplEndOfExceptList MessageType = 349 + RplVersion MessageType = 351 + RplWhoReply MessageType = 352 + RplNamReply MessageType = 353 + RplLinks MessageType = 364 + RplEndOfLinks MessageType = 365 + RplEndOfNames MessageType = 366 + RplBanList MessageType = 367 + RplEndOfBanList MessageType = 368 + RplEndOfWhowas MessageType = 369 + RplInfo MessageType = 371 + RplMotd MessageType = 372 + RplEndOfInfo MessageType = 374 + RplMotdStart MessageType = 375 + RplEndOfMotd MessageType = 376 + RplYoureOper MessageType = 381 + RplRehashing MessageType = 382 + RplYoureService MessageType = 383 + RplTime MessageType = 391 + RplUsersStart MessageType = 392 + RplUsers MessageType = 393 + RplEndOfUsers MessageType = 394 + RplNoUsers MessageType = 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 + ErrNoSuchNick MessageType = 401 + ErrNoSuchServer MessageType = 402 + ErrNoSuchChannel MessageType = 403 + ErrCannotSendToChan MessageType = 404 + ErrTooManyChannels MessageType = 405 + ErrWasNoSuchNick MessageType = 406 + ErrTooManyTargets MessageType = 407 + ErrNoSuchService MessageType = 408 + ErrNoOrigin MessageType = 409 + ErrNoRecipient MessageType = 411 + ErrNoTextToSend MessageType = 412 + ErrNoTopLevel MessageType = 413 + ErrWildTopLevel MessageType = 414 + ErrBadMask MessageType = 415 + ErrUnknownCommand MessageType = 421 + ErrNoMotd MessageType = 422 + ErrNoAdminInfo MessageType = 423 + ErrFileError MessageType = 424 + ErrNoNicknameGiven MessageType = 431 + ErrErroneusNickname MessageType = 432 + ErrNicknameInUse MessageType = 433 + ErrNickCollision MessageType = 436 + ErrUnavailResource MessageType = 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 + ErrUserNotInChannel MessageType = 441 + ErrNotOnChannel MessageType = 442 + ErrUserOnChannel MessageType = 443 + ErrNoLogin MessageType = 444 + ErrSummonDisabled MessageType = 445 + ErrUsersDisabled MessageType = 446 + ErrNotRegistered MessageType = 451 + ErrNeedMoreParams MessageType = 461 + ErrAlreadyRegistered MessageType = 462 + ErrNoPermForHost MessageType = 463 + ErrPasswdMismatch MessageType = 464 + ErrYoureBannedCreep MessageType = 465 + ErrYouWillBeBanned MessageType = 466 + ErrKeySet MessageType = 467 + ErrChannelIsFull MessageType = 471 + ErrUnknownMode MessageType = 472 + ErrInviteOnlyChan MessageType = 473 + ErrBannedFromChan MessageType = 474 + ErrBadChannelKey MessageType = 475 + ErrBadChanMask MessageType = 476 + ErrNoChanModes MessageType = 477 + ErrBanListFull MessageType = 478 + ErrNoPrivileges MessageType = 481 + ErrChanOpPrivsNeeded MessageType = 482 + ErrCantKillServer MessageType = 483 + ErrRestricted MessageType = 484 + ErrUniqOpPrivsNeeded MessageType = 485 + ErrNoOperHost MessageType = 491 - ErrUmodeUnknownFlag = 501 - ErrUsersDoNotMatch = 502 + ErrUmodeUnknownFlag MessageType = 501 + ErrUsersDoNotMatch MessageType = 502 ) // names maps numeric codes to their standard IRC names. // //nolint:gochecknoglobals -var names = map[int]string{ +var names = map[MessageType]string{ RplWelcome: "RPL_WELCOME", RplYourHost: "RPL_YOURHOST", RplCreated: "RPL_CREATED", @@ -332,6 +350,6 @@ var names = map[int]string{ // 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 { +func Name(code MessageType) string { return names[code] }