diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2026-01-22 15:50:28 +0100 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2026-01-22 15:50:28 +0100 |
| commit | 94a11e552b50a389a4e3a6b5fe7bdea4ce7097a4 (patch) | |
| tree | 3342b8dadbd723fbf7e9f568e7944fe3a626f4df | |
| parent | 42c25b54e169aeaf515522ba6103b1fe6db49be7 (diff) | |
refactor(main): remove old gokord from start
| -rw-r--r-- | common/timer.go | 28 | ||||
| -rw-r--r-- | main.go | 181 | ||||
| -rw-r--r-- | user/level.go | 30 |
3 files changed, 145 insertions, 94 deletions
diff --git a/common/timer.go b/common/timer.go new file mode 100644 index 0000000..553a8fd --- /dev/null +++ b/common/timer.go @@ -0,0 +1,28 @@ +package common + +import ( + "context" + "time" + + "github.com/nyttikord/gokord/bot" +) + +func NewTimer(ctx context.Context, d time.Duration, fn func(context.Context, context.CancelFunc)) context.CancelFunc { + ctx, cancel := context.WithCancel(ctx) + logger := bot.Logger(ctx).With("module", "timer") + ctx = bot.SetLogger(ctx, logger) + go func(ctx context.Context, d time.Duration) { + ticker := time.NewTicker(d) + fn(ctx, cancel) + for { + select { + case <-ticker.C: + fn(ctx, cancel) + case <-ctx.Done(): + ticker.Stop() + return + } + } + }(ctx, d) + return cancel +} @@ -4,10 +4,15 @@ import ( "context" _ "embed" "flag" + "log/slog" + "math/rand/v2" "os" + "os/signal" + "syscall" "time" "git.anhgelus.world/anhgelus/les-copaings-bot/commands" + "git.anhgelus.world/anhgelus/les-copaings-bot/common" "git.anhgelus.world/anhgelus/les-copaings-bot/config" "git.anhgelus.world/anhgelus/les-copaings-bot/dynamicid" "git.anhgelus.world/anhgelus/les-copaings-bot/exp" @@ -27,20 +32,20 @@ import ( "gonum.org/v1/plot/font" ) +const Version = "3.4.0" + +// Args var ( token string cfgPath string = "config.toml" - //go:embed updates.json - updatesData []byte - Version = gokord.Version{ - Major: 3, - Minor: 3, - Patch: 0, - } verbose bool +) - stopPeriodicReducer chan<- any - stopPeriodicSaver chan<- any +// Cancel timers +var ( + stopPeriodicReducer context.CancelFunc + stopPeriodicSaver context.CancelFunc + stopStatus context.CancelFunc ) //go:embed assets/inter-variable.ttf @@ -86,7 +91,7 @@ func main() { ctx := user.SetState(context.Background(), user.NewState()) - rankCmd := cmd.New("rank", "Affiche le niveau d'un copaing"). + /*rankCmd := cmd.New("rank", "Affiche le niveau d'un copaing"). AddOption(cmd.NewOption( types.CommandOptionUser, "copaing", @@ -137,73 +142,24 @@ func main() { "salon", "Destination du message", )). - SetHandler(rolereact.HandleCommand) + SetHandler(rolereact.HandleCommand)*/ - innovations, err := gokord.LoadInnovationFromJson(updatesData) - if err != nil { - panic(err) + logLevel := slog.LevelInfo + if verbose { + logLevel = slog.LevelDebug } + dg := discordgo.NewWithLogLevel("Bot "+token, logLevel) - b := gokord.Bot{ - Token: token, - Status: []*gokord.Status{ - { - Type: gokord.WatchStatus, - Content: "Les Copaings", - }, - { - Type: gokord.GameStatus, - Content: "ĂȘtre dev par @anhgelus", - }, - { - Type: gokord.ListeningStatus, - Content: "http 418, I'm a tea pot", - }, - { - Type: gokord.GameStatus, - Content: "Les Copaings Bot " + Version.String(), - }, - }, - Commands: []cmd.CommandBuilder{ - rankCmd, - configCmd, - topCmd, - resetCmd, - resetUserCmd, - creditsCmd, - statsCmd, - rolereactCmd, - }, - AfterInit: func(dg *discordgo.Session) { - d := 24 * time.Hour - if gokord.Debug { - d = 3 * exp.DebugFactor * time.Second - } - d2 := 30 * time.Minute - if gokord.Debug { - d2 = 1 * exp.DebugFactor * time.Second - } + dg.Identify.Intents = discord.IntentsAllWithoutPrivileged | + discord.IntentsMessageContent | + discord.IntentGuildMembers - user.PeriodicReducer(ctx, dg) - - stopPeriodicReducer = gokord.NewTimer(d, func(stop chan<- any) { - user.PeriodicReducer(ctx, dg) - }) - stopPeriodicSaver = gokord.NewTimer(d2, func(c chan<- any) { - user.PeriodicSaver(ctx, dg) - }) - }, - Innovations: innovations, - Version: &Version, - Intents: discord.IntentsAllWithoutPrivileged | - discord.IntentsMessageContent | - discord.IntentGuildMembers, - Verbose: verbose, - } + events := dg.EventManager() + events.AddHandler(ready) // related to rolereact // TEMP BECAUSE (OLD) GOKORD DOES NOT SUPPORT COMMAND MESSAGE - b.AddHandler(func(ctx context.Context, s bot.Session, e *event.Ready) { + events.AddHandler(func(ctx context.Context, s bot.Session, e *event.Ready) { guildID := "" logger := bot.Logger(ctx) if gokord.Debug { @@ -230,10 +186,10 @@ func main() { } logger.Debug("pushed rolereaction message command", "CommandID", c.ID) }) - b.AddHandler(func(ct context.Context, s bot.Session, _ *event.Disconnect) { + events.AddHandler(func(ct context.Context, s bot.Session, _ *event.Disconnect) { user.PeriodicSaver(ctx, s) }) - b.AddHandler(func(ctx context.Context, s bot.Session, i *event.InteractionCreate) { + events.AddHandler(func(ctx context.Context, s bot.Session, i *event.InteractionCreate) { if i.Type != types.InteractionApplicationCommand { return } @@ -242,8 +198,8 @@ func main() { rolereact.HandleModifyCommand(ctx, s, cmd) } }) - b.AddHandler(rolereact.HandleReactionAdd) - b.AddHandler(rolereact.HandleReactionRemove) + events.AddHandler(rolereact.HandleReactionAdd) + events.AddHandler(rolereact.HandleReactionRemove) dynamicid.HandleDynamicMessageComponent(&b, rolereact.HandleModifyComponent, rolereact.OpenMessage) dynamicid.HandleDynamicMessageComponent(&b, rolereact.HandleApplyMessage, rolereact.ApplyMessage) dynamicid.HandleDynamicMessageComponent(&b, rolereact.HandleResetMessage, rolereact.ResetMessage) @@ -286,17 +242,82 @@ func main() { }, config.TimeReduceSet) // xp handlers - b.AddHandler(OnMessage) - b.AddHandler(OnVoiceUpdate) - b.AddHandler(OnLeave) + events.AddHandler(OnMessage) + events.AddHandler(OnVoiceUpdate) + events.AddHandler(OnLeave) - b.Start(ctx) + err = dg.Open(ctx) + if err != nil { + panic(err) + } + + setupTimers(ctx, dg) + + sc := make(chan os.Signal, 1) + signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) + <-sc + + dg.Logger().Info("stopping") + + err = dg.Close(ctx) + if err != nil { + panic(err) + } if stopPeriodicReducer != nil { - stopPeriodicReducer <- true + stopPeriodicReducer() } if stopPeriodicSaver != nil { - stopPeriodicSaver <- true + stopPeriodicSaver() + } +} + +func setupTimers(ctx context.Context, dg bot.Session) { + d := 24 * time.Hour + if gokord.Debug { + d = 3 * exp.DebugFactor * time.Second } + d2 := 30 * time.Minute + if gokord.Debug { + d2 = 1 * exp.DebugFactor * time.Second + } + + user.PeriodicReducer(ctx, dg) + + stopPeriodicReducer = common.NewTimer(ctx, d, func(ctx context.Context, _ context.CancelFunc) { + user.PeriodicReducer(ctx, dg) + }) + stopPeriodicSaver = common.NewTimer(ctx, d2, func(ctx context.Context, _ context.CancelFunc) { + user.PeriodicSaver(ctx, dg) + }) +} + +var statuses = []func(context.Context, bot.Session) error{ + func(ctx context.Context, dg bot.Session) error { + return dg.BotAPI().UpdateGameStatus(ctx, 0, "ĂȘtre dev par @anhgelus") + }, + func(ctx context.Context, dg bot.Session) error { + return dg.BotAPI().UpdateWatchStatus(ctx, 0, "Les Copaings") + }, + func(ctx context.Context, dg bot.Session) error { + return dg.BotAPI().UpdateListeningStatus(ctx, "http 418, I'm a tea pot") + }, + func(ctx context.Context, dg bot.Session) error { + return dg.BotAPI().UpdateGameStatus(ctx, 0, "Les Copaings Bot v"+Version) + }, +} + +func ready(ctx context.Context, dg bot.Session, _ *event.Ready) { + logger := bot.Logger(ctx) + logger.Info("bot started", "as", dg.SessionState().User().Username) + now := time.Now().Unix() + rd := rand.New(rand.NewPCG(uint64(now), uint64(len(statuses)))) + stopStatus = common.NewTimer(ctx, 30*time.Second, func(ctx context.Context, _ context.CancelFunc) { + rnd := rd.UintN(uint(len(statuses))) + err := statuses[rnd](ctx, dg) + if err != nil { + bot.Logger(ctx).Error("updating status", "error", err) + } + }) } diff --git a/user/level.go b/user/level.go index 92c10ab..41fb291 100644 --- a/user/level.go +++ b/user/level.go @@ -9,7 +9,6 @@ import ( "git.anhgelus.world/anhgelus/les-copaings-bot/config" "git.anhgelus.world/anhgelus/les-copaings-bot/exp" "github.com/anhgelus/gokord" - discordgo "github.com/nyttikord/gokord" "github.com/nyttikord/gokord/bot" "github.com/nyttikord/gokord/user" ) @@ -46,19 +45,20 @@ func onNewLevel(s bot.Session, m *user.Member, level uint) { } } -func (c *CopaingCached) onNewLevel(s *discordgo.Session, level uint) { - m, err := s.GuildAPI().Member(c.GuildID, c.DiscordID) +func (c *CopaingCached) onNewLevel(ctx context.Context, s bot.Session, level uint) { + m, err := s.GuildAPI().Member(c.GuildID, c.DiscordID).Do(ctx) if err != nil { - s.Logger().Error("getting member for new level", "error", err, "user", c.DiscordID, "guild", c.GuildID) + bot.Logger(ctx).Error("getting member for new level", "error", err, "user", c.DiscordID, "guild", c.GuildID) return } onNewLevel(s, m, level) } -func PeriodicReducer(ctx context.Context, s *discordgo.Session) { +func PeriodicReducer(ctx context.Context, s bot.Session) { PeriodicSaver(ctx, s) - s.Logger().Debug("periodic reducer") + logger := bot.Logger(ctx) + logger.Debug("periodic reducer") state := GetState(ctx) @@ -72,10 +72,10 @@ func PeriodicReducer(ctx context.Context, s *discordgo.Session) { Where("guild_id = ? and created_at < ?", g, exp.TimeStampNDaysBefore(cfg.DaysXPRemains)). Delete(&CopaingXP{}) if res.Error != nil { - s.Logger().Error("removing old xp", "error", res.Error, "guild", g) + logger.Error("removing old xp", "error", res.Error, "guild", g) continue } - s.Logger().Debug("guild cleaned", "guild", g, "rows affected", res.RowsAffected) + logger.Debug("guild cleaned", "guild", g, "rows affected", res.RowsAffected) wg.Go(func() { syncCopaings(ctx, s, state.Copaings(g)) @@ -84,30 +84,32 @@ func PeriodicReducer(ctx context.Context, s *discordgo.Session) { wg.Wait() - s.Logger().Debug("periodic reduce finished", "guilds affected", n) + logger.Debug("periodic reduce finished", "guilds affected", n) } -func syncCopaings(ctx context.Context, s *discordgo.Session, ccs []CopaingCached) { +func syncCopaings(ctx context.Context, s bot.Session, ccs []CopaingCached) { + logger := bot.Logger(ctx) for i, cc := range ccs { if i%50 == 49 { - s.Logger().Debug("sleeping...") + logger.Debug("sleeping...") time.Sleep(15 * time.Second) // prevents spamming the API } oldXp := cc.XP err := cc.Sync(ctx) if err != nil { - s.Logger().Error("syncing copaing", "error", err, "copaing", cc.ID, "guild", cc.GuildID) + logger.Error("syncing copaing", "error", err, "copaing", cc.ID, "guild", cc.GuildID) continue } xp := cc.XP if exp.Level(oldXp) != exp.Level(xp) { - cc.onNewLevel(s, exp.Level(xp)) + cc.onNewLevel(ctx, s, exp.Level(xp)) } } } func PeriodicSaver(ctx context.Context, s bot.Session) { - s.Logger().Debug("saving state in DB") + logger := bot.Logger(ctx) + logger.Debug("saving state in DB") err := saveStateInDB(ctx) if err != nil { panic(err) |
