modules: Move most code in main package to their own modules

master
Luther Wen Xu 2019-11-27 17:07:48 +07:00
parent 4887d55707
commit 825cf44216
Signed by: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
18 changed files with 413 additions and 243 deletions

@ -1,89 +0,0 @@
package main
import (
"crypto/rand"
"fmt"
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
)
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
}
if intendedLevel != rolesFromLevel[0] {
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 {
db.RewardShard(member.User.ID, 1)
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)
}
}

@ -1,54 +0,0 @@
package main
import (
"io/ioutil"
"strings"
"sync"
"time"
"github.com/bwmarrin/discordgo"
)
const guildID = "645550569573842945"
var levelMutex sync.Mutex
var levelQueue = make(map[string]bool)
var assignedLevels = make(map[string]int)
var rolesFromLevel []string
func init() {
levels, _ := ioutil.ReadFile("roles.txt")
rolesFromLevel = strings.Split(string(levels), "\n")
for k, v := range rolesFromLevel {
rolesFromLevel[k] = strings.TrimSpace(v)
}
}
func addToLevelQueue(discordID string) {
levelMutex.Lock()
defer levelMutex.Unlock()
levelQueue[discordID] = true
}
func listenToLevelUpdate(dg *discordgo.Session) {
for {
time.Sleep(5 * time.Second)
levelMutex.Lock()
for k, v := range levelQueue {
if !v {
continue
}
levelQueue[k] = false
level, _, err := getLevelAndXP(k)
if err != nil {
logError(dg, err)
continue
}
if assignedLevels[k] != level {
assignedLevels[k] = level
go checkForGachaEligibility(dg, k, rolesFromLevel[level-1])
}
}
levelMutex.Unlock()
}
}

@ -11,6 +11,8 @@ import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
"PermissionGacha/modules/level"
"PermissionGacha/modules/starboard"
)
func main() {
@ -23,13 +25,13 @@ func main() {
}
dg.AddHandler(messageCreate)
dg.AddHandler(checkPrestigeReact)
dg.AddHandler(listenToStarboardReact)
dg.AddHandler(starboard.ReactListener)
err = dg.Open()
if err != nil {
fmt.Println("Error opening Discord session:", err)
return
}
go listenToLevelUpdate(dg)
go level.ScheduleUpdates(dg)
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)

