diff --git a/go.mod b/go.mod index b8cd9f8..8d76b05 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.2 require ( github.com/BurntSushi/toml v1.5.0 - github.com/lrstanley/girc v0.0.0-20240914071631-5c0cc76257bf + github.com/lrstanley/girc v1.1.0 mellium.im/sasl v0.3.2 mellium.im/xmpp v0.22.0 ) diff --git a/go.sum b/go.sum index 23d806f..c8dbeb3 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/lrstanley/girc v0.0.0-20240914071631-5c0cc76257bf h1:DptjWYSDVuCSxM++oM/NJInqiD5v+z/PI6T3/OMWJR4= github.com/lrstanley/girc v0.0.0-20240914071631-5c0cc76257bf/go.mod h1:lgrnhcF8bg/Bd5HA5DOb4Z+uGqUqGnp4skr+J2GwVgI= +github.com/lrstanley/girc v1.1.0 h1:LxDIjQIAEM/Dxm+l+fx8osDDGm5T2ZWznkcnjrQCUqE= +github.com/lrstanley/girc v1.1.0/go.mod h1:lgrnhcF8bg/Bd5HA5DOb4Z+uGqUqGnp4skr+J2GwVgI= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= diff --git a/vendor/github.com/lrstanley/girc/.editorconfig b/vendor/github.com/lrstanley/girc/.editorconfig index 4ae34fd..302b0ba 100644 --- a/vendor/github.com/lrstanley/girc/.editorconfig +++ b/vendor/github.com/lrstanley/girc/.editorconfig @@ -33,7 +33,6 @@ indent_size = 2 [*.json] indent_size = 2 -insert_final_newline = ignore [*.html] max_line_length = 140 @@ -47,7 +46,6 @@ indent_style = tab [**.min.js] indent_style = ignore -insert_final_newline = ignore [*.bat] indent_style = tab diff --git a/vendor/github.com/lrstanley/girc/.golangci.yaml b/vendor/github.com/lrstanley/girc/.golangci.yaml new file mode 100644 index 0000000..21a2468 --- /dev/null +++ b/vendor/github.com/lrstanley/girc/.golangci.yaml @@ -0,0 +1,220 @@ +# THIS FILE IS GENERATED! DO NOT EDIT! Maintained by Terraform. +# +# golangci-lint: https://golangci-lint.run/ +# false-positives: https://golangci-lint.run/usage/false-positives/ +# actual source: https://github.com/lrstanley/.github/blob/master/terraform/github-common-files/templates/.golangci.yml +# modified variant of: https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322 + +version: "2" + +formatters: + enable: [gofumpt] + +issues: + max-issues-per-linter: 0 + max-same-issues: 50 + +severity: + default: error + rules: + - linters: + - errcheck + - gocritic + severity: warning + +linters: + default: none + enable: + - asasalint # checks for pass []any as any in variadic func(...any) + - asciicheck # checks that your code does not contain non-ASCII identifiers + - bidichk # checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - canonicalheader # checks whether net/http.Header uses canonical header + - copyloopvar # detects places where loop variables are copied (Go 1.22+) + - depguard # checks if package imports are in a list of acceptable packages + - dupl # tool for code clone detection + - durationcheck # checks for two durations multiplied together + - errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases + - errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error + - errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13 + - exhaustive # checks exhaustiveness of enum switch statements + - exptostd # detects functions from golang.org/x/exp/ that can be replaced by std functions + - fatcontext # detects nested contexts in loops + - forbidigo # forbids identifiers + - funlen # tool for detection of long functions + - gocheckcompilerdirectives # validates go compiler directive comments (//go:) + - gochecknoinits # checks that no init functions are present in Go code + - gochecksumtype # checks exhaustiveness on Go "sum types" + - gocognit # computes and checks the cognitive complexity of functions + - goconst # finds repeated strings that could be replaced by a constant + - gocritic # provides diagnostics that check for bugs, performance and style issues + # TODO: breaks multi-line comments when used with --fix: https://github.com/tetafro/godot/issues/39 + # - godot # checks if comments end in a period + - gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod + - goprintffuncname # checks that printf-like functions are named with f at the end + - gosec # inspects source code for security problems + - govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - iface # checks the incorrect use of interfaces, helping developers avoid interface pollution + - ineffassign # detects when assignments to existing variables are not used + - intrange # finds places where for loops could make use of an integer range + - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) + - makezero # finds slice declarations with non-zero initial length + - mirror # reports wrong mirror patterns of bytes/strings usage + - misspell # [useless] finds commonly misspelled English words in comments + - musttag # enforces field tags in (un)marshaled structs + - nakedret # finds naked returns in functions greater than a specified function length + - nestif # reports deeply nested if statements + - nilerr # finds the code that returns nil even if it checks that the error is not nil + - nilnesserr # reports that it checks for err != nil, but it returns a different nil value error (powered by nilness and nilerr) + - nilnil # checks that there is no simultaneous return of nil error and an invalid value + - noctx # finds sending http request without context.Context + - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL + - perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative + - predeclared # finds code that shadows one of Go's predeclared identifiers + - promlinter # checks Prometheus metrics naming via promlint + - reassign # checks that package variables are not reassigned + - recvcheck # checks for receiver type consistency + - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint + - rowserrcheck # checks whether Err of rows is checked successfully + - sloglint # ensure consistent code style when using log/slog + - sqlclosecheck # checks that sql.Rows and sql.Stmt are closed + - staticcheck # is a go vet on steroids, applying a ton of static analysis checks + - testableexamples # checks if examples are testable (have an expected output) + - testifylint # checks usage of github.com/stretchr/testify + - tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes + - unconvert # removes unnecessary type conversions + - unparam # reports unused function parameters + - unused # checks for unused constants, variables, functions and types + - usestdlibvars # detects the possibility to use variables/constants from the Go standard library + - usetesting # reports uses of functions with replacement inside the testing package + - wastedassign # finds wasted assignment statements + - whitespace # detects leading and trailing whitespace + + settings: + gocognit: + min-complexity: 40 + errcheck: + check-type-assertions: true + funlen: + lines: 150 + statements: 75 + ignore-comments: true + gocritic: + disabled-checks: + - whyNoLint + - hugeParam + - ifElseChain + enabled-tags: + - diagnostic + - opinionated + - performance + - style + settings: + captLocal: + paramsOnly: false + underef: + skipRecvDeref: false + rangeValCopy: + sizeThreshold: 512 + depguard: + rules: + "deprecated": + files: ["$all"] + deny: + - pkg: github.com/golang/protobuf + desc: Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules + - pkg: github.com/satori/go.uuid + desc: Use github.com/google/uuid instead, satori's package is not maintained + - pkg: github.com/gofrs/uuid$ + desc: Use github.com/gofrs/uuid/v5 or later, it was not a go module before v5 + "non-test files": + files: ["!$test"] + deny: + - pkg: math/rand$ + desc: Use math/rand/v2 instead, see https://go.dev/blog/randv2 + "non-main files": + files: ["!**/main.go"] + deny: + - pkg: log$ + desc: Use log/slog instead, see https://go.dev/blog/slog + "incorrect import": + files: ["$test"] + deny: + - pkg: github.com/tj/assert$ + desc: Use github.com/stretchr/testify/assert instead, see + gochecksumtype: + default-signifies-exhaustive: false + exhaustive: + check: + - switch + - map + govet: + disable: + - fieldalignment + enable-all: true + settings: + shadow: + strict: true + perfsprint: + strconcat: false + nakedret: + max-func-lines: 0 + nestif: + min-complexity: 10 + rowserrcheck: + packages: + - github.com/jmoiron/sqlx + sloglint: + no-global: all + context: scope + staticcheck: + checks: + - all + # Incorrect or missing package comment: https://staticcheck.dev/docs/checks/#ST1000 + - -ST1000 + # Use consistent method receiver names: https://staticcheck.dev/docs/checks/#ST1016 + - -ST1016 + # Omit embedded fields from selector expression: https://staticcheck.dev/docs/checks/#QF1008 + - -QF1008 + usetesting: + os-temp-dir: true + exclusions: + warn-unused: true + generated: lax + presets: + - common-false-positives + - std-error-handling + paths: + - ".*\\.gen\\.go$" + - ".*\\.gen_test\\.go$" + rules: + - source: "TODO" + linters: [godot] + - text: "should have a package comment" + linters: [revive] + - text: 'exported \S+ \S+ should have comment( \(or a comment on this block\))? or be unexported' + linters: [revive] + - text: 'package comment should be of the form ".+"' + source: "// ?(nolint|TODO)" + linters: [revive] + - text: 'comment on exported \S+ \S+ should be of the form ".+"' + source: "// ?(nolint|TODO)" + linters: [revive, staticcheck] + - text: 'unexported-return: exported func \S+ returns unexported type \S+ .*' + linters: [revive] + - text: "var-declaration: should drop .* from declaration of .*; it is the zero value" + linters: [revive] + - text: ".*use ALL_CAPS in Go names.*" + linters: [revive, staticcheck] + - text: '.* always receives \S+' + linters: [unparam] + - path: _test\.go + linters: + - bodyclose + - dupl + - funlen + - gocognit + - goconst + - gosec + - noctx + - wrapcheck diff --git a/vendor/github.com/lrstanley/girc/.golangci.yml b/vendor/github.com/lrstanley/girc/.golangci.yml deleted file mode 100644 index c0acb79..0000000 --- a/vendor/github.com/lrstanley/girc/.golangci.yml +++ /dev/null @@ -1,228 +0,0 @@ -# THIS FILE IS GENERATED! DO NOT EDIT! Maintained by Terraform. -# -# golangci-lint: https://golangci-lint.run/ -# false-positives: https://golangci-lint.run/usage/false-positives/ -# actual source: https://github.com/lrstanley/.github/blob/master/terraform/github-common-files/templates/.golangci.yml -# modified variant of: https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322 -# - -run: - timeout: 3m - -issues: - max-issues-per-linter: 0 - max-same-issues: 50 - - exclude-rules: - - source: "(noinspection|TODO)" - linters: [godot] - - source: "//noinspection" - linters: [gocritic] - - path: "_test\\.go" - linters: - - bodyclose - - dupl - - funlen - - goconst - - gosec - - noctx - - wrapcheck - -severity: - default-severity: error - rules: - - linters: - - errcheck - - gocritic - severity: warning - -linters: - disable-all: true - enable: - - asasalint # checks for pass []any as any in variadic func(...any) - - asciicheck # checks that your code does not contain non-ASCII identifiers - - bidichk # checks for dangerous unicode character sequences - - bodyclose # checks whether HTTP response body is closed successfully - - canonicalheader # checks whether net/http.Header uses canonical header - - copyloopvar # detects places where loop variables are copied - - cyclop # checks function and package cyclomatic complexity - - dupl # tool for code clone detection - - durationcheck # checks for two durations multiplied together - - errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases - - errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13 - - exportloopref # checks for pointers to enclosing loop variables - - fatcontext # detects nested contexts in loops - - forbidigo # forbids identifiers - - funlen # tool for detection of long functions - - gci # controls golang package import order and makes it always deterministic - - gocheckcompilerdirectives # validates go compiler directive comments (//go:) - - gochecknoinits # checks that no init functions are present in Go code - - gochecksumtype # checks exhaustiveness on Go "sum types" - - goconst # finds repeated strings that could be replaced by a constant - - gocritic # provides diagnostics that check for bugs, performance and style issues - - gocyclo # computes and checks the cyclomatic complexity of functions - - godot # checks if comments end in a period - - godox # detects FIXME, TODO and other comment keywords - - goimports # in addition to fixing imports, goimports also formats your code in the same style as gofmt - - gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod - - gomodguard # allow and block lists linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations - - goprintffuncname # checks that printf-like functions are named with f at the end - - gosec # inspects source code for security problems - - gosimple # specializes in simplifying a code - - govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - ineffassign # detects when assignments to existing variables are not used - - intrange # finds places where for loops could make use of an integer range - - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) - - makezero # finds slice declarations with non-zero initial length - - misspell # finds commonly misspelled words - - musttag # enforces field tags in (un)marshaled structs - - nakedret # finds naked returns in functions greater than a specified function length - - nilerr # finds the code that returns nil even if it checks that the error is not nil - - nilnil # checks that there is no simultaneous return of nil error and an invalid value - - noctx # finds sending http request without context.Context - - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL - - perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative - - predeclared # finds code that shadows one of Go's predeclared identifiers - - promlinter # checks Prometheus metrics naming via promlint - - reassign # checks that package variables are not reassigned - - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint - - rowserrcheck # checks whether Err of rows is checked successfully - - sloglint # ensure consistent code style when using log/slog - - sqlclosecheck # checks that sql.Rows and sql.Stmt are closed - - staticcheck # is a go vet on steroids, applying a ton of static analysis checks - - stylecheck # is a replacement for golint - # - tagalign # aligns struct tags -- disable for now (https://github.com/4meepo/tagalign/issues/13) - - tenv # detects using os.Setenv instead of t.Setenv since Go1.17 - - testableexamples # checks if examples are testable (have an expected output) - - testifylint # checks usage of github.com/stretchr/testify - - tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes - - typecheck # like the front-end of a Go compiler, parses and type-checks Go code - - unconvert # removes unnecessary type conversions - - unparam # reports unused function parameters - - unused # checks for unused constants, variables, functions and types - - usestdlibvars # detects the possibility to use variables/constants from the Go standard library - - wastedassign # finds wasted assignment statements - - whitespace # detects leading and trailing whitespace - -linters-settings: - cyclop: - # The maximal code complexity to report. - max-complexity: 30 - # The maximal average package complexity. - # If it's higher than 0.0 (float) the check is enabled - package-average: 10.0 - - errcheck: - # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. - # Such cases aren't reported by default. - check-type-assertions: true - - funlen: - # Checks the number of lines in a function. - lines: 150 - # Checks the number of statements in a function. - statements: 75 - # Ignore comments. - ignore-comments: true - - gocritic: - disabled-checks: - - whyNoLint - - hugeParam - - ifElseChain - enabled-tags: - - diagnostic - - opinionated - - performance - - style - # https://go-critic.github.io/overview. - settings: - captLocal: - # Whether to restrict checker to params only. - paramsOnly: false - underef: - # Whether to skip (*x).method() calls where x is a pointer receiver. - skipRecvDeref: false - - gomodguard: - blocked: - # List of blocked modules. - modules: - - github.com/golang/protobuf: - recommendations: - - google.golang.org/protobuf - reason: "see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules" - - github.com/satori/go.uuid: - recommendations: - - github.com/google/uuid - reason: "satori's package is not maintained" - - github.com/gofrs/uuid: - recommendations: - - github.com/google/uuid - reason: "gofrs' package is not go module" - - govet: - enable-all: true - # Run `go tool vet help` to see all analyzers. - disable: - - fieldalignment # too strict - settings: - shadow: - # Whether to be strict about shadowing; can be noisy. - strict: true - - nakedret: - # Make an issue if func has more lines of code than this setting, and it has naked returns. - max-func-lines: 0 - - rowserrcheck: - # database/sql is always checked - packages: - - github.com/jmoiron/sqlx - - stylecheck: - checks: - - all - - -ST1008 # handled by revive already. - - sloglint: - # Enforce not using global loggers. - no-global: "all" - # Enforce using methods that accept a context. - context: "scope" - - tagalign: - align: true - sort: true - order: - # go-flags items - - command - - alias - - group - - namespace - - env-namespace - - subcommands-optional - - env - - env-delim - - short - - long - - no-flag - - hidden - - required - - value-name - - default - - choice - - description - - long-description - # everything else - - json - - yaml - - yml - - toml - - validate - strict: false - - tenv: - # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. - # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. - all: true diff --git a/vendor/github.com/lrstanley/girc/builtin.go b/vendor/github.com/lrstanley/girc/builtin.go index 345452e..401565a 100644 --- a/vendor/github.com/lrstanley/girc/builtin.go +++ b/vendor/github.com/lrstanley/girc/builtin.go @@ -102,7 +102,7 @@ func handleConnect(c *Client, e Event) { // nickCollisionHandler helps prevent the client from having conflicting // nicknames with another bot, user, etc. -func nickCollisionHandler(c *Client, e Event) { +func nickCollisionHandler(c *Client, _ Event) { if c.Config.HandleNickCollide == nil { c.Cmd.Nick(c.GetNick() + "_") return @@ -119,7 +119,7 @@ func handlePING(c *Client, e Event) { c.Cmd.Pong(e.Last()) } -func handlePONG(c *Client, e Event) { +func handlePONG(c *Client, _ Event) { c.conn.mu.Lock() c.conn.lastPong = time.Now() c.conn.mu.Unlock() @@ -223,14 +223,19 @@ func handlePART(c *Client, e Event) { // handleTOPIC handles incoming TOPIC events and keeps channel tracking info // updated with the latest channel topic. func handleTOPIC(c *Client, e Event) { - var name string + var name, topic string switch len(e.Params) { case 0: return - case 1: + case 1: // TOPIC, message format is `TOPIC ` name = e.Params[0] - default: + topic = "" + case 2: // TOPIC, message format is `TOPIC :` + name = e.Params[0] + topic = e.Last() + default: // RPL_TOPIC, message format is `332 :` name = e.Params[1] + topic = e.Last() } c.state.Lock() @@ -240,7 +245,7 @@ func handleTOPIC(c *Client, e Event) { return } - channel.Topic = e.Last() + channel.Topic = topic c.state.Unlock() c.state.notify(c, UPDATE_STATE) } @@ -508,7 +513,6 @@ func handleNAMES(c *Client, e Event) { if s == nil { continue } - } else { s = &Source{ Name: nick, diff --git a/vendor/github.com/lrstanley/girc/cap.go b/vendor/github.com/lrstanley/girc/cap.go index f35f2ec..e502035 100644 --- a/vendor/github.com/lrstanley/girc/cap.go +++ b/vendor/github.com/lrstanley/girc/cap.go @@ -117,6 +117,8 @@ func parseCap(raw string) map[string]map[string]string { // handleCAP attempts to find out what IRCv3 capabilities the server supports. // This will lock further registration until we have acknowledged (or denied) // the capabilities. +// +//nolint:nestif,gocognit func handleCAP(c *Client, e Event) { c.state.Lock() defer c.state.Unlock() diff --git a/vendor/github.com/lrstanley/girc/cap_tags.go b/vendor/github.com/lrstanley/girc/cap_tags.go index 3cc8887..718ab21 100644 --- a/vendor/github.com/lrstanley/girc/cap_tags.go +++ b/vendor/github.com/lrstanley/girc/cap_tags.go @@ -64,7 +64,7 @@ type Tags map[string]string func ParseTags(raw string) (t Tags) { t = make(Tags) - if len(raw) > 0 && raw[0] == prefixTag { + if raw != "" && raw[0] == prefixTag { raw = raw[1:] } @@ -143,8 +143,8 @@ func (t Tags) Bytes() []byte { return []byte{} } - max := len(t) - if max == 0 { + maxb := len(t) + if maxb == 0 { return nil } @@ -170,13 +170,13 @@ func (t Tags) Bytes() []byte { buffer.WriteString(names[i]) // Write the value as necessary. - if len(t[names[i]]) > 0 { + if t[names[i]] != "" { buffer.WriteByte(prefixTagValue) buffer.WriteString(t[names[i]]) } // add the separator ";" between tags. - if current < max-1 { + if current < maxb-1 { buffer.WriteByte(tagSeparator) } @@ -263,7 +263,7 @@ func (t Tags) Set(key, value string) error { value = tagEncoder.Replace(value) - if len(value) > 0 && !validTagValue(value) { + if value != "" && !validTagValue(value) { return fmt.Errorf("tag value %q of key %q is invalid", value, key) } diff --git a/vendor/github.com/lrstanley/girc/client.go b/vendor/github.com/lrstanley/girc/client.go index 9376619..c36b8cf 100644 --- a/vendor/github.com/lrstanley/girc/client.go +++ b/vendor/github.com/lrstanley/girc/client.go @@ -10,7 +10,7 @@ import ( "errors" "fmt" "io" - "log" + "log" //nolint:depguard "net" "os" "runtime" @@ -210,19 +210,24 @@ func (w WebIRC) Params() []string { return []string{w.Password, w.Gateway, w.Hostname, w.Address} } -// ErrInvalidConfig is returned when the configuration passed to the client +// ErrInvalidConfig is aliased to InvalidConfigError. +// +// Deprecated: use InvalidConfigError instead. +type ErrInvalidConfig = InvalidConfigError //nolint:errname + +// InvalidConfigError is returned when the configuration passed to the client // is invalid. -type ErrInvalidConfig struct { +type InvalidConfigError struct { Conf Config // Conf is the configuration that was not valid. err error } -func (e ErrInvalidConfig) Error() string { return "invalid configuration: " + e.err.Error() } +func (e InvalidConfigError) Error() string { return "invalid configuration: " + e.err.Error() } // isValid checks some basic settings to ensure the config is valid. func (conf *Config) isValid() error { if conf.Server == "" { - return &ErrInvalidConfig{Conf: *conf, err: errors.New("empty server")} + return &InvalidConfigError{Conf: *conf, err: errors.New("empty server")} } // Default port to 6667 (the standard IRC port). @@ -231,14 +236,14 @@ func (conf *Config) isValid() error { } if conf.Port < 1 || conf.Port > 65535 { - return &ErrInvalidConfig{Conf: *conf, err: errors.New("port outside valid range (1-65535)")} + return &InvalidConfigError{Conf: *conf, err: errors.New("port outside valid range (1-65535)")} } if !IsValidNick(conf.Nick) { - return &ErrInvalidConfig{Conf: *conf, err: errors.New("bad nickname specified")} + return &InvalidConfigError{Conf: *conf, err: errors.New("bad nickname specified")} } if !IsValidUser(conf.User) { - return &ErrInvalidConfig{Conf: *conf, err: errors.New("bad user/ident specified")} + return &InvalidConfigError{Conf: *conf, err: errors.New("bad user/ident specified")} } return nil @@ -386,14 +391,19 @@ func (c *Client) Quit(reason string) { c.Send(&Event{Command: QUIT, Params: []string{reason}}) } -// ErrEvent is an error returned when the server (or library) sends an ERROR +// ErrEvent is an alias to EventError. +// +// Deprecated: use EventError instead. +type ErrEvent = EventError //nolint:errname + +// EventError is an error returned when the server (or library) sends an ERROR // message response. The string returned contains the trailing text from the // message. -type ErrEvent struct { +type EventError struct { Event *Event } -func (e *ErrEvent) Error() string { +func (e *EventError) Error() string { if e.Event == nil { return "unknown error occurred" } @@ -438,7 +448,7 @@ func (c *Client) execLoop(ctx context.Context) error { // if this library is the source of the error, this should // signal back up to the main connect loop, to disconnect. - return &ErrEvent{Event: event} + return &EventError{Event: event} } } } @@ -723,12 +733,12 @@ func (c *Client) GetServerOptionInt(key string) (result int, ok bool) { // by the protocol. If state tracking is enabled, this will utilize ISUPPORT/IRCv3 // information to more accurately calculate the maximum supported length (i.e. extended // length events). -func (c *Client) MaxEventLength() (max int) { +func (c *Client) MaxEventLength() (maxLen int) { if !c.Config.disableTracking { c.state.RLock() - max = c.state.maxLineLength - c.state.maxPrefixLength + maxLen = c.state.maxLineLength - c.state.maxPrefixLength c.state.RUnlock() - return max + return maxLen } return DefaultMaxLineLength - DefaultMaxPrefixLength } diff --git a/vendor/github.com/lrstanley/girc/commands.go b/vendor/github.com/lrstanley/girc/commands.go index a3bec87..837b07b 100644 --- a/vendor/github.com/lrstanley/girc/commands.go +++ b/vendor/github.com/lrstanley/girc/commands.go @@ -26,12 +26,12 @@ func (cmd *Commands) Nick(name string) { func (cmd *Commands) Join(channels ...string) { // We can join multiple channels at once, however we need to ensure that // we are not exceeding the line length (see Client.MaxEventLength()). - max := cmd.c.MaxEventLength() - len(JOIN) - 1 + maxLen := cmd.c.MaxEventLength() - len(JOIN) - 1 var buffer string for i := 0; i < len(channels); i++ { - if len(buffer+","+channels[i]) > max { + if len(buffer+","+channels[i]) > maxLen { cmd.c.Send(&Event{Command: JOIN, Params: []string{buffer}}) buffer = "" continue @@ -330,12 +330,12 @@ func (cmd *Commands) List(channels ...string) { // We can LIST multiple channels at once, however we need to ensure that // we are not exceeding the line length (see Client.MaxEventLength()). - max := cmd.c.MaxEventLength() - len(JOIN) - 1 + maxLen := cmd.c.MaxEventLength() - len(JOIN) - 1 var buffer string for i := 0; i < len(channels); i++ { - if len(buffer+","+channels[i]) > max { + if len(buffer+","+channels[i]) > maxLen { cmd.c.Send(&Event{Command: LIST, Params: []string{buffer}}) buffer = "" continue diff --git a/vendor/github.com/lrstanley/girc/conn.go b/vendor/github.com/lrstanley/girc/conn.go index 58a0a60..1467817 100644 --- a/vendor/github.com/lrstanley/girc/conn.go +++ b/vendor/github.com/lrstanley/girc/conn.go @@ -8,8 +8,9 @@ import ( "bufio" "context" "crypto/tls" - "fmt" + "errors" "net" + "strconv" "sync" "time" @@ -96,21 +97,7 @@ func newConn(conf Config, dialer Dialer, addr string, sts *strictTransport) (*ir } if conf.SSL || sts.enabled() { - var tlsConn net.Conn - tlsConn, err = tlsHandshake(conn, conf.TLSConfig, conf.Server, true) - if err != nil { - if sts.enabled() { - err = &ErrSTSUpgradeFailed{Err: err} - } - - if sts.expired() && !conf.DisableSTSFallback { - sts.lastFailed = time.Now() - sts.reset() - } - return nil, err - } - - conn = tlsConn + conn = tlsHandshake(conn, conf.TLSConfig, conf.Server, true) } ctime := time.Now() @@ -137,12 +124,17 @@ func newMockConn(conn net.Conn) *ircConn { return c } -// ErrParseEvent is returned when an event cannot be parsed with ParseEvent(). -type ErrParseEvent struct { +// ErrParseEvent is aliased to ParseEventError. +// +// Deprecated: use ParseEventError instead. +type ErrParseEvent = ParseEventError //nolint:errname + +// ParseEventError is returned when an event cannot be parsed with ParseEvent(). +type ParseEventError struct { Line string } -func (e ErrParseEvent) Error() string { return "unable to parse event: " + e.Line } +func (e ParseEventError) Error() string { return "unable to parse event: " + e.Line } type decodedEvent struct { event *Event @@ -188,13 +180,13 @@ func (c *ircConn) newReadWriter() { c.io = bufio.NewReadWriter(bufio.NewReader(c.sock), bufio.NewWriter(c.sock)) } -func tlsHandshake(conn net.Conn, conf *tls.Config, server string, validate bool) (net.Conn, error) { +func tlsHandshake(conn net.Conn, conf *tls.Config, server string, validate bool) net.Conn { if conf == nil { - conf = &tls.Config{ServerName: server, InsecureSkipVerify: !validate} + conf = &tls.Config{ServerName: server, InsecureSkipVerify: !validate} //nolint:gosec } tlsConn := tls.Client(conn, conf) - return net.Conn(tlsConn), nil + return net.Conn(tlsConn) } // Close closes the underlying socket. @@ -296,7 +288,8 @@ startConn: c.debug.Printf("connecting to %s... (sts: %v, config-ssl: %v)", addr, c.state.sts.enabled(), c.Config.SSL) conn, err := newConn(c.Config, dialer, addr, &c.state.sts) if err != nil { - if _, ok := err.(*ErrSTSUpgradeFailed); ok { + errSTSUpgradeFailed := &ErrSTSUpgradeFailed{} + if errors.As(err, &errSTSUpgradeFailed) { if !c.state.sts.enabled() { c.RunHandlers(&Event{Command: STS_ERR_FALLBACK}) } @@ -446,8 +439,7 @@ func (c *Client) Send(event *Event) { event.Params[len(event.Params)-1] = Fmt(event.Params[len(event.Params)-1]) } - var events []*Event - events = event.split(c.MaxEventLength()) + events := event.split(c.MaxEventLength()) for _, e := range events { if !c.Config.AllowFlood { @@ -573,9 +565,14 @@ func (c *Client) sendLoop(ctx context.Context) error { } } -// ErrTimedOut is returned when we attempt to ping the server, and timed out +// ErrTimedOut is aliased to TimedOutError. +// +// Deprecated: use TimedOutError instead. +type ErrTimedOut = TimedOutError //nolint:errname + +// TimedOutError is returned when we attempt to ping the server, and timed out // before receiving a PONG back. -type ErrTimedOut struct { +type TimedOutError struct { // TimeSinceSuccess is how long ago we received a successful pong. TimeSinceSuccess time.Duration // LastPong is the time we received our last successful pong. @@ -586,7 +583,7 @@ type ErrTimedOut struct { Delay time.Duration } -func (ErrTimedOut) Error() string { return "timed out waiting for a requested PING response" } +func (TimedOutError) Error() string { return "timed out waiting for a requested PING response" } func (c *Client) pingLoop(ctx context.Context) error { // Don't run the pingLoop if they want to disable it. @@ -641,7 +638,7 @@ func (c *Client) pingLoop(ctx context.Context) error { c.conn.lastPing = time.Now() c.conn.mu.Unlock() - c.Cmd.Ping(fmt.Sprintf("%d", time.Now().UnixNano())) + c.Cmd.Ping(strconv.FormatInt(time.Now().UnixNano(), 10)) pingSent = true case <-ctx.Done(): return nil diff --git a/vendor/github.com/lrstanley/girc/ctcp.go b/vendor/github.com/lrstanley/girc/ctcp.go index 9e35d69..8e75610 100644 --- a/vendor/github.com/lrstanley/girc/ctcp.go +++ b/vendor/github.com/lrstanley/girc/ctcp.go @@ -110,7 +110,7 @@ func EncodeCTCPRaw(cmd, text string) (out string) { out = string(ctcpDelim) + cmd - if len(text) > 0 { + if text != "" { out += string(eventSpace) + text } diff --git a/vendor/github.com/lrstanley/girc/event.go b/vendor/github.com/lrstanley/girc/event.go index 2622f89..7e3b708 100644 --- a/vendor/github.com/lrstanley/girc/event.go +++ b/vendor/github.com/lrstanley/girc/event.go @@ -331,7 +331,7 @@ func (e *Event) Len() (length int) { // supports), which may be useful if you are trying to check and see if a message is // too long, to trim it down yourself. func (e *Event) LenOpts(includeTags bool) (length int) { - if e.Tags != nil { + if e.Tags != nil && includeTags { // Include tags and trailing space. length = e.Tags.Len() + 1 } @@ -357,7 +357,7 @@ func (e *Event) LenOpts(includeTags bool) (length int) { } } - return + return length } // Bytes returns a []byte representation of event. Strips all newlines and @@ -367,7 +367,7 @@ func (e *Event) Bytes() []byte { // Tags. if e.Tags != nil { - e.Tags.writeTo(buffer) + _, _ = e.Tags.writeTo(buffer) } // Event prefix. @@ -416,7 +416,7 @@ func (e *Event) String() string { // support prettification, ok is false. Pretty is not just useful to make // an event prettier, but also to filter out events that most don't visually // see in normal IRC clients. e.g. most clients don't show WHO queries. -func (e *Event) Pretty() (out string, ok bool) { +func (e *Event) Pretty() (out string, ok bool) { //nolint:gocognit if e.Sensitive || e.Echo { return "", false } @@ -448,7 +448,7 @@ func (e *Event) Pretty() (out string, ok bool) { if (e.Command == PRIVMSG || e.Command == NOTICE) && len(e.Params) > 0 { if ctcp := DecodeCTCP(e); ctcp != nil { if ctcp.Reply { - return + return out, ok } if ctcp.Command == CTCP_ACTION { @@ -678,14 +678,14 @@ func ParseSource(raw string) (src *Source) { // Len calculates the length of the string representation of prefix func (s *Source) Len() (length int) { length = len(s.Name) - if len(s.Ident) > 0 { + if s.Ident != "" { length = 1 + length + len(s.Ident) } - if len(s.Host) > 0 { + if s.Host != "" { length = 1 + length + len(s.Host) } - return + return length } // Bytes returns a []byte representation of source. @@ -699,19 +699,19 @@ func (s *Source) Bytes() []byte { // String returns a string representation of source. func (s *Source) String() (out string) { out = s.Name - if len(s.Ident) > 0 { + if s.Ident != "" { out = out + string(prefixIdent) + s.Ident } - if len(s.Host) > 0 { + if s.Host != "" { out = out + string(prefixHost) + s.Host } - return + return out } // IsHostmask returns true if source looks like a user hostmask. func (s *Source) IsHostmask() bool { - return len(s.Ident) > 0 && len(s.Host) > 0 + return s.Ident != "" && s.Host != "" } // IsServer returns true if this source looks like a server name. @@ -723,11 +723,11 @@ func (s *Source) IsServer() bool { // in Event.String(). func (s *Source) writeTo(buffer *bytes.Buffer) { buffer.WriteString(s.Name) - if len(s.Ident) > 0 { + if s.Ident != "" { buffer.WriteByte(prefixIdent) buffer.WriteString(s.Ident) } - if len(s.Host) > 0 { + if s.Host != "" { buffer.WriteByte(prefixHost) buffer.WriteString(s.Host) } diff --git a/vendor/github.com/lrstanley/girc/format.go b/vendor/github.com/lrstanley/girc/format.go index 3b9d60a..26dac2a 100644 --- a/vendor/github.com/lrstanley/girc/format.go +++ b/vendor/github.com/lrstanley/girc/format.go @@ -83,7 +83,7 @@ func Fmt(text string) string { continue } - if text[i] == fmtCloseChar && last > -1 { + if text[i] == fmtCloseChar && last > -1 { //nolint:nestif code := strings.ToLower(text[last+1 : i]) // Check to see if they're passing in a second (background) color @@ -381,7 +381,7 @@ func sliceInsert(input []string, i int, v ...string) []string { // that are above maxWordSplitLength characters, split the word into chunks to fit the // // maximum width. -func splitMessage(input string, maxWidth int) (output []string) { +func splitMessage(input string, maxWidth int) (output []string) { //nolint:gocognit input = strings.ToValidUTF8(input, "?") words := strings.FieldsFunc(strings.TrimSpace(input), func(r rune) bool { diff --git a/vendor/github.com/lrstanley/girc/handler.go b/vendor/github.com/lrstanley/girc/handler.go index 55fd4e9..ca1b921 100644 --- a/vendor/github.com/lrstanley/girc/handler.go +++ b/vendor/github.com/lrstanley/girc/handler.go @@ -6,8 +6,8 @@ package girc import ( "fmt" - "log" - "math/rand" + "log" //nolint:depguard // min go version we support doesn't support slog. + "math/rand" //nolint:depguard // min go version we support doesn't support v2. "runtime" "runtime/debug" "strings" @@ -145,7 +145,7 @@ func (c *Caller) cuid(cmd string, n int) (cuid, uid string) { b := make([]byte, n) for i := range b { - b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))] + b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))] //nolint:gosec // not used for cryptographic purposes. } return cmd + ":" + string(b), string(b) @@ -264,9 +264,7 @@ func (c *Caller) Clear(cmd string) { cmd = strings.ToUpper(cmd) c.mu.Lock() - if _, ok := c.external[cmd]; ok { - delete(c.external, cmd) - } + delete(c.external, cmd) c.mu.Unlock() c.debug.Printf("cleared external handlers for %s", cmd) @@ -496,8 +494,8 @@ func (e *HandlerError) String() string { // debug log (see Config.Debug), or os.Stdout if Config.Debug is unset. func DefaultRecoverHandler(client *Client, err *HandlerError) { if client.Config.Debug == nil { - fmt.Println(err.Error()) - fmt.Println(err.String()) + fmt.Println(err.Error()) //nolint:forbidigo + fmt.Println(err.String()) //nolint:forbidigo return } diff --git a/vendor/github.com/lrstanley/girc/modes.go b/vendor/github.com/lrstanley/girc/modes.go index 127b0a7..b879526 100644 --- a/vendor/github.com/lrstanley/girc/modes.go +++ b/vendor/github.com/lrstanley/girc/modes.go @@ -56,15 +56,12 @@ type CModes struct { // Copy returns a deep copy of CModes. func (c *CModes) Copy() (nc CModes) { - nc = CModes{} nc = *c nc.modes = make([]CMode, len(c.modes)) // Copy modes. - for i := 0; i < len(c.modes); i++ { - nc.modes[i] = c.modes[i] - } + copy(nc.modes, c.modes) return nc } @@ -72,8 +69,7 @@ func (c *CModes) Copy() (nc CModes) { // String returns a complete set of modes for this given state (change?). For // example, "+a-b+cde some-arg". func (c *CModes) String() string { - var out string - var args string + var out, args string if len(c.modes) > 0 { out += "+" @@ -82,7 +78,7 @@ func (c *CModes) String() string { for i := 0; i < len(c.modes); i++ { out += string(c.modes[i].name) - if len(c.modes[i].args) > 0 { + if c.modes[i].args != "" { args += " " + c.modes[i].args } } @@ -445,7 +441,7 @@ func (p *UserPerms) remove(channel string) { // Perms contains all channel-based user permissions. The minimum op, and // voice should be supported on all networks. This also supports non-rfc // Owner, Admin, and HalfOp, if the network has support for it. -type Perms struct { +type Perms struct { //nolint:recvcheck // Owner (non-rfc) indicates that the user has full permissions to the // channel. More than one user can have owner permission. Owner bool `json:"owner"` @@ -547,5 +543,5 @@ func parseUserPrefix(raw string) (modes, nick string, success bool) { return modes, raw[i:], true } - return + return modes, nick, success } diff --git a/vendor/github.com/lrstanley/girc/state.go b/vendor/github.com/lrstanley/girc/state.go index 96d2ef8..a1373bf 100644 --- a/vendor/github.com/lrstanley/girc/state.go +++ b/vendor/github.com/lrstanley/girc/state.go @@ -130,7 +130,7 @@ type User struct { // Channels returns a reference of *Channels that the client knows the user // is in. If you're just looking for the namme of the channels, use // User.ChannelList. -func (u User) Channels(c *Client) []*Channel { +func (u *User) Channels(c *Client) []*Channel { if c == nil { panic("nil Client provided") } @@ -244,7 +244,7 @@ type Channel struct { // Users returns a reference of *Users that the client knows the channel has // If you're just looking for just the name of the users, use Channnel.UserList. -func (ch Channel) Users(c *Client) []*User { +func (ch *Channel) Users(c *Client) []*User { if c == nil { panic("nil Client provided") } @@ -265,7 +265,7 @@ func (ch Channel) Users(c *Client) []*User { // Trusted returns a list of users which have voice or greater in the given // channel. See Perms.IsTrusted() for more information. -func (ch Channel) Trusted(c *Client) []*User { +func (ch *Channel) Trusted(c *Client) []*User { if c == nil { panic("nil Client provided") } @@ -292,7 +292,7 @@ func (ch Channel) Trusted(c *Client) []*User { // Admins returns a list of users which have half-op (if supported), or // greater permissions (op, admin, owner, etc) in the given channel. See // Perms.IsAdmin() for more information. -func (ch Channel) Admins(c *Client) []*User { +func (ch *Channel) Admins(c *Client) []*User { if c == nil { panic("nil Client provided") } @@ -389,7 +389,7 @@ func (s *state) createChannel(name string) (ok bool) { supported := s.chanModes() prefixes, _ := parsePrefixes(s.userPrefixes()) - if _, ok := s.channels[ToRFC1459(name)]; ok { + if _, sok := s.channels[ToRFC1459(name)]; sok { return false } @@ -440,7 +440,7 @@ func (s *state) lookupUser(name string) *User { // createUser creates the user in state, if not already done. func (s *state) createUser(src *Source) (ok bool) { - if _, ok := s.users[src.ID()]; ok { + if _, sok := s.users[src.ID()]; sok { // User already exists. return false } @@ -544,15 +544,20 @@ func (s *strictTransport) enabled() bool { return s.upgradePort > 0 } -// ErrSTSUpgradeFailed is an error that occurs when a connection that was attempted +// ErrSTSUpgradeFailed is an alias to STSUpgradeError. +// +// Deprecated: use STSUpgradeError instead. +type ErrSTSUpgradeFailed = STSUpgradeError //nolint:errname + +// STSUpgradeError is an error that occurs when a connection that was attempted // to be upgraded via a strict transport policy, failed. This does not necessarily // indicate that STS was to blame, but the underlying connection failed for some // reason. -type ErrSTSUpgradeFailed struct { +type STSUpgradeError struct { Err error } -func (e ErrSTSUpgradeFailed) Error() string { +func (e STSUpgradeError) Error() string { return fmt.Sprintf("fail to upgrade to secure (sts) connection: %v", e.Err) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 7e39d93..06ff189 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,7 +2,7 @@ ## explicit; go 1.18 github.com/BurntSushi/toml github.com/BurntSushi/toml/internal -# github.com/lrstanley/girc v0.0.0-20240914071631-5c0cc76257bf +# github.com/lrstanley/girc v1.1.0 ## explicit; go 1.18 github.com/lrstanley/girc github.com/lrstanley/girc/internal/ctxgroup