diff options
Diffstat (limited to 'events.go')
| -rw-r--r-- | events.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/events.go b/events.go new file mode 100644 index 0000000..54c444e --- /dev/null +++ b/events.go @@ -0,0 +1,162 @@ +package main + +import ( + "context" + "errors" + "fmt" + "github.com/anhgelus/gokord/utils" + "github.com/anhgelus/les-copaings-bot/config" + "github.com/anhgelus/les-copaings-bot/exp" + "github.com/anhgelus/les-copaings-bot/user" + "github.com/bwmarrin/discordgo" + "github.com/redis/go-redis/v9" + "strconv" + "strings" + "time" +) + +const ( + ConnectedSince = "connected_since" + NotConnected = -1 + MaxTimeInVocal = 60 * 60 * 6 + MaxXpPerMessage = 250 +) + +func OnMessage(s *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.Bot { + return + } + cfg := config.GetGuildConfig(m.GuildID) + if cfg.IsDisabled(m.ChannelID) { + return + } + c := user.GetCopaing(m.Author.ID, m.GuildID) + // add exp + trimmed := utils.TrimMessage(strings.ToLower(m.Content)) + m.Member.User = m.Author + m.Member.GuildID = m.GuildID + xp := exp.MessageXP(uint(len(trimmed)), exp.CalcDiversity(trimmed)) + if xp > MaxXpPerMessage { + xp = MaxXpPerMessage + } + c.AddXP(s, m.Member, xp, func(_ uint, _ uint) { + if err := s.MessageReactionAdd(m.ChannelID, m.Message.ID, "⬆"); err != nil { + utils.SendAlert( + "events.go - add reaction for new level", err.Error(), + "channel id", m.ChannelID, + "message id", m.Message.ID, + ) + } + }) +} + +func OnVoiceUpdate(s *discordgo.Session, e *discordgo.VoiceStateUpdate) { + if e.Member.User.Bot { + return + } + cfg := config.GetGuildConfig(e.GuildID) + client, err := config.GetRedisClient() + if err != nil { + utils.SendAlert("events.go - Getting redis client", err.Error()) + return + } + if e.BeforeUpdate == nil && e.ChannelID != "" { + if cfg.IsDisabled(e.ChannelID) { + return + } + onConnection(s, e, client) + } else if e.BeforeUpdate != nil && e.ChannelID == "" { + if cfg.IsDisabled(e.BeforeUpdate.ChannelID) { + return + } + onDisconnect(s, e, client) + } +} + +func onConnection(_ *discordgo.Session, e *discordgo.VoiceStateUpdate, client *redis.Client) { + utils.SendDebug("User connected", "username", e.Member.DisplayName()) + c := user.GetCopaing(e.UserID, e.GuildID) + err := client.Set( + context.Background(), + c.GenKey(ConnectedSince), + strconv.FormatInt(time.Now().Unix(), 10), + 0, + ).Err() + if err != nil { + utils.SendAlert("events.go - Setting connected_since", err.Error()) + } +} + +func onDisconnect(s *discordgo.Session, e *discordgo.VoiceStateUpdate, client *redis.Client) { + now := time.Now().Unix() + c := user.GetCopaing(e.UserID, e.GuildID) + key := c.GenKey(ConnectedSince) + res := client.Get(context.Background(), key) + // check validity of user (1) + if errors.Is(res.Err(), redis.Nil) { + utils.SendWarn(fmt.Sprintf( + "User %s diconnect from a vocal but does not have a connected_since", e.Member.DisplayName(), + )) + return + } + if res.Err() != nil { + utils.SendAlert("events.go - Getting connected_since", res.Err().Error()) + err := client.Set(context.Background(), key, strconv.Itoa(NotConnected), 0).Err() + if err != nil { + utils.SendAlert("events.go - Set connected_since to not connected after get err", err.Error()) + } + return + } + con, err := res.Int64() + if err != nil { + utils.SendAlert("events.go - Converting result to int64", err.Error()) + return + } + // check validity of user (2) + if con == NotConnected { + utils.SendWarn(fmt.Sprintf( + "User %s diconnect from a vocal but was registered as not connected", e.Member.DisplayName(), + )) + return + } + utils.SendDebug("User disconnected", "username", e.Member.DisplayName(), "since", con) + err = client.Set(context.Background(), key, strconv.Itoa(NotConnected), 0).Err() + if err != nil { + utils.SendAlert("events.go - Set connected_since to not connected", err.Error()) + } + // add exp + timeInVocal := now - con + if timeInVocal < 0 { + utils.SendAlert("events.go - Calculating time spent in vocal", "the time is negative") + return + } + if timeInVocal > MaxTimeInVocal { + utils.SendWarn(fmt.Sprintf("User %s spent more than 6 hours in vocal", e.Member.DisplayName())) + timeInVocal = MaxTimeInVocal + } + e.Member.GuildID = e.GuildID + c.AddXP(s, e.Member, exp.VocalXP(uint(timeInVocal)), func(_ uint, newLevel uint) { + cfg := config.GetGuildConfig(e.GuildID) + _, err = s.ChannelMessageSend(cfg.FallbackChannel, fmt.Sprintf( + "%s est maintenant niveau %d", e.Member.Mention(), newLevel, + )) + if err != nil { + utils.SendAlert("events.go - Sending new level in fallback channel", err.Error()) + } + }) +} + +func OnLeave(_ *discordgo.Session, e *discordgo.GuildMemberRemove) { + utils.SendDebug("Leave event", "user_id", e.User.ID) + if e.User.Bot { + return + } + c := user.GetCopaing(e.User.ID, e.GuildID) + if err := c.Delete(); err != nil { + utils.SendAlert( + "events.go - deleting user from db", err.Error(), + "user_id", e.User.ID, + "guild_id", e.GuildID, + ) + } +} |