@ -10,6 +10,11 @@ import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
"PermissionGacha/modules/active"
mlevel "PermissionGacha/modules/level"
"PermissionGacha/modules/log"
"PermissionGacha/modules/roles"
"PermissionGacha/modules/starboard"
)
const emojiCheck = "✅"
@ -21,7 +26,7 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.Bot {
return
}
go incrementXP(s, m)
go active.Reward(s, m)
if m.Content == "pgqlevel" {
handleXPRequest(s, m)
@ -38,18 +43,15 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
}
func handleXPRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
level, rawXP, err := getLevelAndXP(m.Author.ID)
level, rawXP, err := mlevel.GetLevelAndXP(m.Author.ID)
if err != nil {
logError(s, err)
log.Error(s, "handleXPRequest", "GetLevelAndXP", err)
return
}
randomSource := make([]byte, 1)
rand.Read(randomSource)
xp := rawXP - (rawXP % 100) + ((int(randomSource[0]) + 128) % 100)
levelUpRequirement := levelUpRequirementCache[level-1]
if level > 1 {
levelUpRequirement -= levelUpRequirementCache[level-2]
}
levelUpRequirement := mlevel.GetLevelUpRequirement(level)
s.ChannelMessageSend(
m.ChannelID,
fmt.Sprintf(
@ -62,7 +64,7 @@ func handleXPRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
func handleShardRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
shard, err := db.GetShard(m.Author.ID)
if err != nil {
logError(s, err)
log.Error(s, "handleShardRequest", "GetShard", err)
return
}
s.ChannelMessageSend(
@ -77,17 +79,19 @@ func handleShardRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
func handlePrestigeRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
currentPrestigeLevel, err := db.GetPrestigeMultiplier(m.Author.ID)
if err != nil {
logError(s, err)
log.Error(s, "handlePrestigeRequest", "GetPrestigeMultiplier", err)
return
}
xp, err := db.GetXP(m.Author.ID)
if err != nil {
logError(s, err)
log.Error(s, "handlePrestigeRequest", "GetXP", err)
return
}
newPrestigeLevel := xp/prestigeRequirement + 1
if xp < levelUpRequirementCache[3] && currentPrestigeLevel == 1 {
level, _ := mlevel.ConvertXPIntoLevel(xp)
if level < 5 && currentPrestigeLevel == 1 {
s.ChannelMessageSend(m.ChannelID, "**PRESTIGE > **Prestige is only unlocked after level 5!")
return
}
@ -112,20 +116,20 @@ func handlePrestigeRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
),
)
if err != nil {
logError(s, "handlePrestigeRequest", "send", err)
log.Error(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)
log.Error(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)
log.Error(s, "handlePrestigeRequest", "removeReaction", err)
}
}()
}
@ -139,14 +143,14 @@ func checkPrestigeReact(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
}
xp, err := db.GetXP(m.UserID)
if err != nil {
logError(s, err)
log.Error(s, "checkPrestigeReact", "GetXP", err)
return
}
newPrestigeLevel := xp/prestigeRequirement + 1
go cleanUpRole(s, m.UserID)
go roles.RemoveAllLevelRoles(s, m.UserID)
err = db.SetPrestigeMultiplier(m.UserID, newPrestigeLevel)
if err != nil {
logError(s, err)
log.Error(s, "checkPrestigeReact", "SetPrestigeMultiplier", err)
return
}
s.ChannelMessageSend(m.ChannelID,
@ -183,7 +187,7 @@ func handleStarRequest(s *discordgo.Session, m *discordgo.MessageCreate) {
s.ChannelMessageSend(m.ChannelID, "**STAR > **It doesn't seem like you've sent a valid message link!")
return
}
err := s.MessageReactionAdd(linkSplit[5], linkSplit[6], starEmoji)
err := starboard.AddReact(s, linkSplit[5], linkSplit[6])
if err != nil {
s.ChannelMessageSend(m.ChannelID, "**STAR > **It doesn't seem like you've sent a valid message link!")
}

@ -1,7 +1,6 @@
package main
package active
import (
"fmt"
"math"
"sync"
"time"
@ -9,6 +8,8 @@ import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
"PermissionGacha/modules/level"
"PermissionGacha/modules/log"
)
const notInGeneralNerf = 10
@ -17,35 +18,25 @@ const generalChannelID = "645550570001924098"
var lastMessage = make(map[string]time.Time)
var incrementMutex = sync.Mutex{}
var levelUpRequirementCache [30]int
func init() {
for i := 1; i <= 30; i++ {
//Constructed on Desmos:
//y=2^{\frac{x}{2}}+.1x^{2}+1.2x-1
fi := float64(i)
levelUpRequirementCache[i-1] = int(10000 * (math.Pow(2, fi/2) + 0.1*fi*fi + 1.2*fi - 1))
}
}
func incrementXP(s *discordgo.Session, m *discordgo.MessageCreate) {
func Reward(s *discordgo.Session, m *discordgo.MessageCreate) {
amountToIncrement := calculateIncrement(m.Author.ID)
if m.ChannelID != generalChannelID {
amountToIncrement /= notInGeneralNerf
}
multiplier, err := db.GetPrestigeMultiplier(m.Author.ID)
if err != nil {
logError(s, err)
log.Error(s, err)
return
}
amountToIncrement *= multiplier
err = db.IncrementXP(m.Author.ID, amountToIncrement)
if err != nil {
logError(s, err)
log.Error(s, err)
return
}
addToLevelQueue(m.Author.ID)
level.QueueCheck(m.Author.ID)
}
func calculateIncrement(discordID string) int {
@ -64,24 +55,3 @@ func calculateIncrement(discordID string) int {
//y=\frac{100}{\left(1+e^{-\left(\frac{x}{2}-5\right)}\right)}
return int(100 / (1 + math.Pow(math.E, -((delta.Seconds()/2)-5))))
}
func convertXPIntoLevel(xp int) (int, int) {
if xp < levelUpRequirementCache[0] {
return 1, xp
}
for i := 0; i < 30; i++ {
if levelUpRequirementCache[i] > xp {
return i + 1, xp - levelUpRequirementCache[i-1]
}
}
return 30, xp - levelUpRequirementCache[29]
}
func getLevelAndXP(discordID string) (int, int, error) {
rawXP, err := db.GetXP(discordID)
if err != nil {
return 1, 0, fmt.Errorf("xp: getLevelAndXP: error requesting XP: %w", err)
}
level, xp := convertXPIntoLevel(rawXP)
return level, xp, nil
}

@ -0,0 +1,3 @@
package config
const GuildID = "645550569573842945"

@ -0,0 +1,22 @@
package gacha
import (
crand "crypto/rand"
"encoding/binary"
mrand "math/rand"
)
var rand = mrand.New(cryptoSource{})
type cryptoSource struct{}
func (cryptoSource) Int63() int64 {
var value uint64
err := binary.Read(crand.Reader, binary.BigEndian, &value)
if err != nil {
panic(err)
}
return int64(value ^ uint64(1<<63))
}
func (cryptoSource) Seed(seed int64) {}

@ -0,0 +1,50 @@
package gacha
import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/modules/config"
)
type reward struct {
FriendlyName string
Reward func(s *discordgo.Session, member *discordgo.Member) (bool, error)
}
var gachaRewards = []reward{
reward{
FriendlyName: "View Audit Log",
Reward: generateRoleReward("645856347258093568"),
},
reward{
FriendlyName: "Manage Webhook",
Reward: generateRoleReward("645856081750523914"),
},
reward{
FriendlyName: "Change Nickname",
Reward: generateRoleReward("645977231281356800"),
},
reward{
FriendlyName: "Use Voice Activity",
Reward: generateRoleReward("645880647474479115"),
},
reward{
FriendlyName: "Embed Link",
Reward: generateRoleReward("645977361254318080"),
},
}
func generateRoleReward(roleID string) func(s *discordgo.Session, member *discordgo.Member) (bool, error) {
return func(s *discordgo.Session, member *discordgo.Member) (bool, error) {
for _, v := range member.Roles {
if v == roleID {
return false, nil
}
}
err := s.GuildMemberRoleAdd(config.GuildID, member.User.ID, roleID)
if err != nil {
return false, err
}
return true, nil
}
}

@ -0,0 +1,87 @@
package gacha
import (
"fmt"
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
"PermissionGacha/modules/config"
)
func RollReward(s *discordgo.Session, rewardeeID string, timesToReward int) error {
if timesToReward <= 0 {
return nil
}
rewardee, err := s.GuildMember(config.GuildID, rewardeeID)
if err != nil {
return err
}
rewardCount := make(map[int]map[bool]int)
shardCount := 0
for i := 0; i < timesToReward; i++ {
rewardID := rand.Intn(len(gachaRewards))
success, err := gachaRewards[rewardID].Reward(s, rewardee)
if err != nil {
return err
}
if _, ok := rewardCount[rewardID]; !ok {
rewardCount[rewardID] = make(map[bool]int)
}
if success {
rewardee, err = s.GuildMember(config.GuildID, rewardeeID)
if err != nil {
return err
}
} else {
shardCount++
}
rewardCount[rewardID][success]++
}
err = db.RewardShard(rewardeeID, shardCount)
if err != nil {
return err
}
channel, err := s.UserChannelCreate(rewardeeID)
if err != nil {
return err
}
if timesToReward == 1 {
for k, v := range rewardCount {
if v[true] > 0 {
//They were rewarded that exact thing.
s.ChannelMessageSend(
channel.ID,
fmt.Sprintf(
"**GACHA >** <@%s>, you just levelled up! You got __%s__.",
rewardeeID, gachaRewards[k].FriendlyName,
),
)
} else {
//They were rewarded that thing but got a shard instead.
s.ChannelMessageSend(
channel.ID,
fmt.Sprintf(
"**GACHA >** <@%s>, you just levelled up! You originally got __%s__ but you got a shard instead.",
rewardeeID, gachaRewards[k].FriendlyName,
),
)
}
}
} else {
msg := fmt.Sprintf(
"**GACHA >** <@%s>, you just levelled up %d times. Here are your rewards:",
rewardeeID, timesToReward,
)
for k, v := range rewardCount {
msg += fmt.Sprintf("\n- __%s__", gachaRewards[k].FriendlyName)
if v[false] > 0 {
msg += fmt.Sprintf(" (%d converted to shards)", v[false])
}
}
s.ChannelMessageSend(channel.ID, msg)
}
return nil
}

@ -0,0 +1,53 @@
package level
import (
"fmt"
"math"
"PermissionGacha/db"
)
var levelUpRequirementCache [30]int
func init() {
for i := 1; i <= 30; i++ {
//Constructed on Desmos:
//y=2^{\frac{x}{2}}+.1x^{2}+1.2x-1
fi := float64(i)
levelUpRequirementCache[i-1] = int(10000 * (math.Pow(2, fi/2) + 0.1*fi*fi + 1.2*fi - 1))
}
}
func GetLevelAndXP(discordID string) (int, int, error) {
rawXP, err := db.GetXP(discordID)
if err != nil {
return 1, 0, fmt.Errorf("level: GetLevelAndXP: error requesting XP: %w", err)
}
level, xp := ConvertXPIntoLevel(rawXP)
return level, xp, nil
}
func GetLevelUpRequirement(level int) int {
if level <= 0 {
return 0
}
if level == 1 {
return levelUpRequirementCache[0]
}
if level > len(levelUpRequirementCache) {
return levelUpRequirementCache[len(levelUpRequirementCache)-1]
}
return levelUpRequirementCache[level-1] - levelUpRequirementCache[level-2]
}
func ConvertXPIntoLevel(xp int) (int, int) {
if xp < levelUpRequirementCache[0] {
return 1, xp
}
for i := 0; i < 30; i++ {
if levelUpRequirementCache[i] > xp {
return i + 1, xp - levelUpRequirementCache[i-1]
}
}
return 30, xp - levelUpRequirementCache[29]
}

@ -0,0 +1,57 @@
package level
import (
"sync"
"time"
"github.com/bwmarrin/discordgo"
"PermissionGacha/modules/gacha"
"PermissionGacha/modules/log"
"PermissionGacha/modules/roles"
)
var (
levelMutex sync.Mutex
levelQueue = make(map[string]bool)
lastKnownLevel = make(map[string]int)
)
func QueueCheck(discordID string) {
levelMutex.Lock()
defer levelMutex.Unlock()
levelQueue[discordID] = true
}
func ScheduleUpdates(s *discordgo.Session) {
for {
time.Sleep(5 * time.Second)
levelMutex.Lock()
for id, isQueued := range levelQueue {
if !isQueued {
continue
}
delete(levelQueue, id)
level, _, err := GetLevelAndXP(id)
if err != nil {
log.Error(s, err)
continue
}
if lastKnownLevel[id] != level {
lastKnownLevel[id] = level
go func() {
oldLevel, err := roles.GetOldLevel(s, id)
if err != nil {
log.Error(s, err)
return
}
if level > oldLevel {
gacha.RollReward(s, id, level-oldLevel)
roles.GiveLevelRoles(s, id, oldLevel, level)
}
}()
}
}
levelMutex.Unlock()
}
}

@ -0,0 +1,18 @@
package log
import (
llog "log"
"github.com/bwmarrin/discordgo"
)
func Error(s *discordgo.Session, a ...interface{}) {
s.UpdateStatusComplex(discordgo.UpdateStatusData{
Game: &discordgo.Game{
Name: "with error",
Type: discordgo.GameTypeGame,
},
Status: string(discordgo.StatusDoNotDisturb),
})
llog.Println(a...)
}

@ -0,0 +1,30 @@
package roles
import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/modules/config"
"PermissionGacha/modules/log"
)
func GiveLevelRoles(s *discordgo.Session, discordID string, oldLevel, newLevel int) {
for i := oldLevel; i <= newLevel; i++ {
s.GuildMemberRoleAdd(config.GuildID, discordID, rolesFromLevel[i-1])
}
}
func RemoveAllLevelRoles(s *discordgo.Session, discordID string) {
member, err := s.GuildMember(config.GuildID, discordID)
if err != nil {
log.Error(s, "RemoveAllLevelRoles", "GuildMember", discordID)
return
}
for _, v := range member.Roles {
for _, w := range rolesFromLevel {
if v == w {
s.GuildMemberRoleRemove(config.GuildID, discordID, v)
break
}
}
}
}

@ -0,0 +1,30 @@
package roles
import (
"fmt"
"github.com/bwmarrin/discordgo"
"PermissionGacha/modules/config"
)
func GetOldLevel(s *discordgo.Session, id string) (int, error) {
member, err := s.GuildMember(config.GuildID, id)
if err != nil {
return 0, fmt.Errorf("roles: EligibleGachaCount: error fetching guild member (%s): %w", id, err)
}
var foundLevel = 0
levelSearchLoop:
for i := len(rolesFromLevel); i > 0; i-- {
for _, v := range member.Roles {
if rolesFromLevel[i-1] == v {
foundLevel = i
break levelSearchLoop
}
}
}
if foundLevel == 0 {
return 0, nil
}
return foundLevel, nil
}

@ -0,0 +1,16 @@
package roles
import (
"io/ioutil"
"strings"
)
var rolesFromLevel []string
func init() {
listOfRoles, _ := ioutil.ReadFile("roles.txt")
rolesFromLevel = strings.Split(string(listOfRoles), "\n")
for k, v := range rolesFromLevel {
rolesFromLevel[k] = strings.TrimSpace(v)
}
}

@ -1,4 +1,4 @@
package main
package starboard
import (
"fmt"
@ -9,6 +9,7 @@ import (
"github.com/bwmarrin/discordgo"
"PermissionGacha/db"
"PermissionGacha/modules/log"
)
const starEmoji = "⭐"
@ -16,7 +17,7 @@ const starChannel = "645551408283648000"
var starboardMutex sync.Mutex
func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
func ReactListener(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
if m.ChannelID == starChannel {
return
}
@ -25,7 +26,7 @@ func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAd
}
messageTimestamp, err := discordgo.SnowflakeTimestamp(m.MessageID)
if err != nil {
logError(s, "listenToStarboardReact", "snowflakeTimestamp", m.MessageID, err)
log.Error(s, "listenToStarboardReact", "snowflakeTimestamp", m.MessageID, err)
return
}
if time.Now().Sub(messageTimestamp) > 24*time.Hour {
@ -36,7 +37,7 @@ func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAd
starredBefore, err := db.HasStarredBefore(m.MessageID)
if err != nil {
logError(s, err)
log.Error(s, err)
return
}
if starredBefore {
@ -45,7 +46,7 @@ func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAd
reacter, err := s.MessageReactions(m.ChannelID, m.MessageID, starEmoji, 5)
if err != nil {
logError(s, "listenToStarboardReact", "messageReactions", m.ChannelID, m.MessageID, err)
log.Error(s, "listenToStarboardReact", "messageReactions", m.ChannelID, m.MessageID, err)
return
}
if len(reacter) < 3 {
@ -54,7 +55,7 @@ func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAd
msg, err := s.ChannelMessage(m.ChannelID, m.MessageID)
if err != nil {
logError(s, "listenToStarboardReact", "channelMessage", m.ChannelID, m.MessageID, err)
log.Error(s, "listenToStarboardReact", "channelMessage", m.ChannelID, m.MessageID, err)
return
}
@ -93,17 +94,21 @@ func listenToStarboardReact(s *discordgo.Session, m *discordgo.MessageReactionAd
},
)
if err != nil {
logError(s, "listenToStarboardReact", "channelMessageSendEmbed", err)
log.Error(s, "listenToStarboardReact", "channelMessageSendEmbed", err)
return
}
err = s.MessageReactionAdd(msg.ChannelID, msg.ID, starEmoji)
if err != nil {
logError(s, "listenToStarboardReact", "messageReactionAdd", err)
log.Error(s, "listenToStarboardReact", "messageReactionAdd", err)
return
}
err = db.SetStarred(msg.ID)
if err != nil {
logError(s, err)
log.Error(s, err)
return
}
}
func AddReact(s *discordgo.Session, channelID, messageID string) error {
return s.MessageReactionAdd(channelID, messageID, starEmoji)
}

@ -1,21 +0,0 @@
package main
import (
"github.com/bwmarrin/discordgo"
)
func cleanUpRole(s *discordgo.Session, discordID string) {
member, err := s.GuildMember(guildID, discordID)
if err != nil {
logError(s, "cleanUpRole", "guildMember", discordID)
return
}
for _, v := range member.Roles {
for _, w := range rolesFromLevel {
if v == w {
s.GuildMemberRoleRemove(guildID, discordID, v)
break
}
}
}
}

@ -1,13 +0,0 @@
package main
import (
"log"
"github.com/bwmarrin/discordgo"
)
func logError(dg *discordgo.Session, a ...interface{}) {
dg.UserUpdateStatus(discordgo.StatusDoNotDisturb)
dg.UpdateStatus(0, "with error")
log.Println(a...)
}