aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2026-01-22 15:50:28 +0100
committerAnhgelus Morhtuuzh <william@herges.fr>2026-01-22 15:50:28 +0100
commit94a11e552b50a389a4e3a6b5fe7bdea4ce7097a4 (patch)
tree3342b8dadbd723fbf7e9f568e7944fe3a626f4df
parent42c25b54e169aeaf515522ba6103b1fe6db49be7 (diff)
refactor(main): remove old gokord from start
-rw-r--r--common/timer.go28
-rw-r--r--main.go181
-rw-r--r--user/level.go30
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
+}
diff --git a/main.go b/main.go
index 6a1da6a..496309d 100644
--- a/main.go
+++ b/main.go
@@ -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)