refactor: add irc.MessageType custom type with Name() and String() methods
All checks were successful
check / check (push) Successful in 2m28s

- Create 'type MessageType int' in pkg/irc/numerics.go
- Type all Rpl*/Err* numeric constants as MessageType
- Add Name() method returning the standard IRC name (e.g. RPL_WELCOME)
- Add String() method returning zero-padded numeric (e.g. 001)
- Update enqueueNumeric/respondIRCError to accept MessageType
- Update internal/db to use MessageType conversion for Name() calls
- Change names map key type from int to MessageType

Refs #52
This commit is contained in:
clawbot
2026-03-10 10:17:57 -07:00
parent fa347772f2
commit 164fec3fc8
3 changed files with 171 additions and 153 deletions

View File

@@ -746,7 +746,7 @@ func scanMessages(
code, _ := strconv.Atoi(msg.Command) code, _ := strconv.Atoi(msg.Command)
msg.Code = code msg.Code = code
if name := irc.Name(code); name != "" { if name := irc.Name(irc.MessageType(code)); name != "" {
msg.Command = name msg.Command = name
} }
} }

View File

@@ -398,12 +398,12 @@ func (hdlr *Handlers) serverName() string {
func (hdlr *Handlers) enqueueNumeric( func (hdlr *Handlers) enqueueNumeric(
ctx context.Context, ctx context.Context,
clientID int64, clientID int64,
code int, code irc.MessageType,
nick string, nick string,
params []string, params []string,
text string, text string,
) { ) {
command := fmt.Sprintf("%03d", code) command := code.String()
body, err := json.Marshal([]string{text}) body, err := json.Marshal([]string{text})
if err != nil { if err != nil {
@@ -969,7 +969,7 @@ func (hdlr *Handlers) respondIRCError(
writer http.ResponseWriter, writer http.ResponseWriter,
request *http.Request, request *http.Request,
clientID, sessionID int64, clientID, sessionID int64,
code int, code irc.MessageType,
nick string, nick string,
params []string, params []string,
text string, text string,

View File

@@ -3,176 +3,194 @@
// RFC 1459 and RFC 2812, and standard command names. // RFC 1459 and RFC 2812, and standard command names.
package irc 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). // Connection registration replies (001-005).
const ( const (
RplWelcome = 1 RplWelcome MessageType = 1
RplYourHost = 2 RplYourHost MessageType = 2
RplCreated = 3 RplCreated MessageType = 3
RplMyInfo = 4 RplMyInfo MessageType = 4
RplBounce = 5 // RFC 2812; also known as RPL_ISUPPORT in practice RplBounce MessageType = 5 // RFC 2812; also known as RPL_ISUPPORT in practice
RplIsupport = 5 // De-facto standard (same numeric as RplBounce) RplIsupport MessageType = 5 // De-facto standard (same numeric as RplBounce)
) )
// Command responses (200-399). // Command responses (200-399).
const ( const (
// RFC 2812 trace/stats/links replies (200-219). // RFC 2812 trace/stats/links replies (200-219).
RplTraceLink = 200 RplTraceLink MessageType = 200
RplTraceConnecting = 201 RplTraceConnecting MessageType = 201
RplTraceHandshake = 202 RplTraceHandshake MessageType = 202
RplTraceUnknown = 203 RplTraceUnknown MessageType = 203
RplTraceOperator = 204 RplTraceOperator MessageType = 204
RplTraceUser = 205 RplTraceUser MessageType = 205
RplTraceServer = 206 RplTraceServer MessageType = 206
RplTraceService = 207 RplTraceService MessageType = 207
RplTraceNewType = 208 RplTraceNewType MessageType = 208
RplTraceClass = 209 RplTraceClass MessageType = 209
RplStatsLinkInfo = 211 RplStatsLinkInfo MessageType = 211
RplStatsCommands = 212 RplStatsCommands MessageType = 212
RplStatsCLine = 213 RplStatsCLine MessageType = 213
RplStatsNLine = 214 RplStatsNLine MessageType = 214
RplStatsILine = 215 RplStatsILine MessageType = 215
RplStatsKLine = 216 RplStatsKLine MessageType = 216
RplStatsQLine = 217 RplStatsQLine MessageType = 217
RplStatsYLine = 218 RplStatsYLine MessageType = 218
RplEndOfStats = 219 RplEndOfStats MessageType = 219
RplUmodeIs = 221 RplUmodeIs MessageType = 221
RplServList = 234 RplServList MessageType = 234
RplServListEnd = 235 RplServListEnd MessageType = 235
RplStatsLLine = 241 RplStatsLLine MessageType = 241
RplStatsUptime = 242 RplStatsUptime MessageType = 242
RplStatsOLine = 243 RplStatsOLine MessageType = 243
RplStatsHLine = 244 RplStatsHLine MessageType = 244
RplLuserClient = 251 RplLuserClient MessageType = 251
RplLuserOp = 252 RplLuserOp MessageType = 252
RplLuserUnknown = 253 RplLuserUnknown MessageType = 253
RplLuserChannels = 254 RplLuserChannels MessageType = 254
RplLuserMe = 255 RplLuserMe MessageType = 255
RplAdminMe = 256 RplAdminMe MessageType = 256
RplAdminLoc1 = 257 RplAdminLoc1 MessageType = 257
RplAdminLoc2 = 258 RplAdminLoc2 MessageType = 258
RplAdminEmail = 259 RplAdminEmail MessageType = 259
RplTraceLog = 261 RplTraceLog MessageType = 261
RplTraceEnd = 262 RplTraceEnd MessageType = 262
RplTryAgain = 263 RplTryAgain MessageType = 263
RplAway = 301 RplAway MessageType = 301
RplUserHost = 302 RplUserHost MessageType = 302
RplIson = 303 RplIson MessageType = 303
RplUnaway = 305 RplUnaway MessageType = 305
RplNowAway = 306 RplNowAway MessageType = 306
RplWhoisUser = 311 RplWhoisUser MessageType = 311
RplWhoisServer = 312 RplWhoisServer MessageType = 312
RplWhoisOperator = 313 RplWhoisOperator MessageType = 313
RplWhoWasUser = 314 RplWhoWasUser MessageType = 314
RplEndOfWho = 315 RplEndOfWho MessageType = 315
RplWhoisIdle = 317 RplWhoisIdle MessageType = 317
RplEndOfWhois = 318 RplEndOfWhois MessageType = 318
RplWhoisChannels = 319 RplWhoisChannels MessageType = 319
RplListStart = 321 RplListStart MessageType = 321
RplList = 322 RplList MessageType = 322
RplListEnd = 323 RplListEnd MessageType = 323
RplChannelModeIs = 324 RplChannelModeIs MessageType = 324
RplUniqOpIs = 325 RplUniqOpIs MessageType = 325
RplCreationTime = 329 RplCreationTime MessageType = 329
RplNoTopic = 331 RplNoTopic MessageType = 331
RplTopic = 332 RplTopic MessageType = 332
RplTopicWhoTime = 333 RplTopicWhoTime MessageType = 333
RplInviting = 341 RplInviting MessageType = 341
RplSummoning = 342 RplSummoning MessageType = 342
RplInviteList = 346 RplInviteList MessageType = 346
RplEndOfInviteList = 347 RplEndOfInviteList MessageType = 347
RplExceptList = 348 RplExceptList MessageType = 348
RplEndOfExceptList = 349 RplEndOfExceptList MessageType = 349
RplVersion = 351 RplVersion MessageType = 351
RplWhoReply = 352 RplWhoReply MessageType = 352
RplNamReply = 353 RplNamReply MessageType = 353
RplLinks = 364 RplLinks MessageType = 364
RplEndOfLinks = 365 RplEndOfLinks MessageType = 365
RplEndOfNames = 366 RplEndOfNames MessageType = 366
RplBanList = 367 RplBanList MessageType = 367
RplEndOfBanList = 368 RplEndOfBanList MessageType = 368
RplEndOfWhowas = 369 RplEndOfWhowas MessageType = 369
RplInfo = 371 RplInfo MessageType = 371
RplMotd = 372 RplMotd MessageType = 372
RplEndOfInfo = 374 RplEndOfInfo MessageType = 374
RplMotdStart = 375 RplMotdStart MessageType = 375
RplEndOfMotd = 376 RplEndOfMotd MessageType = 376
RplYoureOper = 381 RplYoureOper MessageType = 381
RplRehashing = 382 RplRehashing MessageType = 382
RplYoureService = 383 RplYoureService MessageType = 383
RplTime = 391 RplTime MessageType = 391
RplUsersStart = 392 RplUsersStart MessageType = 392
RplUsers = 393 RplUsers MessageType = 393
RplEndOfUsers = 394 RplEndOfUsers MessageType = 394
RplNoUsers = 395 RplNoUsers MessageType = 395
) )
// Error replies (400-599). // Error replies (400-599).
const ( const (
ErrNoSuchNick = 401 ErrNoSuchNick MessageType = 401
ErrNoSuchServer = 402 ErrNoSuchServer MessageType = 402
ErrNoSuchChannel = 403 ErrNoSuchChannel MessageType = 403
ErrCannotSendToChan = 404 ErrCannotSendToChan MessageType = 404
ErrTooManyChannels = 405 ErrTooManyChannels MessageType = 405
ErrWasNoSuchNick = 406 ErrWasNoSuchNick MessageType = 406
ErrTooManyTargets = 407 ErrTooManyTargets MessageType = 407
ErrNoSuchService = 408 ErrNoSuchService MessageType = 408
ErrNoOrigin = 409 ErrNoOrigin MessageType = 409
ErrNoRecipient = 411 ErrNoRecipient MessageType = 411
ErrNoTextToSend = 412 ErrNoTextToSend MessageType = 412
ErrNoTopLevel = 413 ErrNoTopLevel MessageType = 413
ErrWildTopLevel = 414 ErrWildTopLevel MessageType = 414
ErrBadMask = 415 ErrBadMask MessageType = 415
ErrUnknownCommand = 421 ErrUnknownCommand MessageType = 421
ErrNoMotd = 422 ErrNoMotd MessageType = 422
ErrNoAdminInfo = 423 ErrNoAdminInfo MessageType = 423
ErrFileError = 424 ErrFileError MessageType = 424
ErrNoNicknameGiven = 431 ErrNoNicknameGiven MessageType = 431
ErrErroneusNickname = 432 ErrErroneusNickname MessageType = 432
ErrNicknameInUse = 433 ErrNicknameInUse MessageType = 433
ErrNickCollision = 436 ErrNickCollision MessageType = 436
ErrUnavailResource = 437 ErrUnavailResource MessageType = 437
ErrUserNotInChannel = 441 ErrUserNotInChannel MessageType = 441
ErrNotOnChannel = 442 ErrNotOnChannel MessageType = 442
ErrUserOnChannel = 443 ErrUserOnChannel MessageType = 443
ErrNoLogin = 444 ErrNoLogin MessageType = 444
ErrSummonDisabled = 445 ErrSummonDisabled MessageType = 445
ErrUsersDisabled = 446 ErrUsersDisabled MessageType = 446
ErrNotRegistered = 451 ErrNotRegistered MessageType = 451
ErrNeedMoreParams = 461 ErrNeedMoreParams MessageType = 461
ErrAlreadyRegistered = 462 ErrAlreadyRegistered MessageType = 462
ErrNoPermForHost = 463 ErrNoPermForHost MessageType = 463
ErrPasswdMismatch = 464 ErrPasswdMismatch MessageType = 464
ErrYoureBannedCreep = 465 ErrYoureBannedCreep MessageType = 465
ErrYouWillBeBanned = 466 ErrYouWillBeBanned MessageType = 466
ErrKeySet = 467 ErrKeySet MessageType = 467
ErrChannelIsFull = 471 ErrChannelIsFull MessageType = 471
ErrUnknownMode = 472 ErrUnknownMode MessageType = 472
ErrInviteOnlyChan = 473 ErrInviteOnlyChan MessageType = 473
ErrBannedFromChan = 474 ErrBannedFromChan MessageType = 474
ErrBadChannelKey = 475 ErrBadChannelKey MessageType = 475
ErrBadChanMask = 476 ErrBadChanMask MessageType = 476
ErrNoChanModes = 477 ErrNoChanModes MessageType = 477
ErrBanListFull = 478 ErrBanListFull MessageType = 478
ErrNoPrivileges = 481 ErrNoPrivileges MessageType = 481
ErrChanOpPrivsNeeded = 482 ErrChanOpPrivsNeeded MessageType = 482
ErrCantKillServer = 483 ErrCantKillServer MessageType = 483
ErrRestricted = 484 ErrRestricted MessageType = 484
ErrUniqOpPrivsNeeded = 485 ErrUniqOpPrivsNeeded MessageType = 485
ErrNoOperHost = 491 ErrNoOperHost MessageType = 491
ErrUmodeUnknownFlag = 501 ErrUmodeUnknownFlag MessageType = 501
ErrUsersDoNotMatch = 502 ErrUsersDoNotMatch MessageType = 502
) )
// names maps numeric codes to their standard IRC names. // names maps numeric codes to their standard IRC names.
// //
//nolint:gochecknoglobals //nolint:gochecknoglobals
var names = map[int]string{ var names = map[MessageType]string{
RplWelcome: "RPL_WELCOME", RplWelcome: "RPL_WELCOME",
RplYourHost: "RPL_YOURHOST", RplYourHost: "RPL_YOURHOST",
RplCreated: "RPL_CREATED", RplCreated: "RPL_CREATED",
@@ -332,6 +350,6 @@ var names = map[int]string{
// Name returns the standard IRC name for a numeric code // Name returns the standard IRC name for a numeric code
// (e.g., Name(2) returns "RPL_YOURHOST"). Returns an // (e.g., Name(2) returns "RPL_YOURHOST"). Returns an
// empty string if the code is unknown. // empty string if the code is unknown.
func Name(code int) string { func Name(code MessageType) string {
return names[code] return names[code]
} }