diff --git a/.golangci.yml b/.golangci.yml index be9cf3a..69e5e6c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -46,12 +46,12 @@ linters: - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true] - gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true] - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true] - - gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false] - gosec # Inspects source code for security problems [fast: true, auto-fix: false] - gosimple # Linter for Go source code that specializes in simplifying a code [fast: true, auto-fix: false] - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: true, auto-fix: false] - ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false] - misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true] + - mnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false] - nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false] - nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false] - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false] diff --git a/cli.go b/cli.go index ae5ab70..d448813 100644 --- a/cli.go +++ b/cli.go @@ -1,85 +1,7 @@ package main import ( - "fmt" - "os" - "sort" - "strings" - "sync" - - "github.com/pkg/errors" + "github.com/Luzifer/go_helpers/v2/cli" ) -type ( - cliRegistry struct { - cmds map[string]cliRegistryEntry - sync.Mutex - } - - cliRegistryEntry struct { - Description string - Name string - Params []string - Run func([]string) error - } -) - -var ( - cli = newCLIRegistry() - errHelpCalled = errors.New("help called") -) - -func newCLIRegistry() *cliRegistry { - return &cliRegistry{ - cmds: make(map[string]cliRegistryEntry), - } -} - -func (c *cliRegistry) Add(e cliRegistryEntry) { - c.Lock() - defer c.Unlock() - - c.cmds[e.Name] = e -} - -func (c *cliRegistry) Call(args []string) error { - c.Lock() - defer c.Unlock() - - cmdEntry := c.cmds[args[0]] - if cmdEntry.Name != args[0] { - c.help() - return errHelpCalled - } - - return cmdEntry.Run(args) -} - -func (c *cliRegistry) help() { - // Called from Call, does not need lock - - var ( - maxCmdLen int - cmds []cliRegistryEntry - ) - - for name := range c.cmds { - entry := c.cmds[name] - if l := len(entry.CommandDisplay()); l > maxCmdLen { - maxCmdLen = l - } - cmds = append(cmds, entry) - } - - sort.Slice(cmds, func(i, j int) bool { return cmds[i].Name < cmds[j].Name }) - - tpl := fmt.Sprintf(" %%-%ds %%s\n", maxCmdLen) - fmt.Fprintln(os.Stdout, "Supported sub-commands are:") - for _, cmd := range cmds { - fmt.Fprintf(os.Stdout, tpl, cmd.CommandDisplay(), cmd.Description) - } -} - -func (c cliRegistryEntry) CommandDisplay() string { - return strings.Join(append([]string{c.Name}, c.Params...), " ") -} +var cliTool = cli.New() diff --git a/cli_actorDocs.go b/cli_actorDocs.go index 6309847..b67d8bf 100644 --- a/cli_actorDocs.go +++ b/cli_actorDocs.go @@ -4,11 +4,12 @@ import ( "bytes" "os" + "github.com/Luzifer/go_helpers/v2/cli" "github.com/pkg/errors" ) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "actor-docs", Description: "Generate markdown documentation for available actors", Run: func([]string) error { diff --git a/cli_apiToken.go b/cli_apiToken.go index eb63991..45bc752 100644 --- a/cli_apiToken.go +++ b/cli_apiToken.go @@ -3,6 +3,7 @@ package main import ( "os" + "github.com/Luzifer/go_helpers/v2/cli" "github.com/gofrs/uuid/v3" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -10,12 +11,12 @@ import ( ) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "api-token", Description: "Generate an api-token to be entered into the config", Params: []string{"", "", "[...scope]"}, Run: func(args []string) error { - if len(args) < 3 { //nolint:gomnd // Just a count of parameters + if len(args) < 3 { //nolint:mnd // Just a count of parameters return errors.New("Usage: twitch-bot api-token [...scope]") } diff --git a/cli_migrateDatabase.go b/cli_migrateDatabase.go index acca430..928620b 100644 --- a/cli_migrateDatabase.go +++ b/cli_migrateDatabase.go @@ -3,6 +3,7 @@ package main import ( "sync" + "github.com/Luzifer/go_helpers/v2/cli" "github.com/Luzifer/twitch-bot/v3/pkg/database" "github.com/Luzifer/twitch-bot/v3/plugins" "github.com/pkg/errors" @@ -16,12 +17,12 @@ var ( ) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "copy-database", Description: "Copies database contents to a new storage DSN i.e. for migrating to a new DBMS", Params: []string{"", ""}, Run: func(args []string) error { - if len(args) < 3 { //nolint:gomnd // Just a count of parameters + if len(args) < 3 { //nolint:mnd // Just a count of parameters return errors.New("Usage: twitch-bot copy-database ") } diff --git a/cli_resetSecrets.go b/cli_resetSecrets.go index b051570..ec8398c 100644 --- a/cli_resetSecrets.go +++ b/cli_resetSecrets.go @@ -1,12 +1,13 @@ package main import ( + "github.com/Luzifer/go_helpers/v2/cli" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "reset-secrets", Description: "Remove encrypted data to reset encryption passphrase", Run: func([]string) error { diff --git a/cli_tplDocs.go b/cli_tplDocs.go index 1be9838..ed2ecbb 100644 --- a/cli_tplDocs.go +++ b/cli_tplDocs.go @@ -4,11 +4,12 @@ import ( "bytes" "os" + "github.com/Luzifer/go_helpers/v2/cli" "github.com/pkg/errors" ) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "tpl-docs", Description: "Generate markdown documentation for available template functions", Run: func([]string) error { diff --git a/cli_validateConfig.go b/cli_validateConfig.go index 29422ee..0645500 100644 --- a/cli_validateConfig.go +++ b/cli_validateConfig.go @@ -1,9 +1,12 @@ package main -import "github.com/pkg/errors" +import ( + "github.com/Luzifer/go_helpers/v2/cli" + "github.com/pkg/errors" +) func init() { - cli.Add(cliRegistryEntry{ + cliTool.Add(cli.RegistryEntry{ Name: "validate-config", Description: "Try to load configuration file and report errors if any", Run: func([]string) error { diff --git a/config.go b/config.go index a449161..8fa9141 100644 --- a/config.go +++ b/config.go @@ -211,7 +211,9 @@ func writeConfigToYAML(filename, authorName, authorEmail, summary string, obj *c } tmpFileName := tmpFile.Name() - fmt.Fprintf(tmpFile, "# Automatically updated by %s using Config-Editor frontend, last update: %s\n", authorName, time.Now().Format(time.RFC3339)) + if _, err = fmt.Fprintf(tmpFile, "# Automatically updated by %s using Config-Editor frontend, last update: %s\n", authorName, time.Now().Format(time.RFC3339)); err != nil { + return fmt.Errorf("writing file header: %w", err) + } if err = yaml.NewEncoder(tmpFile).Encode(obj); err != nil { tmpFile.Close() //nolint:errcheck,gosec,revive diff --git a/configRemoteUpdate.go b/configRemoteUpdate.go index 4b285ed..256d871 100644 --- a/configRemoteUpdate.go +++ b/configRemoteUpdate.go @@ -9,7 +9,7 @@ import ( ) func updateConfigCron() string { - minute := rand.Intn(60) //nolint:gomnd,gosec // Only used to distribute load + minute := rand.Intn(60) //nolint:mnd,gosec // Only used to distribute load return fmt.Sprintf("0 %d * * * *", minute) } diff --git a/internal/actors/counter/actor.go b/internal/actors/counter/actor.go index 4bd6083..1ffa34a 100644 --- a/internal/actors/counter/actor.go +++ b/internal/actors/counter/actor.go @@ -336,7 +336,7 @@ func routeActorCounterGetValue(w http.ResponseWriter, r *http.Request) { } w.Header().Set("Content-Type", "text-plain") - fmt.Fprintf(w, template, cv) + http.Error(w, fmt.Sprintf(template, cv), http.StatusOK) } func routeActorCounterSetValue(w http.ResponseWriter, r *http.Request) { diff --git a/internal/actors/spotify/http.go b/internal/actors/spotify/http.go index 0c13191..28f7a43 100644 --- a/internal/actors/spotify/http.go +++ b/internal/actors/spotify/http.go @@ -68,5 +68,5 @@ func handleStartAuth(w http.ResponseWriter, r *http.Request) { return } - fmt.Fprintln(w, "Spotify is now authorized for this channel, you can close this page") + http.Error(w, "Spotify is now authorized for this channel, you can close this page", http.StatusOK) } diff --git a/internal/actors/variables/actor.go b/internal/actors/variables/actor.go index 759762a..e0a6593 100644 --- a/internal/actors/variables/actor.go +++ b/internal/actors/variables/actor.go @@ -195,7 +195,7 @@ func routeActorSetVarGetValue(w http.ResponseWriter, r *http.Request) { } w.Header().Set("Content-Type", "text-plain") - fmt.Fprint(w, vc) + http.Error(w, vc, http.StatusOK) } func routeActorSetVarSetValue(w http.ResponseWriter, r *http.Request) { diff --git a/internal/actors/vip/vip.go b/internal/actors/vip/vip.go index db473c4..fb46ecf 100644 --- a/internal/actors/vip/vip.go +++ b/internal/actors/vip/vip.go @@ -188,7 +188,7 @@ func handleModVIP(m *irc.Message, modFn func(tc *twitch.Client, channel, user st channel := strings.TrimLeft(plugins.DeriveChannel(m, nil), "#") parts := strings.Split(m.Trailing(), " ") - if len(parts) != 2 { //nolint:gomnd // Just a count, makes no sense as a constant + if len(parts) != 2 { //nolint:mnd // Just a count, makes no sense as a constant return errors.Errorf("wrong command usage, must consist of 2 words") } diff --git a/internal/apimodules/msgformat/msgformat.go b/internal/apimodules/msgformat/msgformat.go index 6b5ebfb..3753422 100644 --- a/internal/apimodules/msgformat/msgformat.go +++ b/internal/apimodules/msgformat/msgformat.go @@ -54,5 +54,5 @@ func handleFormattedMessage(w http.ResponseWriter, r *http.Request) { return } - fmt.Fprint(w, msg) + http.Error(w, msg, http.StatusOK) } diff --git a/internal/service/timer/timer.go b/internal/service/timer/timer.go index 063dd60..8b3ac3c 100644 --- a/internal/service/timer/timer.go +++ b/internal/service/timer/timer.go @@ -72,9 +72,7 @@ func (s Service) InCooldown(tt plugins.TimerType, limiter, ruleID string) (bool, } func (Service) getCooldownTimerKey(tt plugins.TimerType, limiter, ruleID string) string { - h := sha256.New() - fmt.Fprintf(h, "%d:%s:%s", tt, limiter, ruleID) - return fmt.Sprintf("sha256:%x", h.Sum(nil)) + return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(fmt.Sprintf("%d:%s:%s", tt, limiter, ruleID)))) } // Permit timer @@ -90,9 +88,10 @@ func (s Service) HasPermit(channel, username string) (bool, error) { } func (Service) getPermitTimerKey(channel, username string) string { - h := sha256.New() - fmt.Fprintf(h, "%d:%s:%s", plugins.TimerTypePermit, channel, strings.ToLower(strings.TrimLeft(username, "@"))) - return fmt.Sprintf("sha256:%x", h.Sum(nil)) + return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(fmt.Sprintf( + "%d:%s:%s", + plugins.TimerTypePermit, channel, strings.ToLower(strings.TrimLeft(username, "@")), + )))) } // Generic timer diff --git a/internal/template/date/interval.go b/internal/template/date/interval.go index 8ce65b6..ffe70c2 100644 --- a/internal/template/date/interval.go +++ b/internal/template/date/interval.go @@ -40,15 +40,15 @@ func NewInterval(a, b time.Time) (i Interval) { i.Seconds = u.Second() - l.Second() if i.Seconds < 0 { - i.Minutes, i.Seconds = i.Minutes-1, i.Seconds+60 //nolint:gomnd + i.Minutes, i.Seconds = i.Minutes-1, i.Seconds+60 //nolint:mnd } if i.Minutes < 0 { - i.Hours, i.Minutes = i.Hours-1, i.Minutes+60 //nolint:gomnd + i.Hours, i.Minutes = i.Hours-1, i.Minutes+60 //nolint:mnd } if i.Hours < 0 { - i.Days, i.Hours = i.Days-1, i.Hours+24 //nolint:gomnd + i.Days, i.Hours = i.Days-1, i.Hours+24 //nolint:mnd } if i.Days < 0 { @@ -57,7 +57,7 @@ func NewInterval(a, b time.Time) (i Interval) { } if i.Months < 0 { - i.Years, i.Months = i.Years-1, i.Months+12 //nolint:gomnd + i.Years, i.Months = i.Years-1, i.Months+12 //nolint:mnd } return i diff --git a/internal/template/random/random.go b/internal/template/random/random.go index 23f6535..12a8bbd 100644 --- a/internal/template/random/random.go +++ b/internal/template/random/random.go @@ -63,7 +63,7 @@ func stringToSeed(s string) (int64, error) { ) for i := 0; i < len(hashSum); i++ { - sum += int64(float64(hashSum[len(hashSum)-1-i]%10) * math.Pow(10, float64(i))) //nolint:gomnd // No need to put the 10 of 10**i into a constant named "ten" + sum += int64(float64(hashSum[len(hashSum)-1-i]%10) * math.Pow(10, float64(i))) //nolint:mnd // No need to put the 10 of 10**i into a constant named "ten" } return sum, nil diff --git a/irc.go b/irc.go index e69f644..eb5f503 100644 --- a/irc.go +++ b/irc.go @@ -294,7 +294,7 @@ func (i ircHandler) handlePermit(m *irc.Message) { } msgParts := strings.Split(m.Trailing(), " ") - if len(msgParts) != 2 { //nolint:gomnd // This is not a magic number but just an expected count + if len(msgParts) != 2 { //nolint:mnd // This is not a magic number but just an expected count return } diff --git a/main.go b/main.go index 78ed6bd..9a4d286 100644 --- a/main.go +++ b/main.go @@ -193,7 +193,7 @@ func main() { } if len(rconfig.Args()) > 1 { - if err = cli.Call(rconfig.Args()[1:]); err != nil { + if err = cliTool.Call(rconfig.Args()[1:]); err != nil { log.Fatalf("error in command: %s", err) } return diff --git a/pkg/database/coreKV.go b/pkg/database/coreKV.go index 1b9dc2b..e7c01ad 100644 --- a/pkg/database/coreKV.go +++ b/pkg/database/coreKV.go @@ -78,12 +78,9 @@ func (c connector) StoreEncryptedCoreMeta(key string, value any) error { } func (c connector) ValidateEncryption() error { - validationHasher := sha512.New() - fmt.Fprint(validationHasher, c.encryptionSecret) - var ( storedHash string - validationHash = fmt.Sprintf("%x", validationHasher.Sum(nil)) + validationHash = fmt.Sprintf("%x", sha512.Sum512([]byte(c.encryptionSecret))) ) err := backoff.NewBackoff(). diff --git a/pkg/database/logger.go b/pkg/database/logger.go index 2ff9cb3..05e26df 100644 --- a/pkg/database/logger.go +++ b/pkg/database/logger.go @@ -21,10 +21,10 @@ func NewLogrusLogWriterWithLevel(logger *logrus.Logger, level logrus.Level, dbDr // Print implements the gorm.Logger interface func (l LogWriter) Print(a ...any) { - fmt.Fprint(l.Writer, a...) + fmt.Fprint(l.Writer, a...) //nolint:errcheck // Interface ignores this error } // Printf implements the gorm.Logger interface func (l LogWriter) Printf(format string, a ...any) { - fmt.Fprintf(l.Writer, format, a...) + fmt.Fprintf(l.Writer, format, a...) //nolint:errcheck // Interface ignores this error } diff --git a/pkg/twitch/badges.go b/pkg/twitch/badges.go index 5f5d8ec..7dab4ca 100644 --- a/pkg/twitch/badges.go +++ b/pkg/twitch/badges.go @@ -45,7 +45,7 @@ func ParseBadgeLevels(m *irc.Message) BadgeCollection { badges := strings.Split(badgeString, ",") for _, b := range badges { badgeParts := strings.Split(b, "/") - if len(badgeParts) != 2 { //nolint:gomnd // This is not a magic number but just an expected count + if len(badgeParts) != 2 { //nolint:mnd // This is not a magic number but just an expected count continue } diff --git a/plugins/timerstore.go b/plugins/timerstore.go index 52ef1b5..781bab8 100644 --- a/plugins/timerstore.go +++ b/plugins/timerstore.go @@ -52,9 +52,7 @@ func (t *testTimerStore) InCooldown(tt TimerType, limiter, ruleID string) (bool, } func (testTimerStore) getCooldownTimerKey(tt TimerType, limiter, ruleID string) string { - h := sha256.New() - fmt.Fprintf(h, "%d:%s:%s", tt, limiter, ruleID) - return fmt.Sprintf("sha256:%x", h.Sum(nil)) + return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(fmt.Sprintf("%d:%s:%s", tt, limiter, ruleID)))) } // Permit timer @@ -69,7 +67,5 @@ func (t *testTimerStore) HasPermit(channel, username string) (bool, error) { } func (testTimerStore) getPermitTimerKey(channel, username string) string { - h := sha256.New() - fmt.Fprintf(h, "%d:%s:%s", TimerTypePermit, channel, strings.ToLower(strings.TrimLeft(username, "@"))) - return fmt.Sprintf("sha256:%x", h.Sum(nil)) + return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(fmt.Sprintf("%d:%s:%s", TimerTypePermit, channel, strings.ToLower(strings.TrimLeft(username, "@")))))) }