commands+db: Implement level recalculation
parent
24a3887288
commit
4f687f4d56
@ -0,0 +1,49 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
|
||||
"gitea.teamortix.com/chanbakjsd/Milen/level"
|
||||
"gitea.teamortix.com/chanbakjsd/Milen/util"
|
||||
)
|
||||
|
||||
func handleRecalculateLevel(dg *discordgo.Session, m *discordgo.MessageCreate, arguments []string) {
|
||||
if len(arguments) == 0 {
|
||||
util.SendFailEmbed(
|
||||
dg, m.ChannelID, "Bot Owner Access Required",
|
||||
"⚠️ This action might take a while and disable level calculation system.\nTo confirm, check console for launch code.",
|
||||
)
|
||||
fmt.Println("Level launch requested: " + calculationCode)
|
||||
return
|
||||
}
|
||||
if arguments[0] != calculationCode {
|
||||
util.SendFailEmbed(
|
||||
dg, m.ChannelID, "Incorrect Launch Code", "You entered an incorrect code.",
|
||||
)
|
||||
}
|
||||
util.SendSuccessEmbed(dg, m.ChannelID, "Level is being recalculated.")
|
||||
level.RecalculateEverything(dg, m.GuildID)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
calculationCode = randomBase64(20)
|
||||
}
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+="
|
||||
|
||||
var calculationCode string
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
calculationCode = randomBase64(20)
|
||||
}
|
||||
|
||||
func randomBase64(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type PlayerLevel struct {
|
||||
UserID string `gorm:"primary_key"`
|
||||
LastActive time.Time
|
||||
XP int64
|
||||
}
|
||||
|
||||
func IncrementXP(userID string, value int64) {
|
||||
db.Where(&PlayerLevel{UserID: userID}).
|
||||
UpdateColumn("xp", gorm.Expr("xp + ?", value)).
|
||||
UpdateColumn("last_active", time.Now())
|
||||
}
|
||||
|
||||
func GetLastActive(userID string) time.Time {
|
||||
result := PlayerLevel{
|
||||
UserID: userID,
|
||||
}
|
||||
db.Where(&result).First(&result)
|
||||
return result.LastActive
|
||||
}
|
||||
|
||||
func DeleteAllLevel() {
|
||||
db.Delete(&PlayerLevel{})
|
||||
}
|
||||
|
||||
func SetXP(userID string, lastActive time.Time, xp int64) {
|
||||
db.Create(&PlayerLevel{
|
||||
UserID: userID,
|
||||
LastActive: lastActive,
|
||||
XP: xp,
|
||||
})
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package db
|
||||
|
||||
type ReactRole struct {
|
||||
MessageID string
|
||||
EmojiID string
|
||||
RoleID string
|
||||
}
|
||||
|
||||
func CreateReactRole(messageID, emojiID, roleID string) {
|
||||
db.Create(&ReactRole{
|
||||
MessageID: messageID,
|
||||
EmojiID: emojiID,
|
||||
RoleID: roleID,
|
||||
})
|
||||
}
|
||||
|
||||
func GetReactRole(messageID, emojiID string) string {
|
||||
result := ReactRole{
|
||||
MessageID: messageID,
|
||||
EmojiID: emojiID,
|
||||
}
|
||||
db.Where(&result).First(&result)
|
||||
return result.RoleID
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package level
|
||||
|
||||
import (
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
var ShouldListen = true
|
||||
|
||||
func Event(dg *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
if m.Author.Bot || ShouldListen {
|
||||
return
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package level
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
|
||||
"gitea.teamortix.com/chanbakjsd/Milen/db"
|
||||
"gitea.teamortix.com/chanbakjsd/Milen/util"
|
||||
)
|
||||
|
||||
func RecalculateEverything(dg *discordgo.Session, guildID string) {
|
||||
ShouldListen = false
|
||||
defer func() {
|
||||
ShouldListen = true
|
||||
}()
|
||||
|
||||
startTime := time.Now()
|
||||
guild, err := dg.Guild(guildID)
|
||||
if err != nil {
|
||||
util.ReportError(dg, err)
|
||||
return
|
||||
}
|
||||
listOfMessages := make(map[string][]*discordgo.Message)
|
||||
for _, v := range guild.Channels {
|
||||
beforeID := ""
|
||||
for {
|
||||
messages, err := dg.ChannelMessages(v.ID, 100, beforeID, "", "")
|
||||
if err != nil {
|
||||
util.ReportError(dg, err)
|
||||
return
|
||||
}
|
||||
for _, msg := range messages {
|
||||
if list, ok := listOfMessages[msg.Author.ID]; ok {
|
||||
listOfMessages[msg.Author.ID] = append(list, msg)
|
||||
} else {
|
||||
listOfMessages[msg.Author.ID] = []*discordgo.Message{msg}
|
||||
}
|
||||
}
|
||||
if len(messages) < 100 {
|
||||
break
|
||||
}
|
||||
beforeID = messages[99].ID
|
||||
}
|
||||
}
|
||||
fetchedTime := time.Now()
|
||||
totalXP := make(map[string]int64)
|
||||
for k, v := range listOfMessages {
|
||||
sort.Slice(v, func(i, j int) bool {
|
||||
return v[i].ID < v[j].ID
|
||||
})
|
||||
prevTime, err := discordgo.SnowflakeTimestamp(v[0].ID)
|
||||
if err != nil {
|
||||
util.ReportError(dg, err)
|
||||
return
|
||||
}
|
||||
for i := 1; i < len(v); i++ {
|
||||
nextTime, err := discordgo.SnowflakeTimestamp(v[i].ID)
|
||||
if err != nil {
|
||||
util.ReportError(dg, err)
|
||||
return
|
||||
}
|
||||
xp := int64(nextTime.Sub(prevTime).Seconds())
|
||||
if xp > int64(len(v[i].Content)-3)/3 {
|
||||
xp = int64(len(v[i].Content)-3) / 3
|
||||
}
|
||||
if xp > 10 {
|
||||
xp = 10
|
||||
}
|
||||
if xp >= 0 {
|
||||
totalXP[k] += xp
|
||||
}
|
||||
prevTime = nextTime
|
||||
}
|
||||
}
|
||||
|
||||
processTime := time.Now()
|
||||
db.DeleteAllLevel()
|
||||
for k, v := range totalXP {
|
||||
userHistory := listOfMessages[k]
|
||||
newestMessage := userHistory[len(userHistory)-1]
|
||||
time, err := discordgo.SnowflakeTimestamp(newestMessage.ID)
|
||||
if err != nil {
|
||||
util.ReportError(dg, err)
|
||||
return
|
||||
}
|
||||
db.SetXP(k, time, v)
|
||||
}
|
||||
|
||||
finishTime := time.Now()
|
||||
|
||||
fmt.Printf("[RECALC] Fetch took %v.\n", fetchedTime.Sub(startTime))
|
||||
fmt.Printf("[RECALC] XP calculation took %v.\n", processTime.Sub(fetchedTime))
|
||||
fmt.Printf("[RECALC] DB write took %v.\n", finishTime.Sub(processTime))
|
||||
fmt.Printf("[RECALC] Total took %v.\n", finishTime.Sub(startTime))
|
||||
}
|
Loading…
Reference in New Issue