From be8eb6dd60d7058ef96caf2237f7d541b6333ae3 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 18 Aug 2022 08:11:05 +0200 Subject: [PATCH 1/7] v0.1.7: Getting started on /ledger --- sql_migrations/000009_add_user_ledger.down.sql | 1 + sql_migrations/000009_add_user_ledger.up.sql | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 sql_migrations/000009_add_user_ledger.down.sql create mode 100644 sql_migrations/000009_add_user_ledger.up.sql diff --git a/sql_migrations/000009_add_user_ledger.down.sql b/sql_migrations/000009_add_user_ledger.down.sql new file mode 100644 index 0000000..5c7c02b --- /dev/null +++ b/sql_migrations/000009_add_user_ledger.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS user_ledger; diff --git a/sql_migrations/000009_add_user_ledger.up.sql b/sql_migrations/000009_add_user_ledger.up.sql new file mode 100644 index 0000000..4c6a59e --- /dev/null +++ b/sql_migrations/000009_add_user_ledger.up.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS user_ledger +( + id bigserial PRIMARY KEY, + user_id bigint NOT NULL REFERENCES users ON DELETE CASCADE, + emissary varchar(32) NOT NULL, + band int NULL, + rank bigint NOT NULL, + score bigint NULL, + next_rank bigint NULL, + ctime timestamp(0) with time zone NOT NULL DEFAULT NOW() +); From e148afb4f97f5d04321f6dc6be9b3452c2b7466b Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 18 Aug 2022 08:11:55 +0200 Subject: [PATCH 2/7] v0.1.7: Change timer defaults, due to too many requests made by the bot (RARE contacted us :D ) --- config/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index cab97d6..f42dd15 100644 --- a/config/config.go +++ b/config/config.go @@ -46,9 +46,9 @@ type Config struct { Timer struct { FHSpam int64 `fig:"flameheart_spam" default:"60"` TRUpdate time.Duration `fig:"traderoutes_update" default:"12h"` - USUpdate time.Duration `fig:"userstats_update" default:"30m"` - RCCheck time.Duration `fig:"ratcookie_check" default:"5m"` - DDUpdate time.Duration `fig:"dailydeed_update" default:"12h"` + USUpdate time.Duration `fig:"userstats_update" default:"6h"` + RCCheck time.Duration `fig:"ratcookie_check" default:"6h"` + DDUpdate time.Duration `fig:"dailydeed_update" default:"24h"` } confPath string confFile string From 466fb786977b48757654f6b22a2474f3a3daf58e Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 18 Aug 2022 11:18:45 +0200 Subject: [PATCH 3/7] v0.1.7: discordgo upgrade and first-run flag - Added firstrun flag so that the "run once at start" tasks are optionally executed - Upgraded discordgo to 0.2.6 and fixed the breaking changes --- Makefile | 3 +++ bot/bot.go | 26 +++++++++++++------------ bot/sc_handler_compare.go | 2 +- bot/sc_handler_config.go | 6 +++--- bot/sc_handler_rarethief_traderoutes.go | 2 +- bot/sc_handler_register.go | 4 ++-- bot/sc_handler_sot_achievement.go | 2 +- bot/sc_handler_sot_dailydeeds.go | 2 +- bot/sc_handler_sot_flameheart.go | 2 +- bot/sc_handler_sot_season.go | 2 +- bot/sc_handler_sot_setrat.go | 4 ++-- bot/sc_handler_sot_userstats.go | 4 ++-- bot/sc_handler_time.go | 2 +- bot/sc_handler_uptime.go | 2 +- bot/sc_handler_version.go | 2 +- bot/slashcmd.go | 4 ++-- cmd/arrgo/arrgo.go | 8 +++++++- config/config.go | 11 +++++++++++ go.mod | 2 +- go.sum | 4 ++-- 20 files changed, 58 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index f5ac632..a493225 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ test: dev: @/usr/bin/env CGO_ENABLED=0 go run -ldflags="-s -w $(BUILDVER)" $(MODNAME)/cmd/arrgo -c ./arrgo.toml +dev-firstrun: + @/usr/bin/env CGO_ENABLED=0 go run -ldflags="-s -w $(BUILDVER)" $(MODNAME)/cmd/arrgo -c ./arrgo.toml -firstrun + dev-migrate: @/usr/bin/env CGO_ENABLED=0 go run -ldflags="-s -w $(BUILDVER)" $(MODNAME)/cmd/arrgo -c ./arrgo.toml -migrate diff --git a/bot/bot.go b/bot/bot.go index a519882..fd64ee6 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -137,18 +137,20 @@ func (b *Bot) Run() error { ddt := time.NewTicker(b.Config.Timer.DDUpdate) defer ddt.Stop() - // Perform an update for all scheduled update tasks once - go func() { - if err := b.ScheduledEventUpdateTradeRoutes(); err != nil { - b.Log.Error().Msgf("failed to update trade routes: %s", err) - } - if err := b.ScheduledEventUpdateUserStats(); err != nil { - b.Log.Error().Msgf("failed to update user stats: %s", err) - } - if err := b.ScheduledEventUpdateDailyDeeds(); err != nil { - b.Log.Error().Msgf("failed to update daily deeds: %s", err) - } - }() + // Perform an update for all scheduled update tasks once if first-run flag is set + if b.Config.GetFirstRun() { + go func() { + if err := b.ScheduledEventUpdateTradeRoutes(); err != nil { + b.Log.Error().Msgf("failed to update trade routes: %s", err) + } + if err := b.ScheduledEventUpdateUserStats(); err != nil { + b.Log.Error().Msgf("failed to update user stats: %s", err) + } + if err := b.ScheduledEventUpdateDailyDeeds(); err != nil { + b.Log.Error().Msgf("failed to update daily deeds: %s", err) + } + }() + } // Wait here until CTRL-C or other term signal is received. ll.Info().Msg("bot successfully initialized and connected. Press CTRL-C to exit.") diff --git a/bot/sc_handler_compare.go b/bot/sc_handler_compare.go index c923542..10f6289 100644 --- a/bot/sc_handler_compare.go +++ b/bot/sc_handler_compare.go @@ -143,7 +143,7 @@ func (b *Bot) SlashCmdSoTCompare(s *discordgo.Session, i *discordgo.InteractionC } } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_config.go b/bot/sc_handler_config.go index 135c88c..b950896 100644 --- a/bot/sc_handler_config.go +++ b/bot/sc_handler_config.go @@ -72,7 +72,7 @@ func (b *Bot) configFlameheart(s *discordgo.Session, i *discordgo.InteractionCre } // Edit the deferred message - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return fmt.Errorf("failed to edit /config flameheart-spam request: %w", err) } @@ -115,7 +115,7 @@ func (b *Bot) overrideAnnounceChannel(s *discordgo.Session, i *discordgo.Interac Description: fmt.Sprintf("The annoucment channel for this server has been set to: <#%s>", ch), }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return fmt.Errorf("failed to edit /override annouce-channel request: %w", err) } @@ -149,7 +149,7 @@ func (b *Bot) configAnnounceSoTPlaySummary(s *discordgo.Session, i *discordgo.In } // Edit the deferred message - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return fmt.Errorf("failed to edit /config announce-sot-summary request: %w", err) } diff --git a/bot/sc_handler_rarethief_traderoutes.go b/bot/sc_handler_rarethief_traderoutes.go index 412c036..4781150 100644 --- a/bot/sc_handler_rarethief_traderoutes.go +++ b/bot/sc_handler_rarethief_traderoutes.go @@ -66,7 +66,7 @@ func (b *Bot) SlashCmdSoTTradeRoutes(s *discordgo.Session, i *discordgo.Interact }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_register.go b/bot/sc_handler_register.go index 249fc1d..b309fed 100644 --- a/bot/sc_handler_register.go +++ b/bot/sc_handler_register.go @@ -23,7 +23,7 @@ func (b *Bot) SlashCmdRegister(s *discordgo.Session, i *discordgo.InteractionCre Description: "You are already registered with ArrGo. Thanks for double checking...", }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return fmt.Errorf("failed to edit /register request: %w", err) } return nil @@ -52,7 +52,7 @@ func (b *Bot) SlashCmdRegister(s *discordgo.Session, i *discordgo.InteractionCre Description: "You have successfully registered your account and are now able to use the full feature set", }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return fmt.Errorf("failed to edit /register request: %w", err) } diff --git a/bot/sc_handler_sot_achievement.go b/bot/sc_handler_sot_achievement.go index eff7f6f..7539112 100644 --- a/bot/sc_handler_sot_achievement.go +++ b/bot/sc_handler_sot_achievement.go @@ -49,7 +49,7 @@ func (b *Bot) SlashCmdSoTAchievement(s *discordgo.Session, i *discordgo.Interact Type: discordgo.EmbedTypeImage, }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_sot_dailydeeds.go b/bot/sc_handler_sot_dailydeeds.go index 03d57ca..7f8c412 100644 --- a/bot/sc_handler_sot_dailydeeds.go +++ b/bot/sc_handler_sot_dailydeeds.go @@ -85,7 +85,7 @@ func (b *Bot) SlashCmdSoTDailyDeeds(s *discordgo.Session, i *discordgo.Interacti } } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_sot_flameheart.go b/bot/sc_handler_sot_flameheart.go index c32f129..5247956 100644 --- a/bot/sc_handler_sot_flameheart.go +++ b/bot/sc_handler_sot_flameheart.go @@ -17,7 +17,7 @@ func (b *Bot) SlashCmdSoTFlameheart(s *discordgo.Session, i *discordgo.Interacti } // Edit the deferred message - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } diff --git a/bot/sc_handler_sot_season.go b/bot/sc_handler_sot_season.go index 81faba1..989e514 100644 --- a/bot/sc_handler_sot_season.go +++ b/bot/sc_handler_sot_season.go @@ -138,7 +138,7 @@ func (b *Bot) SlashCmdSoTSeasonProgress(s *discordgo.Session, i *discordgo.Inter } } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_sot_setrat.go b/bot/sc_handler_sot_setrat.go index 16d20ca..e1b9985 100644 --- a/bot/sc_handler_sot_setrat.go +++ b/bot/sc_handler_sot_setrat.go @@ -39,7 +39,7 @@ func (b *Bot) SlashCmdSetRAT(s *discordgo.Session, i *discordgo.InteractionCreat "command to register your user with the bot", }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil @@ -87,7 +87,7 @@ func (b *Bot) SlashCmdSetRAT(s *discordgo.Session, i *discordgo.InteractionCreat Description: "Thank you for storing/updating your Sea of Thieves authentication cookie.", }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_sot_userstats.go b/bot/sc_handler_sot_userstats.go index 77ed5b3..028b918 100644 --- a/bot/sc_handler_sot_userstats.go +++ b/bot/sc_handler_sot_userstats.go @@ -98,7 +98,7 @@ func (b *Bot) SlashCmdSoTOverview(s *discordgo.Session, i *discordgo.Interaction }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil @@ -153,7 +153,7 @@ func (b *Bot) SlashCmdSoTBalance(s *discordgo.Session, i *discordgo.InteractionC e[0].Description = fmt.Sprintf("**Current Title:** %s", ub.Title) } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_time.go b/bot/sc_handler_time.go index 2f0f51a..2ce985b 100644 --- a/bot/sc_handler_time.go +++ b/bot/sc_handler_time.go @@ -15,7 +15,7 @@ func (b *Bot) SlashCmdTime(s *discordgo.Session, i *discordgo.InteractionCreate) Description: fmt.Sprintf("The current bot time is: ", time.Now().Unix()), }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_uptime.go b/bot/sc_handler_uptime.go index f0c92c9..1c5e74e 100644 --- a/bot/sc_handler_uptime.go +++ b/bot/sc_handler_uptime.go @@ -21,7 +21,7 @@ func (b *Bot) SlashCmdUptime(s *discordgo.Session, i *discordgo.InteractionCreat "which means I've been running for %s now!", b.StartTimeUnix(), td.String()), }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/sc_handler_version.go b/bot/sc_handler_version.go index fdf51d5..e3dd5e6 100644 --- a/bot/sc_handler_version.go +++ b/bot/sc_handler_version.go @@ -15,7 +15,7 @@ func (b *Bot) SlashCmdVersion(s *discordgo.Session, i *discordgo.InteractionCrea "Nice to meet you!", Version), }, } - if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}); err != nil { + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { return err } return nil diff --git a/bot/slashcmd.go b/bot/slashcmd.go index ef4e087..c088d1a 100644 --- a/bot/slashcmd.go +++ b/bot/slashcmd.go @@ -339,7 +339,7 @@ func (b *Bot) SlashCommandHandler(s *discordgo.Session, i *discordgo.Interaction Data: &discordgo.InteractionResponseData{Content: ""}, } if _, ok := el[i.ApplicationCommandData().Name]; ok { - r.Data.Flags = uint64(discordgo.MessageFlagsEphemeral) + r.Data.Flags = discordgo.MessageFlagsEphemeral } err := s.InteractionRespond(i.Interaction, r) if err != nil { @@ -357,7 +357,7 @@ func (b *Bot) SlashCommandHandler(s *discordgo.Session, i *discordgo.Interaction Title: "Oh no! Something went wrong!", }, } - _, _ = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: e}) + _, _ = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}) } } } diff --git a/cmd/arrgo/arrgo.go b/cmd/arrgo/arrgo.go index 7edd831..04f5e8f 100644 --- a/cmd/arrgo/arrgo.go +++ b/cmd/arrgo/arrgo.go @@ -17,6 +17,7 @@ type CLIFlags struct { r bool // Remove slash commands m bool // Run in SQL migration mode d bool // Run in SQL downgrade mode + f bool // First run } func main() { @@ -29,7 +30,9 @@ func main() { flag.StringVar(&cf.c, "c", cf.c, "Path to config file") flag.BoolVar(&cf.r, "r", cf.r, "Remove slash commands") flag.BoolVar(&cf.m, "migrate", false, "Execute SQL migrations before starting the bot") - flag.BoolVar(&cf.d, "downgrade", false, "Execute SQL downgrade migrations before starting the bot") + flag.BoolVar(&cf.d, "downgrade", false, "Execute SQL downgrade migrations before "+ + "starting the bot") + flag.BoolVar(&cf.f, "firstrun", false, "Execute first-run tasks during startup") flag.Parse() // Read/Parse config @@ -42,6 +45,9 @@ func main() { _, _ = fmt.Fprintf(os.Stderr, "could not read config: %s. Aborting", err) os.Exit(1) } + if cf.f { + c.SetFirstRun() + } // Initialize zerolog zerolog.SetGlobalLevel(zerolog.InfoLevel) diff --git a/config/config.go b/config/config.go index f42dd15..d842b41 100644 --- a/config/config.go +++ b/config/config.go @@ -52,6 +52,7 @@ type Config struct { } confPath string confFile string + firstRun bool } // WithConfFile overrides the default config file path/name @@ -94,3 +95,13 @@ func New(ol ...CfgOpt) (Config, error) { func (c *Config) ConfFilePath() string { return c.confFile } + +// SetFirstRun sets the fristRun flag in the config to true +func (c *Config) SetFirstRun() { + c.firstRun = true +} + +// GetFirstRun returns the state of the firstRun flag in the config +func (c *Config) GetFirstRun() bool { + return c.firstRun +} diff --git a/go.mod b/go.mod index 768b02c..6798d6c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/wneessen/arrgo go 1.18 require ( - github.com/bwmarrin/discordgo v0.25.0 + github.com/bwmarrin/discordgo v0.26.0 github.com/golang-migrate/migrate/v4 v4.15.2 github.com/kkyr/fig v0.3.0 github.com/lib/pq v1.10.6 diff --git a/go.sum b/go.sum index c45aae7..ec022b5 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bwmarrin/discordgo v0.25.0 h1:NXhdfHRNxtwso6FPdzW2i3uBvvU7UIQTghmV2T4nqAs= -github.com/bwmarrin/discordgo v0.25.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= +github.com/bwmarrin/discordgo v0.26.0 h1:/AdFmxHXSHInYAZ7K0O3VEIXlVjGpztk/nuCr9o+JCs= +github.com/bwmarrin/discordgo v0.26.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From 19ed9d79189470e0c6f9e77cbc4b2d97ccc1929a Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 25 Aug 2022 14:11:36 +0200 Subject: [PATCH 4/7] v0.1.7: Up the HTTP client timeout to 20 secs... SoT API seems to be very laggy --- bot/httpclient.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/httpclient.go b/bot/httpclient.go index 7107d83..54ff059 100644 --- a/bot/httpclient.go +++ b/bot/httpclient.go @@ -67,7 +67,7 @@ func NewHTTPClient() (*HTTPClient, error) { } hc := &http.Client{ Transport: t, - Timeout: 10 * time.Second, + Timeout: 20 * time.Second, Jar: cj, } From 29136115d253e2ccc0d70ba789c212aa47b2310e Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Fri, 26 Aug 2022 13:48:08 +0200 Subject: [PATCH 5/7] v0.1.7: All scheduled tasks are now executed in Go routines with random delay on API heavy tasks --- bot/bot.go | 54 ++++++++++++++++++-------------- bot/sc_handler_sot_userstats.go | 7 +++++ bot/se_handler_checkratcookie.go | 6 ++++ config/config.go | 3 +- crypto/random.go | 15 +++++++++ 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index fd64ee6..bb4b852 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -119,14 +119,12 @@ func (b *Bot) Run() error { signal.Notify(sc) // Timer events - var rn int - rn = int(b.Config.Timer.FHSpam) - rn, err = crypto.RandNum(int(b.Config.Timer.FHSpam)) + rd, err := crypto.RandDuration(b.Config.Timer.FHSpam, "m") if err != nil { ll.Warn().Msgf("failed to generate random number for FH timer: %s", err) - rn = int(b.Config.Timer.FHSpam) + rd = time.Minute * time.Duration(b.Config.Timer.FHSpam) } - fht := time.NewTicker(time.Duration(int64(rn)+b.Config.Timer.FHSpam) * time.Minute) + fht := time.NewTicker(rd) defer fht.Stop() trt := time.NewTicker(b.Config.Timer.TRUpdate) defer trt.Stop() @@ -170,33 +168,43 @@ func (b *Bot) Run() error { return nil } case <-fht.C: - if err := b.ScheduledEventSoTFlameheart(); err != nil { - ll.Error().Msgf("failed to process scheuled flameheart event: %s", err) - } + go func() { + if err := b.ScheduledEventSoTFlameheart(); err != nil { + ll.Error().Msgf("failed to process scheuled flameheart event: %s", err) + } + }() // Reset the duration - rn, err = crypto.RandNum(int(b.Config.Timer.FHSpam)) + rd, err := crypto.RandDuration(b.Config.Timer.FHSpam, "m") if err != nil { ll.Warn().Msgf("failed to generate random number for FH timer: %s", err) - rn = int(b.Config.Timer.FHSpam) + rd = time.Minute * time.Duration(b.Config.Timer.FHSpam) } - fht.Reset(time.Duration(int64(rn)+b.Config.Timer.FHSpam) * time.Minute) + fht.Reset(rd) case <-trt.C: - if err := b.ScheduledEventUpdateTradeRoutes(); err != nil { - ll.Error().Msgf("failed to process scheuled traderoute update event: %s", err) - } + go func() { + if err := b.ScheduledEventUpdateTradeRoutes(); err != nil { + ll.Error().Msgf("failed to process scheuled traderoute update event: %s", err) + } + }() case <-ust.C: - if err := b.ScheduledEventUpdateUserStats(); err != nil { - ll.Error().Msgf("failed to process scheuled traderoute update event: %s", err) - } + go func() { + if err := b.ScheduledEventUpdateUserStats(); err != nil { + ll.Error().Msgf("failed to process scheuled traderoute update event: %s", err) + } + }() case <-rct.C: - if err := b.ScheduledEventCheckRATCookies(); err != nil { - ll.Error().Msgf("failed to process scheuled RAT cookie check event: %s", err) - } + go func() { + if err := b.ScheduledEventCheckRATCookies(); err != nil { + ll.Error().Msgf("failed to process scheuled RAT cookie check event: %s", err) + } + }() case <-ddt.C: - if err := b.ScheduledEventUpdateDailyDeeds(); err != nil { - ll.Error().Msgf("failed to process scheuled daily deeds update event: %s", err) - } + go func() { + if err := b.ScheduledEventUpdateDailyDeeds(); err != nil { + ll.Error().Msgf("failed to process scheuled daily deeds update event: %s", err) + } + }() } } } diff --git a/bot/sc_handler_sot_userstats.go b/bot/sc_handler_sot_userstats.go index 028b918..60f658a 100644 --- a/bot/sc_handler_sot_userstats.go +++ b/bot/sc_handler_sot_userstats.go @@ -5,10 +5,12 @@ import ( "errors" "fmt" "github.com/bwmarrin/discordgo" + "github.com/wneessen/arrgo/crypto" "github.com/wneessen/arrgo/model" "golang.org/x/text/language" "golang.org/x/text/message" "net/http" + "time" ) // SoTUserOverview represents the JSON structure of the Sea of Thieves user overview API response @@ -226,6 +228,11 @@ func (b *Bot) ScheduledEventUpdateUserStats() error { ll.Error().Msgf("failed to store user stats in DB: %s", err) continue } + rd, err := crypto.RandDuration(10, "s") + if err != nil { + rd = time.Second * 10 + } + time.Sleep(rd) } return nil } diff --git a/bot/se_handler_checkratcookie.go b/bot/se_handler_checkratcookie.go index b955c02..df9e692 100644 --- a/bot/se_handler_checkratcookie.go +++ b/bot/se_handler_checkratcookie.go @@ -3,6 +3,7 @@ package bot import ( "errors" "fmt" + "github.com/wneessen/arrgo/crypto" "github.com/wneessen/arrgo/model" "net/http" "time" @@ -89,6 +90,11 @@ func (b *Bot) ScheduledEventCheckRATCookies() error { } } } + rd, err := crypto.RandDuration(10, "s") + if err != nil { + rd = time.Second * 10 + } + time.Sleep(rd) } return nil } diff --git a/config/config.go b/config/config.go index d842b41..643502b 100644 --- a/config/config.go +++ b/config/config.go @@ -44,11 +44,12 @@ type Config struct { EncryptionKey string `fig:"enc_key"` } Timer struct { - FHSpam int64 `fig:"flameheart_spam" default:"60"` + FHSpam int `fig:"flameheart_spam" default:"60"` TRUpdate time.Duration `fig:"traderoutes_update" default:"12h"` USUpdate time.Duration `fig:"userstats_update" default:"6h"` RCCheck time.Duration `fig:"ratcookie_check" default:"6h"` DDUpdate time.Duration `fig:"dailydeed_update" default:"24h"` + ULUpdate time.Duration `fig:"userledger_update" default:"6h"` } confPath string confFile string diff --git a/crypto/random.go b/crypto/random.go index f539ab7..957844a 100644 --- a/crypto/random.go +++ b/crypto/random.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "strings" + "time" ) // Range of characters for the different types of string generations @@ -89,6 +90,20 @@ func RandNum(n int) (int, error) { return rn, nil } +// RandDuration returns a random time.Duration in u with a maximum value of the given n +func RandDuration(n int, u string) (time.Duration, error) { + var d time.Duration + rn, err := RandNum(n) + if err != nil { + return d, err + } + d, err = time.ParseDuration(fmt.Sprintf("%d%s", rn, u)) + if err != nil { + return d, err + } + return d, nil +} + // getCharRange returns the range of characters as controlled by the s and h bools func getCharRange(s, h bool) string { var cr string From 9ad21758237845ba18955208fb8d51e814a7530f Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Tue, 6 Sep 2022 08:50:09 +0200 Subject: [PATCH 6/7] v0.1.7: dependency - bump github.com/bwmarrin/discordgo to 0.26.1 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 6798d6c..86588ff 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/wneessen/arrgo go 1.18 require ( - github.com/bwmarrin/discordgo v0.26.0 + github.com/bwmarrin/discordgo v0.26.1 github.com/golang-migrate/migrate/v4 v4.15.2 github.com/kkyr/fig v0.3.0 github.com/lib/pq v1.10.6 diff --git a/go.sum b/go.sum index ec022b5..512d50c 100644 --- a/go.sum +++ b/go.sum @@ -174,6 +174,8 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bwmarrin/discordgo v0.26.0 h1:/AdFmxHXSHInYAZ7K0O3VEIXlVjGpztk/nuCr9o+JCs= github.com/bwmarrin/discordgo v0.26.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= +github.com/bwmarrin/discordgo v0.26.1 h1:AIrM+g3cl+iYBr4yBxCBp9tD9jR3K7upEjl0d89FRkE= +github.com/bwmarrin/discordgo v0.26.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From 3a0d0d098bbd7ca307580970994a9dd52bf2d458 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Sat, 1 Oct 2022 12:24:45 +0200 Subject: [PATCH 7/7] v0.1.7: Completed the Emissary Ledger slash command --- bot/bot.go | 1 + bot/format.go | 1 + bot/sc_handler_sot_ledger.go | 180 +++++++++++++++++++++++++++++++++++ bot/slashcmd.go | 2 +- go.sum | 2 - 5 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 bot/sc_handler_sot_ledger.go diff --git a/bot/bot.go b/bot/bot.go index bb4b852..b45683d 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -22,6 +22,7 @@ const ( ApiURLSoTUserOverview = "https://www.seaofthieves.com/api/profilev2/overview" ApiURLSoTEventHub = "https://www.seaofthieves.com/event-hub" ApiURLRTTradeRoutes = "https://maps.seaofthieves.rarethief.com/js/trade_routes.js" + ApiURLSoTLedger = "https://www.seaofthieves.com/api/ledger/friends" AssetsBaseURL = "https://github.com/wneessen/arrgo/raw/main/assets" ) diff --git a/bot/format.go b/bot/format.go index 54f70ce..9c213ff 100644 --- a/bot/format.go +++ b/bot/format.go @@ -15,6 +15,7 @@ const ( IconShip = "⛵" IconVomit = "🤮" IconDistance = "📐" + IconGauge = "🌡️" ) // changeIcon returns either an increase or decrease icon based on the provided value diff --git a/bot/sc_handler_sot_ledger.go b/bot/sc_handler_sot_ledger.go new file mode 100644 index 0000000..e5b5501 --- /dev/null +++ b/bot/sc_handler_sot_ledger.go @@ -0,0 +1,180 @@ +package bot + +import ( + "encoding/json" + "fmt" + "github.com/bwmarrin/discordgo" + "regexp" + "strings" +) + +// SoTLedger represents the JSON structure of the Sea of Thieves leder positions within a season API response +type SoTLedger struct { + Current SoTCurrentLedger `json:"current"` +} + +// SoTCurrentLedger represents the JSON structure of the Sea of Thieves current leder within the overall +// ledger response +type SoTCurrentLedger struct { + Friends SoTFriendsLedger `json:"friends"` +} + +// SoTFriendsLedger represents the JSON structure of the Sea of Thieves friends positioning withing the current leder +type SoTFriendsLedger struct { + User SoTEmissaryLedger `json:"user"` +} + +// SoTEmissaryLedger represents the JSON structure of the Sea of Thieves ledger data +type SoTEmissaryLedger struct { + Name string + Band int `json:"band"` + BandTitle string + Rank int `json:"rank"` + Score int `json:"score"` + ToNextRank int `json:"toNextRank"` +} + +// SlashCmdSoTLedger handles the /ledger slash command +func (b *Bot) SlashCmdSoTLedger(s *discordgo.Session, i *discordgo.InteractionCreate) error { + eo := i.ApplicationCommandData().Options + if len(eo) <= 0 { + return fmt.Errorf("no option given") + } + rc, ok := eo[0].Value.(string) + if !ok { + return fmt.Errorf("provided option value is not a string") + } + + re, err := regexp.Compile(`^(?i:athena|hoarder|merchant|order|reaper)$`) + if err != nil { + return err + } + ema := re.FindStringSubmatch(rc) + if len(ema) != 1 { + return fmt.Errorf("failed to parse value string") + } + em := ema[0] + + r, err := b.NewRequester(i.Interaction) + if err != nil { + return err + } + + l, err := b.SoTGetLedger(r, em) + if err != nil { + return err + } + + var ef []*discordgo.MessageEmbedField + ef = append(ef, &discordgo.MessageEmbedField{ + Name: "Faction/Company", + Value: l.Name, + Inline: false, + }) + ef = append(ef, &discordgo.MessageEmbedField{ + Name: "Current Title", + Value: l.BandTitle, + Inline: false, + }) + ef = append(ef, &discordgo.MessageEmbedField{ + Name: "Emissary value", + Value: fmt.Sprintf("%s **%d**", IconAncientCoin, l.Score), + Inline: true, + }) + ef = append(ef, &discordgo.MessageEmbedField{ + Name: "Ledger position", + Value: fmt.Sprintf("%s **%d**", IconGauge, l.Rank), + Inline: true, + }) + ef = append(ef, &discordgo.MessageEmbedField{ + Name: "Next level in", + Value: fmt.Sprintf("%s **%d** points", IconIncrease, l.ToNextRank), + Inline: true, + }) + + e := []*discordgo.MessageEmbed{ + { + Title: "Your global ledger in Sea of Thieves:", + Thumbnail: &discordgo.MessageEmbedThumbnail{ + URL: fmt.Sprintf("%s/ledger/%s%d.png", AssetsBaseURL, em, 4-l.Band), + }, + Type: discordgo.EmbedTypeRich, + Fields: ef, + }, + } + if _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Embeds: &e}); err != nil { + return err + } + return nil +} + +// SoTGetLedger returns the parsed API response from the Sea of Thieves leaderboard ledger API +func (b *Bot) SoTGetLedger(rq *Requester, em string) (SoTEmissaryLedger, error) { + var l SoTEmissaryLedger + var al SoTLedger + hc, err := NewHTTPClient() + if err != nil { + return l, fmt.Errorf(ErrFailedHTTPClient, err) + } + c, err := rq.GetSoTRATCookie() + if err != nil { + return l, err + } + + urlfmt := "%s/%s?count=3" + var url string + switch strings.ToLower(em) { + case "athena": + url = fmt.Sprintf(urlfmt, ApiURLSoTLedger, "AthenasFortune") + case "hoarder": + url = fmt.Sprintf(urlfmt, ApiURLSoTLedger, "GoldHoarders") + case "merchant": + url = fmt.Sprintf(urlfmt, ApiURLSoTLedger, "MerchantAlliance") + case "order": + url = fmt.Sprintf(urlfmt, ApiURLSoTLedger, "OrderOfSouls") + case "reaper": + url = fmt.Sprintf(urlfmt, ApiURLSoTLedger, "ReapersBones") + default: + return l, fmt.Errorf("unknown emissary given") + } + + r, err := hc.HttpReq(url, ReqMethodGet, nil) + if err != nil { + return l, err + } + r.SetSOTRequest(c) + rd, _, err := hc.Fetch(r) + if err != nil { + return l, err + } + + if err := json.Unmarshal(rd, &al); err != nil { + return l, err + } + + l = al.Current.Friends.User + switch strings.ToLower(em) { + case "athena": + tl := []string{"Legend", "Guardian", "Voyager", "Seeker"} + l.Name = "Athena's Fortune" + l.BandTitle = tl[l.Band] + case "hoarder": + tl := []string{"Captain", "Marauder", "Seafarer", "Castaway"} + l.Name = "Gold Hoarders" + l.BandTitle = tl[l.Band] + case "merchant": + tl := []string{"Admiral", "Commander", "Cadet", "Sailor"} + l.Name = "Merchant Alliance" + l.BandTitle = tl[l.Band] + case "order": + tl := []string{"Grandee", "Chief", "Mercenary", "Apprentice"} + l.Name = "Order of Souls" + l.BandTitle = tl[l.Band] + case "reaper": + tl := []string{"Master", "Keeper", "Servant", "Follower"} + l.Name = "Reaper's Bones" + l.BandTitle = tl[l.Band] + } + + return l, nil +} diff --git a/bot/slashcmd.go b/bot/slashcmd.go index c088d1a..03ef5a0 100644 --- a/bot/slashcmd.go +++ b/bot/slashcmd.go @@ -320,7 +320,7 @@ func (b *Bot) SlashCommandHandler(s *discordgo.Session, i *discordgo.Interaction "overview": b.SlashCmdSoTOverview, "compare": b.SlashCmdSoTCompare, "dailydeeds": b.SlashCmdSoTDailyDeeds, - "ledger": b.SlashCmdSoTDailyDeeds, + "ledger": b.SlashCmdSoTLedger, } // Define list of slash commands that should use ephemeral messages diff --git a/go.sum b/go.sum index 512d50c..268381b 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,6 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bwmarrin/discordgo v0.26.0 h1:/AdFmxHXSHInYAZ7K0O3VEIXlVjGpztk/nuCr9o+JCs= -github.com/bwmarrin/discordgo v0.26.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/bwmarrin/discordgo v0.26.1 h1:AIrM+g3cl+iYBr4yBxCBp9tD9jR3K7upEjl0d89FRkE= github.com/bwmarrin/discordgo v0.26.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=