diff --git a/commands/config.go b/commands/config.go index 472a4ea..0f9a6d6 100644 --- a/commands/config.go +++ b/commands/config.go @@ -7,15 +7,30 @@ import ( "github.com/anhgelus/les-copaings-bot/config" "github.com/anhgelus/les-copaings-bot/exp" "github.com/bwmarrin/discordgo" + "strconv" "strings" + "time" ) const ( - SelectConfigModify = "config_modify" - SelectOptConfigXpRole = "xp_role" - SelectOptConfigDisChannel = "disabled_channel" - SelectOptConfigFallbackChannel = "fallback_channel" - SelectOptConfigTimeReduce = "time_reduce" + ConfigModify = "config_modify" + ConfigModifyXpRole = "xp_role" + ConfigModifyDisChannel = "disabled_channel" + ConfigModifyFallbackChannel = "fallback_channel" + ConfigModifyTimeReduce = "time_reduce" + // xp role related + XpRoleAdd = "xp_role_add" + XpRoleAddLevel = "xp_role_add_level" + XpRoleAddRole = "xp_role_add_role" + XpRoleDel = "xp_role_del" + XpRoleDelRole = "xp_role_del_role" + XpRoleEdit = "xp_role_edit" + XpRoleEditLevel = "xp_role_edit_level" + XpRoleEditRole = "xp_role_edit_role" +) + +var ( + configModifyMap = map[string]uint{} ) func Config(s *discordgo.Session, i *discordgo.InteractionCreate, optMap utils.OptionMap, resp *utils.ResponseBuilder) { @@ -80,30 +95,30 @@ func Config(s *discordgo.Session, i *discordgo.InteractionCreate, optMap utils.O }).AddComponent(discordgo.ActionsRow{Components: []discordgo.MessageComponent{ discordgo.SelectMenu{ MenuType: discordgo.StringSelectMenu, - CustomID: SelectConfigModify, + CustomID: ConfigModify, Placeholder: "Modifier...", Options: []discordgo.SelectMenuOption{ { Label: "Rôles liés à l'XP", - Value: SelectOptConfigXpRole, + Value: ConfigModifyXpRole, Description: "Gère les rôles liés à l'XP", Emoji: &discordgo.ComponentEmoji{Name: "🏅"}, }, { Label: "Salons désactivés", - Value: SelectOptConfigDisChannel, + Value: ConfigModifyDisChannel, Description: "Gère les salons désactivés", Emoji: &discordgo.ComponentEmoji{Name: "❌"}, }, { Label: "Salons de repli", // I don't have a better idea for this... - Value: SelectOptConfigFallbackChannel, + Value: ConfigModifyFallbackChannel, Description: "Spécifie le salon de repli", Emoji: &discordgo.ComponentEmoji{Name: "💾"}, }, { Label: "Temps avec la réduction", - Value: SelectOptConfigTimeReduce, + Value: ConfigModifyTimeReduce, Description: "Gère le temps avant la réduction d'XP", Emoji: &discordgo.ComponentEmoji{Name: "⌛"}, }, @@ -117,52 +132,76 @@ func Config(s *discordgo.Session, i *discordgo.InteractionCreate, optMap utils.O } func ConfigXP(s *discordgo.Session, i *discordgo.InteractionCreate) { - resp.IsEphemeral() - // verify every args - t, ok := optMap["type"] - if !ok { - err := resp.SetMessage("Le type d'action n'a pas été renseigné.").Send() - if err != nil { - utils.SendAlert("commands/config.go - Action type not set", err.Error()) - } + if i.Type != discordgo.InteractionMessageComponent { return } - ts := t.StringValue() - lvl, ok := optMap["level"] - if !ok { - err := resp.SetMessage("Le niveau n'a pas été renseigné.").Send() - if err != nil { - utils.SendAlert("commands/config.go - Level not set", err.Error()) - } - return - } - level := lvl.IntValue() - if level < 1 { - err := resp.SetMessage("Le niveau doit forcément être supérieur à 0.").Send() - if err != nil { - utils.SendAlert("commands/config.go - Invalid level", err.Error()) - } - return - } - xp := exp.LevelXP(uint(level)) - r, ok := optMap["role"] - if !ok { - err := resp.SetMessage("Le rôle n'a pas été renseigné.").Send() - if err != nil { - utils.SendAlert("commands/config.go - Role not set", err.Error()) - } - return - } - role := r.RoleValue(s, i.GuildID) + cfg := config.GetGuildConfig(i.GuildID) - // add or delete or edit - var err error - switch ts { - case "add": + resp := utils.NewResponseBuilder(s, i) + + msgData := i.MessageComponentData() + switch msgData.CustomID { + case ConfigModifyXpRole: + err := resp.IsEphemeral(). + SetMessage("Action à réaliser"). + AddComponent(discordgo.ActionsRow{Components: []discordgo.MessageComponent{ + discordgo.SelectMenu{ + MenuType: discordgo.StringSelectMenu, + CustomID: ConfigModify, + Placeholder: "Action", + Options: []discordgo.SelectMenuOption{ + { + Label: "Ajouter", + Value: XpRoleAdd, + Description: "Ajouter un rôle à XP", + Emoji: &discordgo.ComponentEmoji{Name: "⬆️"}, + }, + { + Label: "Supprimer", + Value: XpRoleDel, + Description: "Supprimer un rôle à XP", + Emoji: &discordgo.ComponentEmoji{Name: "❌"}, + }, + { + Label: "Modifier", + Value: XpRoleEdit, + Description: "Modifier un rôle à XP", + Emoji: &discordgo.ComponentEmoji{Name: "📝"}, + }, + }, + }, + }}).Send() + if err != nil { + utils.SendAlert("config/guild.go - Sending config", err.Error()) + } + case XpRoleAdd, XpRoleEdit: + cID := XpRoleAddLevel + if msgData.CustomID == XpRoleEdit { + cID = XpRoleEditLevel + } + err := resp.IsModal(). + SetTitle("Role"). + AddComponent(discordgo.ActionsRow{Components: []discordgo.MessageComponent{ + discordgo.TextInput{ + CustomID: cID, + Label: "Niveau", + Style: discordgo.TextInputShort, + Placeholder: "5", + Required: true, + MinLength: 0, + MaxLength: 5, + }, + }}). + Send() + if err != nil { + utils.SendAlert("config/guild.go - Sending modal to add", err.Error()) + } + case XpRoleAddRole: + roleId := msgData.Values[0] for _, r := range cfg.XpRoles { - if r.RoleID == role.ID { - err = resp.SetMessage("Le rôle est déjà présent dans la config").Send() + if r.RoleID == roleId { + err := resp.SetMessage("Le rôle est déjà présent dans la config").Send() if err != nil { utils.SendAlert("commands/config.go - Role already in config", err.Error()) } @@ -170,82 +209,140 @@ func ConfigXP(s *discordgo.Session, i *discordgo.InteractionCreate) { } } cfg.XpRoles = append(cfg.XpRoles, config.XpRole{ - XP: xp, - RoleID: role.ID, + XP: configModifyMap[getKeyConfigRole(i)], + RoleID: roleId, }) - err = cfg.Save() + err := cfg.Save() if err != nil { utils.SendAlert( "commands/config.go - Saving config", err.Error(), - "guild_id", - i.GuildID, - "role_id", - role.ID, - "type", - "add", + "guild_id", i.GuildID, + "role_id", roleId, + "type", "add", ) } - case "del": - _, r := cfg.FindXpRole(role.ID) - if r == nil { - err = resp.SetMessage("Le rôle n'a pas été trouvé dans la config.").Send() - if err != nil { - utils.SendAlert("commands/config.go - Role not found (del)", err.Error()) - } - return + if err = resp.IsEphemeral().SetMessage("Rôle ajouté.").Send(); err != nil { + utils.SendAlert("commands/config.go - Sending success", err.Error()) } - err = gokord.DB.Delete(r).Error - if err != nil { - utils.SendAlert( - "commands/config.go - Deleting entry", - err.Error(), - "guild_id", - i.GuildID, - "role_id", - role.ID, - "type", - "del", - ) - } - case "edit": - _, r := cfg.FindXpRole(role.ID) + case XpRoleEditRole: + roleId := msgData.Values[0] + _, r := cfg.FindXpRole(roleId) if r == nil { - err = resp.SetMessage("Le rôle n'a pas été trouvé dans la config.").Send() + err := resp.SetMessage("Le rôle n'a pas été trouvé dans la config.").Send() if err != nil { utils.SendAlert("commands/config.go - Role not found (edit)", err.Error()) } return } - r.XP = xp - err = gokord.DB.Save(r).Error + r.XP = configModifyMap[getKeyConfigRole(i)] + err := gokord.DB.Save(r).Error if err != nil { utils.SendAlert( "commands/config.go - Saving config", err.Error(), - "guild_id", - i.GuildID, - "role_id", - role.ID, - "type", - "edit", + "guild_id", i.GuildID, + "role_id", roleId, + "type", "edit", ) } + if err = resp.IsEphemeral().SetMessage("Rôle modifié.").Send(); err != nil { + utils.SendAlert("commands/config.go - Sending success", err.Error()) + } + case XpRoleDel: + err := resp.IsEphemeral(). + SetMessage("Rôle à supprimer"). + AddComponent(discordgo.ActionsRow{Components: []discordgo.MessageComponent{discordgo.SelectMenu{ + MenuType: discordgo.RoleSelectMenu, + CustomID: XpRoleDelRole, + }}}). + Send() + if err != nil { + utils.SendAlert("config/guild.go - Sending response to del", err.Error()) + } + case XpRoleDelRole: + roleId := msgData.Values[0] + _, r := cfg.FindXpRole(roleId) + if r == nil { + err := resp.SetMessage("Le rôle n'a pas été trouvé dans la config.").Send() + if err != nil { + utils.SendAlert("commands/config.go - Role not found (del)", err.Error()) + } + return + } + err := gokord.DB.Delete(r).Error + if err != nil { + utils.SendAlert( + "commands/config.go - Deleting entry", + err.Error(), + "guild_id", i.GuildID, + "role_id", roleId, + "type", "del", + ) + } + if err = resp.IsEphemeral().SetMessage("Rôle supprimé.").Send(); err != nil { + utils.SendAlert("commands/config.go - Sending success", err.Error()) + } default: - err = resp.SetMessage("Le type d'action n'est pas valide.").Send() + err := resp.SetMessage("Le type d'action n'est pas valide.").Send() if err != nil { utils.SendAlert("commands/config.go - Invalid action type", err.Error()) } return } - if err != nil { - err = resp.SetMessage("Il y a eu une erreur lors de la modification de de la base de données.").Send() - } else { - err = resp.SetMessage("La configuration a bien été mise à jour.").Send() +} + +func ConfigXPModal(s *discordgo.Session, i *discordgo.InteractionCreate) { + if i.Type != discordgo.InteractionModalSubmit { + return } - if err != nil { - utils.SendAlert("commands/config.go - Config updated message", err.Error()) + resp := utils.NewResponseBuilder(s, i) + + modalData := i.ModalSubmitData() + + if modalData.CustomID != XpRoleAddLevel && modalData.CustomID != XpRoleEditLevel { + return } + + input := modalData.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput) + + k := getKeyConfigRole(i) + in, err := strconv.Atoi(input.Value) + if err != nil || in < 0 { + if err = resp.IsEphemeral(). + SetMessage("Impossible de lire le nombre. Il doit s'agit d'un nombre entier positif."). + Send(); err != nil { + utils.SendAlert("command/config.go - Sending bad number", err.Error()) + } + return + } + configModifyMap[k] = uint(in) + go func(i *discordgo.InteractionCreate, k string) { + time.Sleep(5 * time.Minute) + delete(configModifyMap, k) + }(i, k) + + cID := XpRoleAddRole + resp.SetMessage("Rôle à ajouter") + if modalData.CustomID == XpRoleEditLevel { + cID = XpRoleEditLevel + resp.SetMessage("Rôle à modifier") + } + + err = resp.IsEphemeral(). + SetMessage("Rôle à supprimer"). + AddComponent(discordgo.ActionsRow{Components: []discordgo.MessageComponent{discordgo.SelectMenu{ + MenuType: discordgo.RoleSelectMenu, + CustomID: cID, + }}}). + Send() + if err != nil { + utils.SendAlert("config/guild.go - Sending response to add/edit", err.Error()) + } +} + +func getKeyConfigRole(i *discordgo.InteractionCreate) string { + return fmt.Sprintf("r:%s:%s", i.GuildID, i.User.ID) } func ConfigChannel(s *discordgo.Session, i *discordgo.InteractionCreate, optMap utils.OptionMap, resp *utils.ResponseBuilder) { diff --git a/go.mod b/go.mod index 16d6af9..0c5e711 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,12 @@ module github.com/anhgelus/les-copaings-bot go 1.24 require ( - github.com/anhgelus/gokord v0.10.0 + github.com/anhgelus/gokord v0.10.3 github.com/bwmarrin/discordgo v0.29.0 + github.com/joho/godotenv v1.5.1 github.com/pelletier/go-toml/v2 v2.2.4 gorm.io/driver/postgres v1.5.11 - gorm.io/gorm v1.30.0 + gorm.io/gorm v1.30.1 ) require ( @@ -16,11 +17,10 @@ require ( github.com/gorilla/websocket v1.5.3 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.7.4 // indirect + github.com/jackc/pgx/v5 v5.7.5 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/joho/godotenv v1.5.1 // indirect github.com/redis/go-redis/v9 v9.9.0 // indirect golang.org/x/crypto v0.38.0 // indirect golang.org/x/sync v0.14.0 // indirect diff --git a/go.sum b/go.sum index 0b8314f..3157ad4 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/anhgelus/gokord v0.9.0 h1:vz7jHZ6papdt/xehe+nx4DxOLquPO6QukW8UzH81bGY github.com/anhgelus/gokord v0.9.0/go.mod h1:NSepHjTV61LUnuyGgHxEhZNMnWREErGFyOtRYPgdx/E= github.com/anhgelus/gokord v0.10.0 h1:FaaMWntaezmSCvarcSMjfWr5OXVVwwzlDMnNX8gXaWE= github.com/anhgelus/gokord v0.10.0/go.mod h1:NSepHjTV61LUnuyGgHxEhZNMnWREErGFyOtRYPgdx/E= +github.com/anhgelus/gokord v0.10.3 h1:4uKHRXFsRg1wRJQ3Sikz1MpL68cUZxyseRD+5hVe7tE= +github.com/anhgelus/gokord v0.10.3/go.mod h1:NSepHjTV61LUnuyGgHxEhZNMnWREErGFyOtRYPgdx/E= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -28,6 +30,8 @@ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7Ulw github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg= github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= +github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= +github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -73,3 +77,5 @@ gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw= gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= +gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4= +gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= diff --git a/main.go b/main.go index b2def4f..1047d16 100644 --- a/main.go +++ b/main.go @@ -141,4 +141,5 @@ func afterInit(dg *discordgo.Session) { //interaction: /config dg.AddHandler(commands.ConfigXP) + dg.AddHandler(commands.ConfigXPModal) }