diff --git a/commands/config.go b/commands/config.go new file mode 100644 index 0000000..51180c4 --- /dev/null +++ b/commands/config.go @@ -0,0 +1,136 @@ +package commands + +import ( + "fmt" + "github.com/anhgelus/gokord/utils" + "github.com/anhgelus/les-copaings-bot/config" + "github.com/anhgelus/les-copaings-bot/xp" + "github.com/bwmarrin/discordgo" +) + +func Config(s *discordgo.Session, i *discordgo.InteractionCreate) { + resp := utils.ResponseBuilder{C: s, I: i} + err := resp.Message("Merci d'utiliser les sous-commandes.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Sending please use subcommand", err.Error()) + } +} + +func ConfigShow(s *discordgo.Session, i *discordgo.InteractionCreate) { + cfg := config.GetGuildConfig(i.GuildID) + resp := utils.ResponseBuilder{C: s, I: i} + roles := "" + l := len(cfg.XpRoles) - 1 + for i, r := range cfg.XpRoles { + if i == l { + roles += fmt.Sprintf("> **%d** - <@&%s>", xp.Level(r.XP), r.RoleID) + } else { + roles += fmt.Sprintf("> **%d** - <@&%s>\n", xp.Level(r.XP), r.RoleID) + } + } + err := resp.Embeds([]*discordgo.MessageEmbed{ + { + Type: discordgo.EmbedTypeRich, + Title: "Config", + Description: "Configuration", + Color: utils.Success, + Fields: []*discordgo.MessageEmbedField{ + { + Name: "Rôles liés aux niveaux", + Value: roles, + Inline: false, + }, + }, + }, + }).Send() + if err != nil { + utils.SendAlert("config/guild.go - Sending config", err.Error()) + } +} + +func ConfigXP(s *discordgo.Session, i *discordgo.InteractionCreate) { + optMap := utils.GenerateOptionMapForSubcommand(i) + for k, v := range optMap { + utils.SendSuccess("option map", "key", k, "value", v) + } + resp := utils.ResponseBuilder{C: s, I: i} + // verify every args + t, ok := optMap["type"] + if !ok { + err := resp.Message("Le type d'action n'a pas été renseigné.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Action type not set", err.Error()) + } + return + } + ts := t.StringValue() + lvl, ok := optMap["level"] + if !ok { + err := resp.Message("Le niveau n'a pas été renseigné.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Level not set", err.Error()) + } + return + } + level := lvl.IntValue() + if level < 1 { + err := resp.Message("Le niveau doit forcément être supérieur à 0.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Invalid level", err.Error()) + } + return + } + exp := xp.XPForLevel(uint(level)) + r, ok := optMap["role"] + if !ok { + err := resp.Message("Le role n'a pas été renseigné.").IsEphemeral().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 + switch ts { + case "add": + cfg.XpRoles = append(cfg.XpRoles, config.XpRole{ + XP: exp, + RoleID: role.ID, + }) + case "del": + pos, r := cfg.FindXpRole(exp, role.ID) + if r == nil { + err := resp.Message("Le role n'a pas été trouvé dans la config.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Role not found (del)", err.Error()) + } + return + } + cfg.XpRoles = append(cfg.XpRoles[:pos], cfg.XpRoles[pos+1:]...) + case "edit": + pos, r := cfg.FindXpRole(exp, role.ID) + if r == nil { + err := resp.Message("Le role n'a pas été trouvé dans la config.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Role not found (edit)", err.Error()) + } + return + } + r.RoleID = role.ID + cfg.XpRoles[pos] = *r + default: + err := resp.Message("Le type d'action n'est pas valide.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Invalid action type", err.Error()) + } + return + } + // save + cfg.Save() + err := resp.Message("La configuration a bien été mise à jour.").IsEphemeral().Send() + if err != nil { + utils.SendAlert("commands/config.go - Config updated", err.Error()) + } +} diff --git a/config/guild.go b/config/guild.go new file mode 100644 index 0000000..ddeb300 --- /dev/null +++ b/config/guild.go @@ -0,0 +1,42 @@ +package config + +import ( + "github.com/anhgelus/gokord" + "gorm.io/gorm" +) + +type GuildConfig struct { + gorm.Model + GuildID string `gorm:"not null"` + XpRoles []XpRole +} + +type XpRole struct { + gorm.Model + XP uint + RoleID string + GuildConfigID uint +} + +func GetGuildConfig(guildID string) *GuildConfig { + cfg := GuildConfig{GuildID: guildID} + return cfg.Load() +} + +func (cfg *GuildConfig) Load() *GuildConfig { + gokord.DB.Where("guild_id = ?", cfg.GuildID).Preload("XpRoles").FirstOrCreate(cfg) + return cfg +} + +func (cfg *GuildConfig) Save() { + gokord.DB.Save(cfg) +} + +func (cfg *GuildConfig) FindXpRole(xp uint, roleID string) (int, *XpRole) { + for i, r := range cfg.XpRoles { + if r.XP == xp && r.RoleID == roleID { + return i, &r + } + } + return 0, nil +} diff --git a/go.mod b/go.mod index aaf4054..fab5864 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/anhgelus/les-copaings-bot go 1.22 -require github.com/anhgelus/gokord v0.1.5 +require github.com/anhgelus/gokord v0.2.0 require ( github.com/bwmarrin/discordgo v0.28.1 // indirect diff --git a/go.sum b/go.sum index 0725808..2a43c00 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,18 @@ github.com/anhgelus/gokord v0.1.4 h1:hoe87eCcf+Y22WDKwesQuyvxna4SWXrjpYNpdwH8pbI github.com/anhgelus/gokord v0.1.4/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= github.com/anhgelus/gokord v0.1.5 h1:yFFKK6B1hCZU3mvoLAW2nZnjTkXJv7J7uqi/bWMuJbA= github.com/anhgelus/gokord v0.1.5/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.1.6-0.20240415111450-5f4b048c7253 h1:XDES1W0OLHQMyU3+wNv96FjivpUXoi1s2+UEZjG7y14= +github.com/anhgelus/gokord v0.1.6-0.20240415111450-5f4b048c7253/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.1.6-0.20240415112117-6f6a99167c29 h1:ZpcDTpx0obVleuXAGj/PqjlFUUTo+MKMLMP0CngcDTU= +github.com/anhgelus/gokord v0.1.6-0.20240415112117-6f6a99167c29/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.1.6-0.20240415112732-e29b97ef3a65 h1:/Ho6Q18UwMNTIENOmsu0e64nZEB96xc9fSD/A55laEA= +github.com/anhgelus/gokord v0.1.6-0.20240415112732-e29b97ef3a65/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.1.6-0.20240415112938-8cc98f5fc515 h1:2ZGhq4WgtIdd8wPOk2K8QLSOlxi2ojduGaJ/yxm5+Mw= +github.com/anhgelus/gokord v0.1.6-0.20240415112938-8cc98f5fc515/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.1.6 h1:bBfiYc9BUpAHbE1VPqjJbRZtgVJryMe8KjJRfQ2aLqo= +github.com/anhgelus/gokord v0.1.6/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= +github.com/anhgelus/gokord v0.2.0 h1:/bVOE/We9scbD5KN3QKrqG7oxQ3R8KD4n7+i7vwfv6o= +github.com/anhgelus/gokord v0.2.0/go.mod h1:CRyk26IhIZ/0Mkc5/5WOU8C08mGCOqzKzR6eDFfPisI= 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= diff --git a/main.go b/main.go index caede84..adc2e1c 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "flag" "github.com/anhgelus/gokord" "github.com/anhgelus/les-copaings-bot/commands" + "github.com/anhgelus/les-copaings-bot/config" "github.com/anhgelus/les-copaings-bot/xp" "github.com/bwmarrin/discordgo" ) @@ -21,20 +22,50 @@ func main() { panic(err) } - err = gokord.DB.AutoMigrate(&xp.Copaing{}) + err = gokord.DB.AutoMigrate(&xp.Copaing{}, &config.GuildConfig{}, &config.XpRole{}) if err != nil { panic(err) } - rankCmd := gokord.NewCommand("rank", "Affiche le niveau d'une personne"). + rankCmd := gokord.NewCommand("rank", "Affiche le niveau d'un copaing"). HasOption(). AddOption(gokord.NewOption( discordgo.ApplicationCommandOptionUser, "copaing", "Le niveau du Copaing que vous souhaitez obtenir", )). - SetHandler(commands.Rank). - ToCmd() + SetHandler(commands.Rank) + + configCmd := gokord.NewCommand("config", "Modifie la config"). + ContainsSub(). + AddSub( + gokord.NewCommand("show", "Affiche la config").SetHandler(commands.ConfigShow), + ). + AddSub( + gokord.NewCommand("xp", "Modifie l'xp"). + HasOption(). + AddOption(gokord.NewOption( + discordgo.ApplicationCommandOptionString, + "type", + "Type d'action à effectuer", + ). + AddChoice(gokord.NewChoice("Ajouter", "add")). + AddChoice(gokord.NewChoice("Supprimer", "del")). + AddChoice(gokord.NewChoice("Modifier", "edit")).IsRequired(), + ). + AddOption(gokord.NewOption( + discordgo.ApplicationCommandOptionInteger, + "level", + "Niveau du rôle", + ).IsRequired()). + AddOption(gokord.NewOption( + discordgo.ApplicationCommandOptionRole, + "role", + "Rôle", + ).IsRequired()). + SetHandler(commands.ConfigXP), + ). + SetHandler(commands.Config) bot := gokord.Bot{ Token: token, @@ -45,8 +76,9 @@ func main() { Url: "", }, }, - Commands: []*gokord.Cmd{ + Commands: []*gokord.GeneralCommand{ rankCmd, + configCmd, }, AfterInit: afterInit, } diff --git a/xp/events.go b/xp/events.go index f6b9bc5..3ce4f06 100644 --- a/xp/events.go +++ b/xp/events.go @@ -21,8 +21,7 @@ const ( ) func OnMessage(s *discordgo.Session, m *discordgo.MessageCreate) { - c := Copaing{DiscordID: m.Author.ID, GuildID: m.GuildID} - c.Load() + c := GetCopaing(m.Author.ID, m.GuildID) // add xp trimmed := utils.TrimMessage(strings.ToLower(m.Content)) c.AddXP(s, XPMessage(uint(len(trimmed)), calcDiversity(trimmed)), func(_ uint, _ uint) { @@ -119,8 +118,7 @@ func onDisconnect(s *discordgo.Session, e *discordgo.VoiceStateUpdate, client *r utils.SendWarn(fmt.Sprintf("User %s spent more than 6 hours in vocal", e.Member.DisplayName())) timeInVocal = MaxTimeInVocal } - c := Copaing{DiscordID: u.DiscordID, GuildID: u.GuildID} - c.Load() + c := GetCopaing(u.DiscordID, u.GuildID) c.AddXP(s, XPVocal(uint(timeInVocal)), func(_ uint, _ uint) { //TODO: handle new level in vocal }) diff --git a/xp/member.go b/xp/member.go index 578e533..280b9e0 100644 --- a/xp/member.go +++ b/xp/member.go @@ -10,13 +10,18 @@ import ( type Copaing struct { gorm.Model - DiscordID string - XP uint - GuildID string + DiscordID string `gorm:"not null"` + XP uint `gorm:"default:0"` + GuildID string `gorm:"not null"` } var r *redis.Client +func GetCopaing(discordID string, guildID string) *Copaing { + c := Copaing{DiscordID: discordID, GuildID: guildID} + return c.Load() +} + func (c *Copaing) Load() *Copaing { gokord.DB.Where("discord_id = ? and guild_id = ?", c.DiscordID, c.GuildID).FirstOrCreate(c) return c