diff options
| -rw-r--r-- | commands/reset.go | 5 | ||||
| -rw-r--r-- | commands/stats.go | 12 | ||||
| -rw-r--r-- | common/db.go | 57 | ||||
| -rw-r--r-- | config/guild.go | 5 | ||||
| -rw-r--r-- | config/xp_role.go | 7 | ||||
| -rw-r--r-- | main.go | 19 | ||||
| -rw-r--r-- | migrations/000-leave-gorm.sql | 8 | ||||
| -rw-r--r-- | rolereact/events.go | 18 | ||||
| -rw-r--r-- | rolereact/manager.go | 14 | ||||
| -rw-r--r-- | user/level.go | 5 | ||||
| -rw-r--r-- | user/member.go | 15 | ||||
| -rw-r--r-- | user/state.go | 8 |
12 files changed, 113 insertions, 60 deletions
diff --git a/commands/reset.go b/commands/reset.go index f9c81d2..d18e6ea 100644 --- a/commands/reset.go +++ b/commands/reset.go @@ -3,16 +3,15 @@ package commands import ( "context" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" "git.anhgelus.world/anhgelus/les-copaings-bot/user" "github.com/nyttikord/gokord/bot" "github.com/nyttikord/gokord/interaction" ) func Reset(ctx context.Context, dg bot.Session, i *interaction.ApplicationCommand) { - var copaings []*user.Copaing + //var copaings []*user.Copaing //TODO: delete everything from cache - common.GetDB(ctx).Where("guild_id = ?", i.GuildID).Delete(&copaings) + //common.GetDB(ctx).Where("guild_id = ?", i.GuildID).Delete(&copaings) resp := interaction.NewMessageResponse().IsEphemeral().Message("L'XP a été reset.").Response() err := interaction.Respond(i.Interaction, resp).Do(ctx) if err != nil { diff --git a/commands/stats.go b/commands/stats.go index 15f258b..28c0bcc 100644 --- a/commands/stats.go +++ b/commands/stats.go @@ -111,10 +111,10 @@ func Stats(ctx context.Context, dg bot.Session, i *interaction.ApplicationComman func statsAll(ctx context.Context, dg bot.Session, i *interaction.ApplicationCommand, days int) (io.WriterTo, error) { return stats(ctx, dg, i, days, func(before, after string) *gorm.DB { - return common.GetDB(ctx).Raw( + return nil /*common.GetDB(ctx).Raw( before+"WHERE guild_id = ? and created_at > ?"+after, i.GuildID, exp.TimeStampNDaysBefore(ctx, uint(days)), - ) + )*/ }) } @@ -124,10 +124,10 @@ func statsMember(ctx context.Context, dg bot.Session, i *interaction.Application return nil, err } return stats(ctx, dg, i, days, func(before, after string) *gorm.DB { - return common.GetDB(ctx).Raw( + return nil /*common.GetDB(ctx).Raw( before+"WHERE guild_id = ? and created_at > ? and copaing_id = ?"+after, i.GuildID, exp.TimeStampNDaysBefore(ctx, uint(days)), user.GetCopaing(ctx, discordID, i.GuildID).ID, - ) + )*/ }) } @@ -171,7 +171,7 @@ func stats(ctx context.Context, dg bot.Session, i *interaction.ApplicationComman for _, raw := range rawData { _, ok := copaings[raw.CopaingID] if !ok { - var cp user.Copaing + /*var cp user.Copaing if err := common.GetDB(ctx).First(&cp, raw.CopaingID).Error; err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { bot.Logger(ctx).Error("finding copaing", "error", err, "copaing", raw.CopaingID) @@ -180,7 +180,7 @@ func stats(ctx context.Context, dg bot.Session, i *interaction.ApplicationComman bot.Logger(ctx).Warn("copaing not found, skipping", "copaing", raw.CopaingID) continue } - copaings[raw.CopaingID] = &cp + copaings[raw.CopaingID] = &cp*/ } pts, ok := stats[raw.CopaingID] now := time.Now().Unix() diff --git a/common/db.go b/common/db.go new file mode 100644 index 0000000..76e39a2 --- /dev/null +++ b/common/db.go @@ -0,0 +1,57 @@ +package common + +import ( + "context" + "database/sql" + "embed" + "fmt" + "log/slog" + "path" + "regexp" + "strconv" + "strings" + + "github.com/nyttikord/avl" +) + +var regexpMigration = regexp.MustCompile(`(\d{3})-(.*)\.sql`) + +type migrationData struct { + id uint64 + name string + content string +} + +func Migrate(ctx context.Context, log *slog.Logger, db *sql.DB, migrations embed.FS, dir string) error { + entries, err := migrations.ReadDir(dir) + if err != nil { + return err + } + tree := avl.NewKeySimple[uint64, migrationData]() + for _, entry := range entries { + if strings.HasSuffix(entry.Name(), ".sql") { + log.Debug("reading migration...", "path", dir+"/"+entry.Name()) + subs := regexpMigration.FindStringSubmatch(entry.Name()) + if len(subs) < 3 { + return fmt.Errorf("invalid migration name %s", entry.Name()) + } + id, _ := strconv.ParseUint(subs[1], 10, 16) + b, err := migrations.ReadFile(path.Join(dir, entry.Name())) + if err != nil { + return err + } + tree.Insert(id, migrationData{id, subs[2], string(b)}) + } else { + log.Warn("invalid migration entry, skipping", "path", dir+"/"+entry.Name()) + } + } + for _, mig := range tree.Sort() { + log.Debug("migrating...", "id", mig.id, "name", mig.name) + _, err := db.ExecContext(ctx, mig.content) + if err != nil { + log.Error("migrating", "id", mig.id, "name", mig.name) + return err + } + } + return nil +} diff --git a/config/guild.go b/config/guild.go index bcebd65..dc8251f 100644 --- a/config/guild.go +++ b/config/guild.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" "github.com/nyttikord/gokord/bot" "github.com/nyttikord/gokord/channel" ) @@ -47,11 +46,11 @@ func GetGuildConfig(ctx context.Context, guildID uint64) *Guild { } func (cfg *Guild) Load(ctx context.Context) error { - return common.GetDB(ctx).Where("guild_id = ?", cfg.GuildID).Preload("XpRoles").FirstOrCreate(cfg).Error + return nil //common.GetDB(ctx).Where("guild_id = ?", cfg.GuildID).Preload("XpRoles").FirstOrCreate(cfg).Error } func (cfg *Guild) Save(ctx context.Context) error { - return common.GetDB(ctx).Save(cfg).Error + return nil //common.GetDB(ctx).Save(cfg).Error } func (cfg *Guild) IsDisabled(ctx context.Context, dg bot.Session, channelID uint64) bool { diff --git a/config/xp_role.go b/config/xp_role.go index 6592ac9..81082e8 100644 --- a/config/xp_role.go +++ b/config/xp_role.go @@ -6,7 +6,6 @@ import ( "slices" "strconv" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" "git.anhgelus.world/anhgelus/les-copaings-bot/dynamicid" "git.anhgelus.world/anhgelus/les-copaings-bot/exp" "github.com/nyttikord/gokord/bot" @@ -210,7 +209,7 @@ func HandleXpRoleEditRole(ctx context.Context, dg bot.Session, i *interaction.Me return } xpRole.RoleID = role - err = common.GetDB(ctx).Save(xpRole).Error + err = nil // common.GetDB(ctx).Save(xpRole).Error if err != nil { bot.Logger(ctx).Error("saving config", "error", err, "guild", i.GuildID, "id", id, "type", "add") } @@ -295,7 +294,7 @@ func HandleXpRoleEditLevel(ctx context.Context, dg bot.Session, i *interaction.M return } xpRole.XP = xp - err = common.GetDB(ctx).Save(xpRole).Error + err = nil //common.GetDB(ctx).Save(xpRole).Error if err != nil { bot.Logger(ctx).Error("saving config", "guild", i.GuildID, "id", id, "type", "edit") } @@ -319,7 +318,7 @@ func HandleXpRoleDel(ctx context.Context, dg bot.Session, i *interaction.Message } return } - err := common.GetDB(ctx).Delete(role).Error + var err error = nil //common.GetDB(ctx).Delete(role).Error if err != nil { bot.Logger(ctx).Error("deleting entry", "error", err, "guild", i.GuildID, "id", id, "type", "del") } @@ -2,7 +2,7 @@ package main import ( "context" - _ "embed" + "embed" "flag" "log/slog" "math/rand/v2" @@ -51,6 +51,9 @@ var finishDeploy context.CancelFunc //go:embed assets/inter-variable.ttf var interTTF []byte +//go:embed migrations +var migrations embed.FS + func init() { flag.StringVar(&token, "token", os.Getenv("TOKEN"), "token of the bot") flag.StringVar(&cfgPath, "config", cfgPath, "config's path") @@ -87,7 +90,13 @@ func main() { panic(err) } - err = db.AutoMigrate(&user.Copaing{}, &config.Guild{}, &config.XpRole{}, &user.CopaingXP{}, &config.RoleReactMessage{}, &config.RoleReact{}) + logLevel := slog.LevelInfo + if verbose || cfg.Debug { + logLevel = slog.LevelDebug + } + dg := gokord.NewWithLogLevel("Bot "+token, logLevel) + + err = common.Migrate(context.Background(), dg.Logger(), db, migrations, "migrations") if err != nil { panic(err) } @@ -97,12 +106,6 @@ func main() { ctx = common.SetDebug(ctx, cfg.Debug) ctx = common.SetAuthor(ctx, cfg.Author) - logLevel := slog.LevelInfo - if verbose || cfg.Debug { - logLevel = slog.LevelDebug - } - dg := gokord.NewWithLogLevel("Bot "+token, logLevel) - dg.Identify.Intents = discord.IntentsAllWithoutPrivileged | discord.IntentsMessageContent | discord.IntentGuildMembers diff --git a/migrations/000-leave-gorm.sql b/migrations/000-leave-gorm.sql index 91addd8..f80555a 100644 --- a/migrations/000-leave-gorm.sql +++ b/migrations/000-leave-gorm.sql @@ -1,11 +1,11 @@ -CREATE DOMAIN snowflake AS NUMERIC(20,0) CHECK (VALUE < 36893488147419103232 and CHECK VALUE > 0); +CREATE DOMAIN snowflake AS NUMERIC(20,0) CHECK (VALUE > 0); CREATE DOMAIN uint AS INTEGER CHECK (VALUE >= 0); CREATE TABLE IF NOT EXISTS guilds ( id snowflake PRIMARY KEY, disabled_channels TEXT, fallback_channel snowflake, - days_xp_remains INTEGER CHECK (VALUE > 0) DEFAULT 90 + days_xp_remains INTEGER CHECK (days_xp_remains > 0) DEFAULT 90 ); CREATE TABLE IF NOT EXISTS copaings ( @@ -17,7 +17,7 @@ CREATE TABLE IF NOT EXISTS copaing_xps ( copaing_id snowflake REFERENCES copaings(id) NOT NULL, guild_id snowflake REFERENCES copaings(id) NOT NULL, xp uint DEFAULT 0, - created_at TIMESTAMP DEFAULT NOW, + created_at TIMESTAMP DEFAULT now(), PRIMARY KEY(copaing_id, guild_id, created_at) ); @@ -38,7 +38,7 @@ CREATE TABLE IF NOT EXISTS role_react_messages ( CREATE TABLE IF NOT EXISTS role_reacts ( role snowflake, - message_id snowflake REFERENCES role_react_messages(id), + message_id INTEGER REFERENCES role_react_messages(id), reaction TEXT, PRIMARY KEY(role, message_id, reaction) ); diff --git a/rolereact/events.go b/rolereact/events.go index ac5ad60..c341df7 100644 --- a/rolereact/events.go +++ b/rolereact/events.go @@ -3,8 +3,6 @@ package rolereact import ( "context" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" - "git.anhgelus.world/anhgelus/les-copaings-bot/config" "github.com/nyttikord/gokord/bot" "github.com/nyttikord/gokord/event" "github.com/nyttikord/gokord/guild" @@ -16,10 +14,10 @@ type RoleReact struct { func HandleReactionAdd(ctx context.Context, dg bot.Session, e *event.MessageReactionAdd) { results := []RoleReact{} - common.GetDB(ctx).Model(&config.RoleReact{}). - Joins("JOIN role_react_messages ON role_reacts.role_react_message_id = role_react_messages.id"). - Where("role_react_messages.message_id = ? AND role_reacts.reaction = ?", e.MessageID, e.MessageReaction.Emoji.APIName()). - Scan(&results) + /*common.GetDB(ctx).Model(&config.RoleReact{}). + Joins("JOIN role_react_messages ON role_reacts.role_react_message_id = role_react_messages.id"). + Where("role_react_messages.message_id = ? AND role_reacts.reaction = ?", e.MessageID, e.MessageReaction.Emoji.APIName()). + Scan(&results)*/ for _, role := range results { err := guild.AddMemberRole(e.GuildID, e.UserID, role.RoleID).Do(ctx) if err != nil { @@ -30,10 +28,10 @@ func HandleReactionAdd(ctx context.Context, dg bot.Session, e *event.MessageReac func HandleReactionRemove(ctx context.Context, dg bot.Session, e *event.MessageReactionRemove) { results := []RoleReact{} - common.GetDB(ctx).Model(&config.RoleReact{}). - Joins("JOIN role_react_messages ON role_reacts.role_react_message_id = role_react_messages.id"). - Where("role_react_messages.message_id = ? AND role_reacts.reaction = ?", e.MessageID, e.MessageReaction.Emoji.APIName()). - Scan(&results) + /*common.GetDB(ctx).Model(&config.RoleReact{}). + Joins("JOIN role_react_messages ON role_reacts.role_react_message_id = role_react_messages.id"). + Where("role_react_messages.message_id = ? AND role_reacts.reaction = ?", e.MessageID, e.MessageReaction.Emoji.APIName()). + Scan(&results)*/ for _, role := range results { err := guild.RemoveMemberRole(e.GuildID, e.UserID, role.RoleID).Do(ctx) if err != nil { diff --git a/rolereact/manager.go b/rolereact/manager.go index 91e1bcd..6455b97 100644 --- a/rolereact/manager.go +++ b/rolereact/manager.go @@ -7,7 +7,6 @@ import ( "strings" "time" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" "git.anhgelus.world/anhgelus/les-copaings-bot/config" "github.com/nyttikord/gokord/bot" "github.com/nyttikord/gokord/channel" @@ -64,11 +63,11 @@ func ApplyMessageChange(ctx context.Context, dg bot.Session, i *interaction.Inte for _, role := range message.Roles { roles[role.ID] = *role } - db := common.GetDB(ctx) + //db := common.GetDB(ctx) for _, role := range oldMessage.Roles { _, ok := roles[role.ID] if !ok { - err := db.Delete(role).Error + err = nil //db.Delete(role).Error if err != nil { bot.Logger(ctx).Error("unable to delete reaction role from database", "error", err) return "Impossible de sauvegarder le message de rôle. Merci de contacter l'administrateur du bot." @@ -76,13 +75,14 @@ func ApplyMessageChange(ctx context.Context, dg bot.Session, i *interaction.Inte } } cfg.RrMessages[messageIndex] = *message - err = db.Save(cfg.RrMessages[messageIndex]).Error + err = nil //db.Save(cfg.RrMessages[messageIndex]).Error if err != nil { bot.Logger(ctx).Error("unable to save rolereaction message in database", "error", err) return "Impossible de sauvegarder le message de rôle. Merci de contacter l'administrateur du bot." } for _, role := range cfg.RrMessages[messageIndex].Roles { - err = db.Save(role).Error + println(role.ID) + err = nil //db.Save(role).Error if err != nil { bot.Logger(ctx).Error("unable to save rolereaction role in database", "error", err) return "Impossible de sauvegarder le message de rôle. Merci de contacter l'administrateur du bot." @@ -125,10 +125,10 @@ func GetMessageFromEditID(ctx context.Context, i *interaction.Interaction, editI func GetGuildConfigPreloaded(ctx context.Context, guildID uint64) *config.Guild { cfg := config.Guild{GuildID: guildID} // err := oldGokord.DB.Where("guild_id = ?", cfg.GuildID).Preload("XpRoles").Preload("RrMessages.Roles").FirstOrCreate(cfg).Error - err := common.GetDB(ctx).Where("guild_id = ?", cfg.GuildID).Preload("RrMessages.Roles").FirstOrCreate(&cfg).Error + /*err := common.GetDB(ctx).Where("guild_id = ?", cfg.GuildID).Preload("RrMessages.Roles").FirstOrCreate(&cfg).Error if err != nil { panic(err) - } + }*/ return &cfg } diff --git a/user/level.go b/user/level.go index 98b9329..012f253 100644 --- a/user/level.go +++ b/user/level.go @@ -6,7 +6,6 @@ import ( "sync" "time" - "git.anhgelus.world/anhgelus/les-copaings-bot/common" "git.anhgelus.world/anhgelus/les-copaings-bot/config" "git.anhgelus.world/anhgelus/les-copaings-bot/exp" "github.com/nyttikord/gokord/bot" @@ -60,7 +59,7 @@ func PeriodicReducer(ctx context.Context, dg bot.Session) { n := 0 var wg sync.WaitGroup for _, g := range dg.GuildState().ListGuilds() { - cfg := config.GetGuildConfig(ctx, g) + /*cfg := config.GetGuildConfig(ctx, g) res := common.GetDB(ctx). Model(&CopaingXP{}). Where("guild_id = ? and created_at < ?", g, exp.TimeStampNDaysBefore(ctx, cfg.DaysXPRemains)). @@ -70,7 +69,7 @@ func PeriodicReducer(ctx context.Context, dg bot.Session) { continue } n++ - log.Debug("guild cleaned", "guild", g, "rows affected", res.RowsAffected) + log.Debug("guild cleaned", "guild", g, "rows affected", res.RowsAffected)*/ wg.Go(func() { syncCopaings(ctx, dg, state.Copaings(g)) diff --git a/user/member.go b/user/member.go index db39911..e22e00c 100644 --- a/user/member.go +++ b/user/member.go @@ -3,8 +3,6 @@ package user import ( "context" "time" - - "git.anhgelus.world/anhgelus/les-copaings-bot/common" ) type Copaing struct { @@ -41,7 +39,8 @@ func GetCopaing(ctx context.Context, discordID, guildID uint64) *CopaingCached { } func (c *Copaing) load(ctx context.Context) error { - err := common.GetDB(ctx). + return nil + /*err := common.GetDB(ctx). Where("discord_id = ? and guild_id = ?", c.DiscordID, c.GuildID). Preload("CopaingXPs"). FirstOrCreate(c). @@ -49,21 +48,21 @@ func (c *Copaing) load(ctx context.Context) error { if err != nil { return err } - return err + return err*/ } func (c *Copaing) Save(ctx context.Context) error { - return common.GetDB(ctx).Save(c).Error + return nil //common.GetDB(ctx).Save(c).Error } func (c *Copaing) Delete(ctx context.Context) error { - db := common.GetDB(ctx) + /*db := common.GetDB(ctx) err := db. Where("copaing_id = ? and guild_id = ?", c.ID, c.GuildID). Delete(&CopaingXP{}). Error if err != nil { return err - } - return db.Where("guild_id = ? AND discord_id = ?", c.GuildID, c.DiscordID).Delete(c).Error + }*/ + return nil // db.Where("guild_id = ? AND discord_id = ?", c.GuildID, c.DiscordID).Delete(c).Error } diff --git a/user/state.go b/user/state.go index 9f1c90e..f2bfa5c 100644 --- a/user/state.go +++ b/user/state.go @@ -2,6 +2,7 @@ package user import ( "context" + "database/sql" "errors" "fmt" "math" @@ -11,7 +12,6 @@ import ( "git.anhgelus.world/anhgelus/les-copaings-bot/common" "github.com/nyttikord/avl" "github.com/nyttikord/gokord/state" - "gorm.io/gorm" ) var ErrSyncingUnsavedData = errors.New("trying to sync unsaved data") @@ -141,15 +141,15 @@ type State struct { storage *state.AVLStorage[string, CopaingCached] } -func NewState(db *gorm.DB) *State { +func NewState(db *sql.DB) *State { state := &State{ storage: state.WrapAVLAsStorage(avl.NewKeyString[CopaingCached]()), } var cs []*Copaing - err := db.Find(&cs).Error + /*err := db.Find(&cs).Error if err != nil { panic(err) - } + }*/ for _, v := range cs { FromCopaing(v).Save(SetState(context.Background(), state)) } |
