package main import ( "fmt" "math/rand" "os" "path/filepath" "sort" "strconv" "strings" "time" "github.com/rudi9719/loggy" ) func setupCommands() { reboot := Command{ Name: "Reboot", RequiresAdmin: true, Help: "Reboot me, requires token from logs.", Keywords: []string{"reboot", "re", "restart"}, Exec: Reboot, } commands = append(commands, reboot) bumpset := Command{ Name: "BumpSet", RequiresAdmin: true, Help: "Set the bump timer (requires time in minutes until next bump).", Keywords: []string{"bs", "bumpset", "bumps"}, Exec: BumpSet, } commands = append(commands, bumpset) retrieveVerification := Command{ Name: "Retrieve Verification", RequiresAdmin: true, Help: "Retrieve verification either by discord ID or by nickname", Keywords: []string{"veri", "verification", "retrieve"}, Exec: RetrieveVerification, } commands = append(commands, retrieveVerification) addQuote := Command{ Name: "Add Quote", RequiresAdmin: true, Keywords: []string{"quote", "addq", "q"}, Exec: AddQuote, } commands = append(commands, addQuote) snap := Command{ Name: "Snap", Help: "Trigger a purge!", RequiresAdmin: false, Keywords: []string{"snap", "purge", "sn"}, Exec: Snap, } commands = append(commands, snap) status := Command{ Name: "Status", RequiresAdmin: true, Help: "Show the current status of Thanos/Verifications and probations", Keywords: []string{"st", "status", "stats"}, Exec: Status, } commands = append(commands, status) listCommands := Command{ Name: "List Commands", RequiresAdmin: false, Keywords: []string{"help", "commands", "cmd", "cmds"}, Exec: Commands, } commands = append(commands, listCommands) debugLevel := Command{ Name: "Debug Level", RequiresAdmin: true, Keywords: []string{"debug"}, Exec: Debug, Help: "Set the log level for loggy", } commands = append(commands, debugLevel) activityReport := Command{ Name: "Activity Report", RequiresAdmin: false, Keywords: []string{"activity", "active", "list"}, Exec: ActivityReport, Help: "List activity for the discord. Supply a number to get the top N users (5 would be top 5 users) or all for all users!", } commands = append(commands, activityReport) urlWhitelist := Command{ Name: "Whitelist URL", RequiresAdmin: true, Keywords: []string{"whitelist", "wl"}, Exec: WhitelistURL, Help: "Add a domain to the HTTP whitelist domains are in the format `thisvid.com` without the subdomain.", } commands = append(commands, urlWhitelist) } func Commands(b BotCommand) bool { defer log.PanicSafe() print := "Available commands:\n" for _, cmd := range commands { if cmd.RequiresAdmin { if isAdmin(b.Message.Member) { print += fmt.Sprintf("```%+v\n%+v\n%+v```\n", cmd.Name, cmd.Keywords, cmd.Help) } } else { print += fmt.Sprintf("```%+v\n%+v\n%+v```\n", cmd.Name, cmd.Keywords, cmd.Help) } } b.Session.ChannelMessageSend(b.Message.ChannelID, print) return true } func Debug(b BotCommand) bool { defer log.PanicSafe() level, err := strconv.Atoi(b.Parts[0]) if err != nil { return false } config.LogOpts.Level = loggy.LogLevel(level) log = loggy.NewLogger(config.LogOpts) return true } func Reboot(b BotCommand) bool { defer log.PanicSafe() if strings.Contains(b.Message.Content, rebootToken) { exit(b.Session) return true } return false } func ActivityReport(b BotCommand) bool { useCounter := true counterStop := 4 if len(b.Parts) > 0 { test, err := strconv.Atoi(b.Parts[0]) if err == nil { counterStop = test } else { useCounter = false } } statistics := "```" n := map[int][]string{} counter := 0 var a []int for k, v := range config.Activity { n[v] = append(n[v], k) } for k := range n { a = append(a, k) } sort.Sort(sort.Reverse(sort.IntSlice(a))) for _, k := range a { for _, s := range n[k] { if useCounter && counter == counterStop-1 { return true } user, err := b.Session.GuildMember(config.GuildID, s) if err == nil { statistics += fmt.Sprintf("\n%+v: %+v", user.User.Username, k) counter++ } else { log.LogErrorType(err) } } } statistics += "\n```" return true } func BumpSet(b BotCommand) bool { defer log.PanicSafe() bump = false timer, err := strconv.Atoi(b.Parts[0]) if err != nil { b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("Unable to decode timer: %+v", b.Parts[0])) return false } config.BumpTime = time.Now().Add(time.Duration(timer) * time.Minute).Add(-2 * time.Hour) b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("New last bump time: , expecting next bump at ", config.BumpTime.Unix(), config.BumpTime.Add(2*time.Hour).Unix())) return true } func RetrieveVerification(b BotCommand) bool { defer log.PanicSafe() discordId := b.Parts[0] _, err := strconv.Atoi(discordId) if err != nil { discordId = idFromUsername(discordId) } user, err := b.Session.GuildMember(config.GuildID, discordId) if err != nil { log.LogErrorType(err) return false } matches, err := filepath.Glob(fmt.Sprintf("./verifications/*%+v*", discordId)) if err != nil { log.LogErrorType(err) return false } if len(matches) != 1 { b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("Error finding verification for ID %+v", discordId)) return false } verificationImage, err := os.Open(matches[0]) if err != nil { log.LogErrorType(err) return false } msg := fmt.Sprintf("``` %+v\nJoined: %+v\n```", user.User.Username, user.JoinedAt) b.Session.ChannelFileSendWithMessage(b.Message.ChannelID, msg, matches[0], verificationImage) return true } func AddQuote(b BotCommand) bool { defer log.PanicSafe() quotes = append(quotes, strings.ReplaceAll(b.Message.Content, b.Command, "")) return true } func Snap(b BotCommand) bool { defer log.PanicSafe() go runPurge(b.Session) b.Session.ChannelMessageSend(config.AdminChannel, quotes[rand.Intn(len(quotes))]) return true } func Status(b BotCommand) bool { defer log.PanicSafe() status := fmt.Sprintf("Uptime: %+v\n", time.Since(startupTime)) status += fmt.Sprintf("Last active time: %+v\n", time.Since(lastActiveTime)) status += fmt.Sprintf("Last bump: \n", config.BumpTime.Unix()) status += fmt.Sprintf("Last bumper: %+v\n", userFromID(config.LastBumper).Username) status += fmt.Sprintf("Bump needed: %+v\n", bump) if len(config.Unverified) > 0 { status += "Unverified users:\n" for k, v := range config.Unverified { uvUser := userFromID(k) status += fmt.Sprintf("\n%+v will be removed at ", uvUser.Username, v.Add(1*time.Hour).Unix()) } status += "\n" } else { status += "There are no unverified users.\n" } if len(config.Verifications) > 0 { status += "Pending verifications:\n" for _, v := range config.Verifications { status += fmt.Sprintf("%+v has submitted a verification.", v.Username) } status += "\n" } else { status += "There are no pending verifications.\n" } if len(config.Probations) > 0 { status += "\nThe following users are on probation: \n" for uid, join := range config.Probations { probationUser := userFromID(uid) status += fmt.Sprintf("%+v for until \n", probationUser.Username, join.Add(2*time.Hour).Unix()) } status += "\n" } else { status += "There are no users on probation.\n" } b.Session.ChannelMessageSend(config.AdminChannel, status) statistics := "```" for k, v := range config.Stats { adminUser, err := b.Session.GuildMember(config.GuildID, k) if err == nil { statistics += fmt.Sprintf("\n%+v: %+v", adminUser.User.Username, v+1) } else { log.LogErrorType(err) } } statistics += "\n```" log.LogInfo("Private statistics: %+v", statistics) go runPurge(b.Session) return true } func WhitelistURL(b BotCommand) bool { defer log.PanicSafe() newURL := strings.TrimSpace( strings.ReplaceAll( strings.ReplaceAll(b.Message.Content, b.Command, ""), "<@688025671968096341>", ""), ) if len(newURL) > 0 { config.WhitelistURLs = append(config.WhitelistURLs, newURL) } domains := strings.Join(config.WhitelistURLs, "\n") b.Session.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("Current whitelisted domains: %+v", domains)) log.LogDebug(fmt.Sprintf("Current whitelisted domains: %+v", domains)) return true }