From fd8ad961b27c84876195a1b3ba70323ea968ef08 Mon Sep 17 00:00:00 2001 From: Luther Wen Xu Date: Tue, 19 Nov 2019 14:59:32 +0800 Subject: [PATCH] prestige: Implement prestige command --- db.go | 1 + messageCreate.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ prestige.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++ xp.go | 13 +++++++--- 4 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 prestige.go diff --git a/db.go b/db.go index f19beae..5f52d0f 100644 --- a/db.go +++ b/db.go @@ -17,4 +17,5 @@ func init() { db.SetMaxOpenConns(1) db.Exec("CREATE TABLE xp(id STRING NOT NULL UNIQUE, xp INTEGER NOT NULL)") db.Exec("CREATE TABLE shard(id STRING NOT NULL UNIQUE, shard INTEGER NOT NULL)") + db.Exec("CREATE TABLE prestige(id STRING NOT NULL UNIQUE, multiplier INTEGER NOT NULL)") } diff --git a/messageCreate.go b/messageCreate.go index 71e330b..641b39d 100644 --- a/messageCreate.go +++ b/messageCreate.go @@ -2,11 +2,16 @@ package main import ( "fmt" + "math" + "time" "github.com/bwmarrin/discordgo" ) const generalChannelID = "645550570001924098" +const emojiCheck = "✅" + +var prestigeList = make(map[string]string) func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Author.Bot { @@ -20,6 +25,9 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Content == "pgqshard" { handleShardRequest(s, m) } + if m.Content == "pgqprestige" { + handlePrestigeRequest(s, m) + } } func handleXPRequest(s *discordgo.Session, m *discordgo.MessageCreate) { @@ -47,3 +55,61 @@ func handleShardRequest(s *discordgo.Session, m *discordgo.MessageCreate) { ), ) } + +func handlePrestigeRequest(s *discordgo.Session, m *discordgo.MessageCreate) { + currentPrestigeLevel := getPrestige(s, m.Author.ID) + xp := getXP(s, m.Author.ID) + newPrestigeLevel := xp/130000 + 1 + + if xp < levelUpRequirementCache[4] && currentPrestigeLevel == 1 { + s.ChannelMessageSend(m.ChannelID, "**PRESTIGE > **Prestige is only unlocked after level 5!") + return + } + + var lowerLevelWarning string + if newPrestigeLevel <= currentPrestigeLevel { + lowerLevelWarning = "**WARNING: Your new prestige multiplier is NOT higher than your current prestige multiplier." + } + nearestPowerOfTen := math.Pow10(int(math.Floor(math.Log10(float64(newPrestigeLevel))))) + nextNearestLogicalPrestige := int((math.Floor(float64(newPrestigeLevel)/nearestPowerOfTen) + 1) * nearestPowerOfTen) + + msg, err := s.ChannelMessageSend( + m.ChannelID, + fmt.Sprintf( + "<@%s>, here's your prestige multiplier:\n**Now: **__%dx__\n**New: **__%dx__\n**Next: **__%dx__ [%.1f%%]\n%s\n"+ + "React with :white_check_mark: to proceed with prestiging.", + m.Author.ID, + currentPrestigeLevel, + newPrestigeLevel, + nextNearestLogicalPrestige, float64(xp)/float64(130000*(nextNearestLogicalPrestige-1))*100, + lowerLevelWarning, + ), + ) + if err != nil { + logError(s, "handlePrestigeRequest", "send", err) + return + } + prestigeList[msg.ID] = m.Author.ID + err = s.MessageReactionAdd(msg.ChannelID, msg.ID, emojiCheck) + if err != nil { + logError(s, "handlePrestigeRequest", "addReaction", err) + return + } + go func() { + time.Sleep(15 * time.Second) + err = s.MessageReactionsRemoveAll(msg.ChannelID, msg.ID) + if err != nil { + logError(s, "handlePrestigeRequest", "removeReaction", err) + } + }() +} + +func checkPrestigeReact(s *discordgo.Session, m *discordgo.MessageReactionAdd) { + if prestigeList[m.MessageID] != m.UserID { + return + } + xp := getXP(s, m.UserID) + newPrestigeLevel := xp/130000 + 1 + setPrestige(s, m.UserID, newPrestigeLevel) + s.ChannelMessageSend(m.ChannelID, "**PRESTIGE > ** <@%s>, you have prestiged!") +} diff --git a/prestige.go b/prestige.go new file mode 100644 index 0000000..ed916eb --- /dev/null +++ b/prestige.go @@ -0,0 +1,64 @@ +package main + +import ( + "sync" + + "github.com/bwmarrin/discordgo" +) + +var prestigeCache = make(map[string]int) +var prestigeMutex = sync.Mutex{} + +func setPrestige(dg *discordgo.Session, discordID string, newMultiplier int) { + prestigeMutex.Lock() + defer prestigeMutex.Unlock() + + tx, err := db.Begin() + if err != nil { + logError(dg, "setPrestige", "begin", discordID, newMultiplier, err) + return + } + _, err = tx.Exec("REPLACE INTO prestige(id, multiplier) VALUES(?,?)", discordID, newMultiplier) + if err != nil { + logError(dg, "setPrestige", "insertMultiplier", discordID, newMultiplier, err) + tx.Rollback() + return + } + _, err = tx.Exec("REPLACE INTO xp(id, xp) VALUES(?,0)", discordID) + err = tx.Commit() + if err != nil { + logError(dg, "setPrestige", "insertXP", discordID, newMultiplier, err) + tx.Rollback() + return + } + if err != nil { + logError(dg, "setPrestige", "commit", discordID, newMultiplier, err) + return + } + + prestigeCache[discordID] = newMultiplier +} + +func getPrestige(dg *discordgo.Session, discordID string) int { + prestigeMutex.Lock() + defer prestigeMutex.Unlock() + + if prestigeCache[discordID] > 0 { + return prestigeCache[discordID] + } + + rows, err := db.Query("SELECT multiplier FROM prestige WHERE id=?", discordID) + if err != nil { + logError(dg, "getPrestige", "select", discordID, err) + return 0 + } + defer rows.Close() + if rows.Next() { + var multiplier int + rows.Scan(&multiplier) + prestigeCache[discordID] = multiplier + return multiplier + } + prestigeCache[discordID] = 1 + return 1 +} diff --git a/xp.go b/xp.go index b90ec82..e1da77a 100644 --- a/xp.go +++ b/xp.go @@ -28,6 +28,7 @@ func incrementXP(dg *discordgo.Session, discordID string, inGeneral bool) { if !inGeneral { amountToIncrement /= notInGeneralNerf } + amountToIncrement *= getPrestige(dg, discordID) tx, err := db.Begin() if err != nil { @@ -48,19 +49,23 @@ func incrementXP(dg *discordgo.Session, discordID string, inGeneral bool) { addToLevelQueue(discordID) } -func getLevelAndXP(dg *discordgo.Session, discordID string) (int, int) { +func getXP(dg *discordgo.Session, discordID string) int { rows, err := db.Query("SELECT xp FROM xp WHERE id=?", discordID) if err != nil { logError(dg, "getLevelAndXP", "select", discordID, err) - return 1, 0 + return 0 } defer rows.Close() if rows.Next() { var xp int rows.Scan(&xp) - return convertXPIntoLevel(xp) + return xp } - return 1, 0 + return 0 +} + +func getLevelAndXP(dg *discordgo.Session, discordID string) (int, int) { + return convertXPIntoLevel(getXP(dg, discordID)) } func calculateIncrement(discordID string) int {