From 614186a4a73b49babcd2cb472c6f4a209babb8d3 Mon Sep 17 00:00:00 2001 From: Luther Wen Xu Date: Mon, 18 Nov 2019 22:38:03 +0800 Subject: [PATCH] gacha: Implement permission giving --- db.go | 20 ++++++++++++ gacha.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ levels.go | 10 +++--- messageCreate.go | 16 ++++++++- shard.go | 39 ++++++++++++++++++++++ xp.go | 11 ------- 6 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 db.go create mode 100644 gacha.go create mode 100644 shard.go diff --git a/db.go b/db.go new file mode 100644 index 0000000..f19beae --- /dev/null +++ b/db.go @@ -0,0 +1,20 @@ +package main + +import ( + "database/sql" + + _ "github.com/mattn/go-sqlite3" +) + +var db *sql.DB + +func init() { + var err error + db, err = sql.Open("sqlite3", "./bot.db") + if err != nil { + panic(err) + } + 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)") +} diff --git a/gacha.go b/gacha.go new file mode 100644 index 0000000..5a8060a --- /dev/null +++ b/gacha.go @@ -0,0 +1,85 @@ +package main + +import ( + "crypto/rand" + "fmt" + + "github.com/bwmarrin/discordgo" +) + +const ( + viewAuditLogRole = "645856347258093568" + manageWebhookRole = "645856081750523914" + changeNicknameRole = "645977231281356800" + embedLinkRole = "645977361254318080" + voiceActivityRole = "645977361254318080" +) + +func checkForGachaEligibility(dg *discordgo.Session, discordID, intendedLevel string) { + member, err := dg.GuildMember(guildID, discordID) + if err != nil { + logError(dg, "checkForGachaEligibility", "getGuildMember", discordID) + return + } + found := false + for _, v := range member.Roles { + if v == intendedLevel { + found = true + break + } + } + if found { + return + } + + rollGacha(dg, member) + + err = dg.GuildMemberRoleAdd(guildID, discordID, intendedLevel) + if err != nil { + logError(dg, "checkForGachaEligibility", "guildMemberRoleAdd", err) + } +} + +func rollGacha(dg *discordgo.Session, member *discordgo.Member) { + lookUpAndGive := func(friendlyName, role string) { + found := false + for _, v := range member.Roles { + if v == role { + found = true + break + } + } + channel, err := dg.UserChannelCreate(member.User.ID) + if found { + rewardShard(dg, member.User.ID) + if err == nil { + dg.ChannelMessageSend( + channel.ID, + fmt.Sprintf( + "**GACHA > ** You got __%s__! However, it was a duplicate so you got a shard instead.", friendlyName, + ), + ) + } + } else { + dg.GuildMemberRoleAdd(guildID, member.User.ID, role) + dg.ChannelMessageSend( + channel.ID, + fmt.Sprintf("**GACHA > ** You got __%s__!", friendlyName), + ) + } + } + gachaRandomness := make([]byte, 1) + rand.Read(gachaRandomness) + switch gachaRandomness[0] % 5 { + case 0: + lookUpAndGive("View Audit Log", viewAuditLogRole) + case 1: + lookUpAndGive("Manage Webhook", manageWebhookRole) + case 2: + lookUpAndGive("Change Nickname", changeNicknameRole) + case 3: + lookUpAndGive("Embed Link", embedLinkRole) + case 4: + lookUpAndGive("Use Voice Activity", voiceActivityRole) + } +} diff --git a/levels.go b/levels.go index b6313bf..d7a0986 100644 --- a/levels.go +++ b/levels.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/ioutil" "strings" "sync" @@ -17,7 +18,7 @@ var assignedLevels = make(map[string]int) var rolesFromLevel []string func init() { - levels, _ := ioutil.ReadFile("levels.txt") + levels, _ := ioutil.ReadFile("roles.txt") rolesFromLevel = strings.Split(string(levels), "\n") for k, v := range rolesFromLevel { rolesFromLevel[k] = strings.TrimSpace(v) @@ -32,6 +33,7 @@ func addToLevelQueue(discordID string) { func listenToLevelUpdate(dg *discordgo.Session) { for { + time.Sleep(5 * time.Second) levelMutex.Lock() for k, v := range levelQueue { if !v { @@ -41,13 +43,9 @@ func listenToLevelUpdate(dg *discordgo.Session) { level, _ := getLevelAndXP(dg, k) if assignedLevels[k] != level { assignedLevels[k] = level - err := dg.GuildMemberRoleAdd(guildID, k, rolesFromLevel[level-1]) - if err != nil { - logError(dg, "assignlevel", err) - } + go checkForGachaEligibility(dg, k, rolesFromLevel[level-1]) } } levelMutex.Unlock() - time.Sleep(5 * time.Second) } } diff --git a/messageCreate.go b/messageCreate.go index ac74c64..c5423a0 100644 --- a/messageCreate.go +++ b/messageCreate.go @@ -12,9 +12,12 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { } go incrementXP(s, m.Author.ID) - if m.Content == "p!level" { + if m.Content == "pgqlevel" { handleXPRequest(s, m) } + if m.Content == "pgqshard" { + handleShardRequest(s, m) + } } func handleXPRequest(s *discordgo.Session, m *discordgo.MessageCreate) { @@ -31,3 +34,14 @@ func handleXPRequest(s *discordgo.Session, m *discordgo.MessageCreate) { ), ) } + +func handleShardRequest(s *discordgo.Session, m *discordgo.MessageCreate) { + shard := getShard(s, m.Author.ID) + s.ChannelMessageSend( + m.ChannelID, + fmt.Sprintf( + "<@%s> has %d shards.", + m.Author.ID, shard, + ), + ) +} diff --git a/shard.go b/shard.go new file mode 100644 index 0000000..aa182fc --- /dev/null +++ b/shard.go @@ -0,0 +1,39 @@ +package main + +import ( + "github.com/bwmarrin/discordgo" +) + +func rewardShard(dg *discordgo.Session, discordID string) { + tx, err := db.Begin() + if err != nil { + logError(dg, "rewardShard", "begin", discordID, err) + return + } + _, err = tx.Exec("INSERT INTO shard(id, shard) VALUES(?, 1) ON CONFLICT(id) DO UPDATE SET shard = shard+1;", discordID) + if err != nil { + logError(dg, "rewardShard", "insert", discordID, err) + tx.Rollback() + return + } + err = tx.Commit() + if err != nil { + logError(dg, "rewardShard", "commit", discordID, err) + return + } +} + +func getShard(dg *discordgo.Session, discordID string) int { + rows, err := db.Query("SELECT shard FROM shard WHERE id=?", discordID) + if err != nil { + logError(dg, "getShard", "select", discordID, err) + return 0 + } + defer rows.Close() + if rows.Next() { + var shard int + rows.Scan(&shard) + return shard + } + return 0 +} diff --git a/xp.go b/xp.go index 86ac515..2bb4174 100644 --- a/xp.go +++ b/xp.go @@ -1,29 +1,18 @@ package main import ( - "database/sql" "math" "sync" "time" "github.com/bwmarrin/discordgo" - _ "github.com/mattn/go-sqlite3" ) -var db *sql.DB var lastMessage = make(map[string]time.Time) var incrementMutex = sync.Mutex{} var levelUpRequirementCache [30]int func init() { - var err error - db, err = sql.Open("sqlite3", "./bot.db") - if err != nil { - panic(err) - } - db.SetMaxOpenConns(1) - db.Exec("CREATE TABLE xp(id STRING NOT NULL UNIQUE, xp INTEGER NOT NULL)") - for i := 1; i <= 30; i++ { //Constructed on Desmos: //y=2^{\frac{x}{3}}+.1x^{2}+1.2x-1