1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package main
import (
"context"
"fmt"
"strings"
"time"
"git.anhgelus.world/anhgelus/les-copaings-bot/config"
"git.anhgelus.world/anhgelus/les-copaings-bot/exp"
"git.anhgelus.world/anhgelus/les-copaings-bot/user"
"github.com/nyttikord/gokord/bot"
"github.com/nyttikord/gokord/channel"
"github.com/nyttikord/gokord/event"
)
const (
NotConnected = -1
MaxTimeInVocal = 60 * 60 * 6
MaxXpPerMessage = 250
)
var (
connectedSince = map[string]int64{}
)
func OnMessage(ctx context.Context, dg bot.Session, m *event.MessageCreate) {
if m.Author.Bot {
return
}
cfg := config.GetGuild(ctx, m.GuildID)
if cfg.IsDisabled(ctx, dg, m.ChannelID) {
return
}
cc := user.GetCopaing(ctx, m.Author.ID, m.GuildID)
// add exp
trimmed := exp.TrimMessage(strings.ToLower(m.Content))
m.Member.User = m.Author
m.Member.GuildID = m.GuildID
xp := min(exp.MessageXP(uint(len(trimmed)), exp.CalcDiversity(trimmed)), MaxXpPerMessage)
cc.AddXP(ctx, dg, m.Member, xp, func(_ uint, _ uint) {
if err := channel.AddReaction(m.ChannelID, m.Message.ID, "⬆").Do(ctx); err != nil {
bot.Logger(ctx).Error(
"add reaction for new level",
"error", err, "channel", m.ChannelID, "message", m.Message.ID,
)
}
})
}
func OnVoiceUpdate(ctx context.Context, dg bot.Session, e *event.VoiceStateUpdate) {
if e.Member.User.Bot {
return
}
cfg := config.GetGuild(ctx, e.GuildID)
dis := cfg.IsDisabled(ctx, dg, e.BeforeUpdate.ChannelID)
if (e.BeforeUpdate == nil || dis) && e.ChannelID != 0 {
if dis {
return
}
onConnection(ctx, dg, e)
} else if e.BeforeUpdate != nil && (e.ChannelID == 0 || dis) {
if dis {
return
}
onDisconnect(ctx, dg, e)
}
}
func genMapKey(guildID, userID uint64) string {
return fmt.Sprintf("%d:%d", guildID, userID)
}
func onConnection(ctx context.Context, _ bot.Session, e *event.VoiceStateUpdate) {
bot.Logger(ctx).Debug("user connected", "user", e.Member.DisplayName())
connectedSince[genMapKey(e.GuildID, e.UserID)] = time.Now().Unix()
}
func onDisconnect(ctx context.Context, dg bot.Session, e *event.VoiceStateUpdate) {
now := time.Now().Unix()
cc := user.GetCopaing(ctx, e.UserID, e.GuildID)
// check the validity of user
con, ok := connectedSince[genMapKey(e.GuildID, e.UserID)]
if !ok || con == NotConnected {
bot.Logger(ctx).Warn(
"user disconnect from a vocal but was registered as not connected",
"user", e.Member.DisplayName(),
)
return
}
timeInVocal := now - con
bot.Logger(ctx).Debug("user disconnected", "user", e.Member.DisplayName(), "time in vocal", timeInVocal)
connectedSince[genMapKey(e.GuildID, e.UserID)] = NotConnected
// add exp
if timeInVocal < 0 {
bot.Logger(ctx).Warn("time spent in vocal is negative", "user", e.Member.DisplayName(), "guild", e.GuildID)
return
}
timeInVocal = min(timeInVocal, MaxTimeInVocal)
e.Member.GuildID = e.GuildID
cc.AddXP(ctx, dg, e.Member, exp.VocalXP(uint(timeInVocal)), func(_ uint, newLevel uint) {
cfg := config.GetGuild(ctx, e.GuildID)
if cfg.FallbackChannel == 0 {
return
}
_, err := channel.SendMessage(cfg.FallbackChannel, fmt.Sprintf(
"%s est maintenant niveau %d", e.Member.Mention(), newLevel,
)).Do(ctx)
if err != nil {
bot.Logger(ctx).Error("sending new level in fallback channel", "error", err)
}
})
}
func OnLeave(ctx context.Context, dg bot.Session, e *event.GuildMemberRemove) {
bot.Logger(ctx).Debug("leave event", "user", e.User.Username)
if e.User.Bot {
return
}
c := user.GetCopaing(ctx, e.User.ID, e.GuildID)
if err := c.Delete(ctx); err != nil {
bot.Logger(ctx).Error("deleting user", "user", e.User.Username, "guild", e.GuildID)
}
}
|