|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
|
|
)
|
|
|
|
|
|
|
|
func status(s *discordgo.Session) {
|
|
|
|
defer log.PanicSafe()
|
|
|
|
status := fmt.Sprintf("Uptime: %+v\n", time.Since(startupTime))
|
|
|
|
status += fmt.Sprintf("Last bump: %+v\n", time.Since(config.BumpTime))
|
|
|
|
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 in %+v", uvUser.Username, time.Until(v.Add(1*time.Hour)))
|
|
|
|
}
|
|
|
|
status += "```"
|
|
|
|
} else {
|
|
|
|
status += "There are no unverified users.\n"
|
|
|
|
}
|
|
|
|
if len(config.Verifications) > 0 {
|
|
|
|
status += "Pending verifications:\n"
|
|
|
|
status += "```"
|
|
|
|
for _, v := range config.Verifications {
|
|
|
|
status += fmt.Sprintf("%+v has submitted a verification.", v.Username)
|
|
|
|
}
|
|
|
|
status += "```"
|
|
|
|
} else {
|
|
|
|
status += "There are no pending verifications."
|
|
|
|
}
|
|
|
|
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 another %+v\n", probationUser.Username, time.Until(join.Add(2*time.Hour)))
|
|
|
|
}
|
|
|
|
status += "```"
|
|
|
|
}
|
|
|
|
s.ChannelMessageSend(config.AdminChannel, status)
|
|
|
|
statistics := "```"
|
|
|
|
for k, v := range config.Stats {
|
|
|
|
adminUser, err := s.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(s)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
func storeVerification(v Verification) {
|
|
|
|
defer log.PanicSafe()
|
|
|
|
fileURL, _ := url.Parse(v.Photo)
|
|
|
|
path := fileURL.Path
|
|
|
|
segments := strings.Split(path, "/")
|
|
|
|
|
|
|
|
fileName := segments[len(segments)-1]
|
|
|
|
file, _ := os.Create(fmt.Sprintf("./verifications/%s-%s-%s", v.UserID, v.Username, fileName))
|
|
|
|
client := http.Client{
|
|
|
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
|
|
|
r.URL.Opaque = r.URL.Path
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
resp, err := client.Get(v.Photo)
|
|
|
|
if err != nil {
|
|
|
|
log.LogError("Unable to download verification %s-%s-%s", v.UserID, v.Username, fileName)
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
defer file.Close()
|
|
|
|
_, err = io.Copy(file, resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
log.LogError("Unable to store verification %s-%s-%s", v.UserID, v.Username, fileName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func loadConfig() {
|
|
|
|
var c Config
|
|
|
|
confFile, _ := ioutil.ReadFile(configFile)
|
|
|
|
err := json.Unmarshal([]byte(confFile), &c)
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
config = c
|
|
|
|
|
|
|
|
if time.Since(config.BumpTime) < (2 * time.Hour) {
|
|
|
|
bump = false
|
|
|
|
} else {
|
|
|
|
bump = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.Stats == nil {
|
|
|
|
config.Stats = make(map[string]int)
|
|
|
|
}
|
|
|
|
if config.Unverified == nil {
|
|
|
|
config.Unverified = make(map[string]time.Time)
|
|
|
|
}
|
|
|
|
if config.Verifications == nil {
|
|
|
|
config.Verifications = make(map[string]Verification)
|
|
|
|
}
|
|
|
|
if config.Probations == nil {
|
|
|
|
config.Probations = make(map[string]time.Time)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.LogInfo("Setup completed using config file.")
|
|
|
|
}
|
|
|
|
|
|
|
|
func saveConfig() {
|
|
|
|
defer log.PanicSafe()
|
|
|
|
file, err := json.Marshal(config)
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(configFile, file, 0600)
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func findVerification(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|
|
|
defer log.PanicSafe()
|
|
|
|
parts := strings.Split(m.Content, " ")
|
|
|
|
discordId := parts[1]
|
|
|
|
_, err := strconv.Atoi(discordId)
|
|
|
|
if err != nil {
|
|
|
|
discordId = idFromUsername(discordId)
|
|
|
|
}
|
|
|
|
user, err := s.GuildMember(config.GuildID, discordId)
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
matches, err := filepath.Glob(fmt.Sprintf("./verifications/*%+v*", discordId))
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(matches) != 1 {
|
|
|
|
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Error finding verification for ID %+v", discordId))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
verificationImage, err := os.Open(matches[0])
|
|
|
|
if err != nil {
|
|
|
|
log.LogErrorType(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
msg := fmt.Sprintf("```%+v\nJoined: %+v\n```", user.User.Username, user.JoinedAt)
|
|
|
|
s.ChannelFileSendWithMessage(m.ChannelID, msg, fmt.Sprintf("%+v Verification", discordId), verificationImage)
|
|
|
|
}
|
|
|
|
|
|
|
|
func bumpTimer(s *discordgo.Session) {
|
|
|
|
if !bump {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bump = false
|
|
|
|
config.BumpTime = time.Now()
|
|
|
|
time.Sleep(2 * time.Hour)
|
|
|
|
if time.Since(lastActiveTime) < (5*time.Minute) && lastActiveChan != config.AdminChannel {
|
|
|
|
s.ChannelMessageSend(lastActiveChan, "!d bump is ready, please use it. (say \"!d bump\" without the quotes)")
|
|
|
|
}
|
|
|
|
s.ChannelMessageSend(config.AdminChannel, "!d bump is ready.")
|
|
|
|
bump = true
|
|
|
|
}
|
|
|
|
func purgeTimer(s *discordgo.Session) {
|
|
|
|
for {
|
|
|
|
runPurge(s)
|
|
|
|
saveConfig()
|
|
|
|
if time.Since(lastActiveTime) > 4*time.Hour && time.Since(startupTime) > 12*time.Hour {
|
|
|
|
log.LogInfo("Restarting.")
|
|
|
|
saveConfig()
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
time.Sleep(20 * time.Minute)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v Verification) prettyPrint() string {
|
|
|
|
ret := ""
|
|
|
|
ret += fmt.Sprintf("```%+v has marked %+v's verification as %+v\n", v.Admin, v.Username, v.Status)
|
|
|
|
ret += fmt.Sprintf("Submitted: %+v\nClosed: %+v\n", v.Submitted, v.Closed)
|
|
|
|
ret += fmt.Sprintf("Turnaround time: %+v```", time.Since(v.Submitted))
|
|
|
|
ret += fmt.Sprintf("\n%+v", v.Photo)
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func adminInteraction(s *discordgo.Session, m string) {
|
|
|
|
admin, _ := s.GuildMember(config.GuildID, m)
|
|
|
|
counter, ok := config.Stats[admin.User.ID]
|
|
|
|
if !ok {
|
|
|
|
config.Stats[admin.User.ID] = 0
|
|
|
|
} else {
|
|
|
|
config.Stats[admin.User.ID] = counter + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|