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