Compare commits
No commits in common. 'master' and 'Current' have entirely different histories.
27 changed files with 296 additions and 2026 deletions
Before Width: | Height: | Size: 56 KiB |
@ -1,196 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"math/rand" |
|
||||||
"net/http" |
|
||||||
"strings" |
|
||||||
"time" |
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo" |
|
||||||
"github.com/gorilla/mux" |
|
||||||
) |
|
||||||
|
|
||||||
func reqPass(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo("reqPass called.") |
|
||||||
username := r.URL.Query()["UserName"][0] |
|
||||||
log.LogInfo("reqPass username is %+v.", username) |
|
||||||
var userID string |
|
||||||
if dg == nil { |
|
||||||
log.LogError("Discord session was nill.") |
|
||||||
} |
|
||||||
g, err := dg.GuildMembers(config.GuildID, "", 1000) |
|
||||||
log.LogInfo("reqPass guild is %+v.", config.GuildID) |
|
||||||
if err == nil { |
|
||||||
for _, m := range g { |
|
||||||
if strings.EqualFold(m.Nick, username) { |
|
||||||
for _, r := range m.Roles { |
|
||||||
if r == config.AdminRole { |
|
||||||
userID = m.User.ID |
|
||||||
log.LogInfo("User ID found for %+v as %+v", username, userID) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
log.LogError("Unable to find user ID for %+v", username) |
|
||||||
} |
|
||||||
ipaddr := r.Header.Get("X-Real-IP") |
|
||||||
log.LogInfo("reqPass IP is %+v.", ipaddr) |
|
||||||
log.LogInfo(fmt.Sprintf("reqPass called:```username: %s\nip : %s```", username, ipaddr)) |
|
||||||
go sendPassword(userID, ipaddr) |
|
||||||
http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) |
|
||||||
} |
|
||||||
|
|
||||||
func tryLogin(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
session, err := store.Get(r, "2fa") |
|
||||||
if err != nil { |
|
||||||
log.LogWarn("Error opening session for 2fa store") |
|
||||||
} |
|
||||||
vars := mux.Vars(r) |
|
||||||
username := vars["username"] |
|
||||||
password := vars["password"] |
|
||||||
ip := r.Header.Get("X-Real-IP") |
|
||||||
if len(username) == 0 { |
|
||||||
username = r.FormValue("UserName") |
|
||||||
password = r.FormValue("TempPass") |
|
||||||
} |
|
||||||
access, _ := detectUser(r, "tryLogin") |
|
||||||
if !access { |
|
||||||
log.LogDebug(fmt.Sprintf("%s is attempting login", getSessionIdentifier(r))) |
|
||||||
access = usePassword(username, password, ip) |
|
||||||
if access { |
|
||||||
log.LogInfo(fmt.Sprintf("%s has successfully logged in from %s", username, ip)) |
|
||||||
log.LogDebug(fmt.Sprintf("```%+v```", session.Values)) |
|
||||||
session.Values["username"] = username |
|
||||||
session.Values["ip"] = ip |
|
||||||
session.Values["timestamp"] = fmt.Sprintf("%+v", time.Now()) |
|
||||||
err = session.Save(r, w) |
|
||||||
if err != nil { |
|
||||||
log.LogWarn(fmt.Sprintf("Error saving cookie. ```%+v```", err)) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
greetUser(w, r) |
|
||||||
} |
|
||||||
|
|
||||||
func usePassword(user string, pass string, ip string) bool { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo("%+v", toks) |
|
||||||
tok := toks[strings.ToUpper(user)] |
|
||||||
delete(toks, strings.ToUpper(user)) |
|
||||||
if tok.IP != ip { |
|
||||||
log.LogWarn(fmt.Sprintf("%s attempted to use an improper IP.", user)) |
|
||||||
return false |
|
||||||
} |
|
||||||
if tok.Password != pass { |
|
||||||
log.LogWarn(fmt.Sprintf("%s attempted to use an improper password. %s vs %s", user, tok.Password, pass)) |
|
||||||
return false |
|
||||||
} |
|
||||||
if time.Since(tok.Timestamp) > (time.Minute * 5) { |
|
||||||
log.LogWarn("%s attempted to use expired token. \n%+v\n%+v\n%+v", user, time.Since(tok.Timestamp), tok.Timestamp, time.Now()) |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
func genPassword(length int) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
rand.Seed(time.Now().UnixNano()) |
|
||||||
chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + |
|
||||||
"abcdefghijklmnopqrstuvwxyz" + |
|
||||||
"0123456789") |
|
||||||
var b strings.Builder |
|
||||||
for i := 0; i < length; i++ { |
|
||||||
b.WriteRune(chars[rand.Intn(len(chars))]) |
|
||||||
} |
|
||||||
return b.String() // E.g. "ExcbsVQs"
|
|
||||||
} |
|
||||||
func sendPassword(user string, ipaddr string) { |
|
||||||
defer log.PanicSafe() |
|
||||||
str := genPassword(15) |
|
||||||
log.LogInfo("sending password to %+v for %+v: %+v", ipaddr, user, str) |
|
||||||
m, err := dg.GuildMember(config.GuildID, user) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
now := time.Now() |
|
||||||
toks[strings.ToUpper(m.Nick)] = Tokens{ |
|
||||||
Username: user, |
|
||||||
IP: ipaddr, |
|
||||||
Password: str, |
|
||||||
Timestamp: now, |
|
||||||
} |
|
||||||
pmChann, err := dg.UserChannelCreate(user) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
dg.ChannelMessageSend(pmChann.ID, fmt.Sprintf("A temporary password was requested from %s:", ipaddr)) |
|
||||||
dg.ChannelMessageSend(pmChann.ID, fmt.Sprintf("```%s```", str)) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func getSessionIdentifier(r *http.Request) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
ipaddr := r.Header.Get("X-Real-IP") |
|
||||||
if ipaddr == "" { |
|
||||||
ipaddr = r.RemoteAddr |
|
||||||
} |
|
||||||
uri := r.URL.Path |
|
||||||
return fmt.Sprintf("%s:%s", ipaddr, uri) |
|
||||||
} |
|
||||||
|
|
||||||
func detectUser(r *http.Request, callFunc string) (bool, string) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo(fmt.Sprintf("%s called detectUser", getSessionIdentifier(r))) |
|
||||||
session, err := store.Get(r, "2fa") |
|
||||||
if err != nil { |
|
||||||
log.LogDebug(fmt.Sprintf("Unable to open 2fa session in %s", callFunc)) |
|
||||||
} |
|
||||||
if session.Values["username"] != nil { |
|
||||||
return true, fmt.Sprintf("%s", session.Values["username"]) |
|
||||||
} |
|
||||||
return false, "" |
|
||||||
} |
|
||||||
|
|
||||||
func userFromID(i string) discordgo.User { |
|
||||||
u, err := dg.GuildMember(config.GuildID, i) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
return discordgo.User{} |
|
||||||
} |
|
||||||
return *u.User |
|
||||||
} |
|
||||||
|
|
||||||
func idFromUsername(username string) string { |
|
||||||
userID := "" |
|
||||||
g, err := dg.GuildMembers(config.GuildID, "", 1000) |
|
||||||
log.LogInfo("reqPass guild is %+v.", config.GuildID) |
|
||||||
if err == nil { |
|
||||||
for _, m := range g { |
|
||||||
if strings.EqualFold(m.User.Username, username) { |
|
||||||
userID = m.User.ID |
|
||||||
log.LogInfo("User ID found for %+v as %+v", username, userID) |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
log.LogError("Unable to find user ID for %+v", username) |
|
||||||
} |
|
||||||
return userID |
|
||||||
} |
|
||||||
|
|
||||||
func isAdmin(m *discordgo.Member) bool { |
|
||||||
log.LogDebug("Checking %+v for %+v", m.Roles, config.AdminRole) |
|
||||||
for _, role := range m.Roles { |
|
||||||
if role == config.AdminRole { |
|
||||||
return true |
|
||||||
} else { |
|
||||||
log.LogDebug("%+v != %+v", role, config.AdminRole) |
|
||||||
} |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
@ -1,307 +0,0 @@ |
|||||||
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: <t:%+v:t>, expecting next bump at <t:%+v:t>", 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: <t:%+v:t>\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 <t:%+v:t>", 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 <t:%+v:t>\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 |
|
||||||
} |
|
@ -1,125 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"time" |
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo" |
|
||||||
) |
|
||||||
|
|
||||||
func ready(s *discordgo.Session, event *discordgo.Ready) { |
|
||||||
// Set the playing status.
|
|
||||||
s.UpdateGameStatus(0, fmt.Sprintf("DreamDaddy rev %+v", gitCommit)) |
|
||||||
} |
|
||||||
|
|
||||||
func guildMemberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogDebug("Member %+v has been updated", m.User.Username) |
|
||||||
for _, role := range m.Roles { |
|
||||||
if fmt.Sprintf("%+v", role) == config.MonitorRole { |
|
||||||
log.LogDebug("Role found, Monitor Role") |
|
||||||
s.ChannelMessageSend(config.MonitorChann, fmt.Sprintf("Welcome %+v, you may PM me your verification, or I will ban you in an hour!\nSay \"!rules\" in this channel, without quotes for the rules. You may private/direct message me for verification instructions.\n\nYou will not be able to read/see other channels or users until you verify.", m.User.Mention())) |
|
||||||
config.Unverified[m.User.ID] = time.Now() |
|
||||||
config.Probations[m.User.ID] = time.Now() |
|
||||||
saveConfig() |
|
||||||
return |
|
||||||
} |
|
||||||
log.LogDebug("Monitor Role not found: %+v != %+v", fmt.Sprintf("%+v", role), config.MonitorRole) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func guildMemberAdd(s *discordgo.Session, m *discordgo.GuildMemberAdd) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogDebug("Adding user to Unverified and Probations") |
|
||||||
config.Unverified[m.User.ID] = time.Now() |
|
||||||
config.Probations[m.User.ID] = time.Now() |
|
||||||
log.LogDebug("Giving user monitor role") |
|
||||||
s.GuildMemberRoleAdd(config.GuildID, m.User.ID, config.MonitorRole) |
|
||||||
log.LogDebug("Calling saveConfig") |
|
||||||
saveConfig() |
|
||||||
} |
|
||||||
|
|
||||||
func guildMemberBanned(s *discordgo.Session, m *discordgo.GuildBanAdd) { |
|
||||||
defer log.PanicSafe() |
|
||||||
for uid := range config.Probations { |
|
||||||
if m.User.Email == uid { |
|
||||||
delete(config.Probations, uid) |
|
||||||
s.ChannelMessageDelete(config.IntroChann, introMsg[uid]) |
|
||||||
} |
|
||||||
} |
|
||||||
saveConfig() |
|
||||||
} |
|
||||||
|
|
||||||
func guildMemberRemove(s *discordgo.Session, m *discordgo.GuildMemberRemove) { |
|
||||||
defer log.PanicSafe() |
|
||||||
go runPurge(s) |
|
||||||
banned := false |
|
||||||
for uid, join := range config.Probations { |
|
||||||
if time.Since(join) < 2*time.Hour { |
|
||||||
if m.User.ID == uid { |
|
||||||
banned = true |
|
||||||
s.GuildBanCreateWithReason(config.GuildID, m.User.ID, fmt.Sprintf("Left within 2 hours of joining. %+v", time.Since(join)), 0) |
|
||||||
delete(config.Probations, uid) |
|
||||||
s.ChannelMessageDelete(config.IntroChann, introMsg[uid]) |
|
||||||
} |
|
||||||
} else { |
|
||||||
delete(config.Probations, uid) |
|
||||||
s.ChannelMessageDelete(config.IntroChann, introMsg[uid]) |
|
||||||
} |
|
||||||
} |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v (@%+v) has left, ban: %+v", m.User.ID, m.User.Username, banned)) |
|
||||||
delete(config.Unverified, m.User.ID) |
|
||||||
for msg, v := range config.Verifications { |
|
||||||
if v.UserID == m.User.ID { |
|
||||||
delete(config.Verifications, msg) |
|
||||||
s.ChannelMessageDelete(config.IntroChann, introMsg[m.User.ID]) |
|
||||||
} |
|
||||||
} |
|
||||||
saveConfig() |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func readReaction(s *discordgo.Session, m *discordgo.MessageReactionAdd) { |
|
||||||
defer log.PanicSafe() |
|
||||||
if m.ChannelID != config.AdminChannel || m.UserID == s.State.User.ID { |
|
||||||
return |
|
||||||
} |
|
||||||
admin, _ := s.GuildMember(config.GuildID, m.UserID) |
|
||||||
adminInteraction(s, admin.User.ID) |
|
||||||
verification, ok := config.Verifications[m.MessageID] |
|
||||||
if !ok { |
|
||||||
return |
|
||||||
} |
|
||||||
verification.Admin = admin.User.Username |
|
||||||
verification.Closed = time.Now() |
|
||||||
user := userFromID(verification.UserID) |
|
||||||
if user.ID == "" { |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v, that user was not found, they might have left.", admin.Mention())) |
|
||||||
delete(config.Verifications, m.MessageID) |
|
||||||
return |
|
||||||
} |
|
||||||
if m.Emoji.Name == "👎" { |
|
||||||
rejectVerification(s, user) |
|
||||||
verification.Status = "Rejected" |
|
||||||
} else if m.Emoji.Name == "👍" { |
|
||||||
verifyMember(s, user) |
|
||||||
verification.Status = "Accepted" |
|
||||||
go storeVerification(verification) |
|
||||||
} else if m.Emoji.Name == "👶" { |
|
||||||
requestAge(s, user) |
|
||||||
log.LogInfo("%+v has requested ASL for user %+v.", admin.User.Username, user.Username) |
|
||||||
return |
|
||||||
} else if m.Emoji.Name == "🔄" { |
|
||||||
requestReupload(s, user) |
|
||||||
log.LogInfo("%+v has requested reupload for user %+v.", admin.User.Username, user.Username) |
|
||||||
return |
|
||||||
} else if m.Emoji.Name == "⛔" { |
|
||||||
s.GuildBanCreateWithReason(config.GuildID, user.ID, fmt.Sprintf("Underage, female, or too many failed verifications. %+v", admin.User.Username), 5) |
|
||||||
verification.Status = "Banned" |
|
||||||
} else { |
|
||||||
return |
|
||||||
} |
|
||||||
log.LogInfo("%+v", verification.prettyPrint()) |
|
||||||
delete(config.Verifications, m.MessageID) |
|
||||||
} |
|
@ -1,162 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
"time" |
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo" |
|
||||||
) |
|
||||||
|
|
||||||
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { |
|
||||||
defer log.PanicSafe() |
|
||||||
|
|
||||||
if m.Author.ID == "302050872383242240" && len(m.Embeds) > 0 { |
|
||||||
if strings.Contains(m.Embeds[0].Description, "minutes until the server can be bumped") { |
|
||||||
log.LogDebug("Failed bump detected") |
|
||||||
re := regexp.MustCompile("Please wait another (.*) minutes until the server can be bumped") |
|
||||||
match := re.FindStringSubmatch(m.Embeds[0].Description) |
|
||||||
m.Content = fmt.Sprintf("%+v bs %+v", s.State.User.Mention(), match[1]) |
|
||||||
BumpSet(BotCommand{ |
|
||||||
Message: m, |
|
||||||
Session: s, |
|
||||||
Parts: strings.Split(m.Content, " ")[2:], |
|
||||||
}) |
|
||||||
|
|
||||||
} else { |
|
||||||
go bumpTimer(s) |
|
||||||
} |
|
||||||
return |
|
||||||
|
|
||||||
} |
|
||||||
if m.Author.Bot || m.Author.ID == s.State.User.ID { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if m.GuildID == "" { |
|
||||||
handlePM(s, m) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if isAdmin(m.Member) { |
|
||||||
adminInteraction(s, m.Author.ID) |
|
||||||
} |
|
||||||
|
|
||||||
if m.ChannelID == config.MonitorChann && !isAdmin(m.Member) { |
|
||||||
if strings.Contains(m.Content, "erif") && !m.Author.Bot { |
|
||||||
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%+v send me a private message for verification.", m.Author.Mention())) |
|
||||||
} |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if m.ChannelID != config.AdminChannel { |
|
||||||
lastActiveTime = time.Now() |
|
||||||
if len(m.Attachments) > 0 { |
|
||||||
activeInteraction(s, m.Author.ID) |
|
||||||
} |
|
||||||
} |
|
||||||
if strings.Contains(m.Content, "http") { |
|
||||||
safe := false |
|
||||||
for _, testURL := range config.WhitelistURLs { |
|
||||||
if strings.Contains(m.Content, testURL) { |
|
||||||
safe = true |
|
||||||
} |
|
||||||
} |
|
||||||
if !safe { |
|
||||||
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%+v: That domain is not approved by the admins. Please contact Admins if the domain should be whitelisted.", m.Author.Mention())) |
|
||||||
s.ChannelMessageDelete(m.ChannelID, m.ID) |
|
||||||
channel, err := s.Channel(m.ChannelID) |
|
||||||
if err != nil { |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("DELETED %+v [%+v]: %+v", m.Author.Mention(), m.ChannelID, m.Content)) |
|
||||||
} else { |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("DELETED %+v [%+v]: %+v", m.Author.Mention(), channel.Name, m.Content)) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
parts := strings.Split(m.Content, " ") |
|
||||||
if strings.Contains(m.Content, s.State.User.ID) { |
|
||||||
b := BotCommand{ |
|
||||||
Session: s, |
|
||||||
Message: m, |
|
||||||
Parts: parts[2:], |
|
||||||
} |
|
||||||
log.LogDebug("%+v", b.Parts) |
|
||||||
for _, cmd := range commands { |
|
||||||
for _, keyword := range cmd.Keywords { |
|
||||||
log.LogDebug("Checking if %+v contains %+v", m.Content, keyword) |
|
||||||
if strings.Contains(parts[1], keyword) { |
|
||||||
log.LogDebug("%+v found!", keyword) |
|
||||||
b.Command = keyword |
|
||||||
if !cmd.RequiresAdmin { |
|
||||||
log.LogDebug("%+v does not require admin, running!", cmd.Name) |
|
||||||
if !cmd.Exec(b) { |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("There was an error running %+v\n%+v", cmd.Name, cmd.Help)) |
|
||||||
} else { |
|
||||||
log.LogInfo("Ran command %+v for %+v", cmd.Name, m.Author.Username) |
|
||||||
} |
|
||||||
} else { |
|
||||||
log.LogDebug("%+v does require admin, checking!", cmd.Name) |
|
||||||
if isAdmin(m.Member) { |
|
||||||
if !cmd.Exec(b) { |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("There was an error running %+v\n%+v", cmd.Name, cmd.Help)) |
|
||||||
} else { |
|
||||||
log.LogInfo("Ran command %+v for %+v", cmd.Name, m.Author.Username) |
|
||||||
} |
|
||||||
} else { |
|
||||||
log.LogInfo("%+v tried to run an admin command (%+v) but isn't an admin.", m.Author.Username, keyword) |
|
||||||
} |
|
||||||
} |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func handlePM(s *discordgo.Session, m *discordgo.MessageCreate) { |
|
||||||
defer log.PanicSafe() |
|
||||||
if strings.Contains(m.Content, "Rule") || strings.Contains(m.Content, "rule") { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "I specifically said to say \"!rules\" (without quotes) in the _unverified_ channel for the rules - this is a PM :) .") |
|
||||||
} |
|
||||||
for _, uid := range config.Verifications { |
|
||||||
user := userFromID(uid.UserID) |
|
||||||
if m.Author.ID == user.ID { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "Your verification is pending. An admin will respond to it when they are available.") |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v said: %+v", m.Author.Mention(), m.Content)) |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
if len(m.Attachments) != 1 { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "```I am a bot and this is an autoreply.\n\nUntil you send a verification, I will always say the following message:```\nYou may only send me your verification (and nothing else) to be passed to the admins (and no one else). Verification is a clear full face pic, with your pinky finger held to the corner of your mouth.") |
|
||||||
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v said: %+v", m.Author.Mention(), m.Content)) |
|
||||||
return |
|
||||||
} |
|
||||||
if strings.HasSuffix(strings.ToUpper(m.Attachments[0].ProxyURL), "HEIC") { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "You have tried to send an unsupported file (HEIC). Please try again using an image (jpeg, jpg, png, etc).") |
|
||||||
return |
|
||||||
} |
|
||||||
if strings.HasSuffix(strings.ToUpper(m.Attachments[0].ProxyURL), "MP4") { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "You have tried to send an unsupported file (MP4 Video). Please try again using an image (jpeg, jpg, png, etc).") |
|
||||||
return |
|
||||||
} |
|
||||||
if strings.HasSuffix(strings.ToUpper(m.Attachments[0].ProxyURL), "MP3") { |
|
||||||
s.ChannelMessageSend(m.ChannelID, "You have tried to send an unsupported file (MP3 Audio). Please try again using an image (jpeg, jpg, png, etc).") |
|
||||||
return |
|
||||||
} |
|
||||||
delete(config.Unverified, m.Author.ID) |
|
||||||
var v Verification |
|
||||||
v.Submitted = time.Now() |
|
||||||
v.UserID = m.Author.ID |
|
||||||
v.Username = m.Author.Username |
|
||||||
v.Photo = m.Attachments[0].ProxyURL |
|
||||||
v.Status = "Submitted" |
|
||||||
msg, _ := s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v\n%+v", v.Username, v.Photo)) |
|
||||||
config.Verifications[msg.ID] = v |
|
||||||
s.MessageReactionAdd(config.AdminChannel, msg.ID, "👎") |
|
||||||
s.MessageReactionAdd(config.AdminChannel, msg.ID, "🔄") |
|
||||||
s.MessageReactionAdd(config.AdminChannel, msg.ID, "👍") |
|
||||||
s.MessageReactionAdd(config.AdminChannel, msg.ID, "👶") |
|
||||||
s.MessageReactionAdd(config.AdminChannel, msg.ID, "⛔") |
|
||||||
} |
|
@ -1,18 +0,0 @@ |
|||||||
module git.nightmare.haus/rudi/disgord-thanos |
|
||||||
|
|
||||||
go 1.21 |
|
||||||
|
|
||||||
require ( |
|
||||||
github.com/bwmarrin/discordgo v0.27.1 |
|
||||||
github.com/gorilla/mux v1.8.0 |
|
||||||
github.com/gorilla/sessions v1.2.1 |
|
||||||
github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a |
|
||||||
) |
|
||||||
|
|
||||||
require ( |
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect |
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect |
|
||||||
golang.org/x/crypto v0.13.0 // indirect |
|
||||||
golang.org/x/sys v0.12.0 // indirect |
|
||||||
samhofi.us/x/keybase v1.0.0 // indirect |
|
||||||
) |
|
@ -1,26 +0,0 @@ |
|||||||
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= |
|
||||||
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= |
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= |
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= |
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= |
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= |
|
||||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= |
|
||||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= |
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= |
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= |
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= |
|
||||||
github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a h1:4rkaWoLCWOmra5Mw/dLAWjtDLT/+i5uTX1qhlMVL8WA= |
|
||||||
github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a/go.mod h1:s1ANCN8bF6HwwTpJLR458MFVGua9oqKKDbph/2jptL4= |
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= |
|
||||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= |
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= |
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= |
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|
||||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= |
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= |
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= |
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
|
||||||
samhofi.us/x/keybase v0.0.0-20200129212102-e05e93be9f3f/go.mod h1:fcva80IUFyWcHtV4bBSzgKg07K6Rvuvi3GtGCLNGkyE= |
|
||||||
samhofi.us/x/keybase v1.0.0 h1:ht//EtYMS/hQeZCznA1ibQ515JCKaEkvTD/tarw/9k8= |
|
||||||
samhofi.us/x/keybase v1.0.0/go.mod h1:fcva80IUFyWcHtV4bBSzgKg07K6Rvuvi3GtGCLNGkyE= |
|
@ -1,238 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"fmt" |
|
||||||
"net/http" |
|
||||||
"os" |
|
||||||
"path/filepath" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"github.com/gorilla/mux" |
|
||||||
"github.com/gorilla/sessions" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY"))) |
|
||||||
toks = make(map[string]Tokens) |
|
||||||
) |
|
||||||
|
|
||||||
func topWrapper(r *http.Request) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
headerTemplate, err := os.ReadFile("./static/header.tpl") |
|
||||||
if err != nil { |
|
||||||
log.LogError(fmt.Sprintf("Unable to open header template: ```%+v```", err)) |
|
||||||
return "" |
|
||||||
} |
|
||||||
header := string(headerTemplate) |
|
||||||
login := "Login" |
|
||||||
loggedIn, user := detectUser(r, "topWrapper") |
|
||||||
if loggedIn { |
|
||||||
login = fmt.Sprintf("Logout %s", user) |
|
||||||
} |
|
||||||
header = strings.Replace(header, "$LOGIN", login, -1) |
|
||||||
return header |
|
||||||
} |
|
||||||
|
|
||||||
func bodyWrapper(r *http.Request, template string) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
bodyTemplate, err := os.ReadFile(fmt.Sprintf("./static/%+v.tpl", template)) |
|
||||||
if err != nil { |
|
||||||
log.LogError(fmt.Sprintf("Attempt to load %s.tpl failed. ```%+v```", template, err)) |
|
||||||
return bodyWrapper(r, "404") |
|
||||||
} |
|
||||||
return string(bodyTemplate) |
|
||||||
|
|
||||||
} |
|
||||||
func pageBuilder(r *http.Request, pageName string) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
pageCode := topWrapper(r) |
|
||||||
pageCode += bodyWrapper(r, pageName) |
|
||||||
return pageCode |
|
||||||
} |
|
||||||
|
|
||||||
func greetUser(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo(fmt.Sprintf("%s called greetUser", getSessionIdentifier(r))) |
|
||||||
loggedIn, _ := detectUser(r, "Homepage") |
|
||||||
|
|
||||||
if loggedIn { |
|
||||||
bodyTemplate, _ := os.ReadFile("./static/index.html") |
|
||||||
fmt.Fprint(w, string(bodyTemplate)) |
|
||||||
} else { |
|
||||||
fmt.Fprint(w, pageBuilder(r, "home")) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func passPage(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo(fmt.Sprintf("%s called passPage", getSessionIdentifier(r))) |
|
||||||
fmt.Fprint(w, pageBuilder(r, "pass")) |
|
||||||
} |
|
||||||
func loginPage(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
log.LogInfo(fmt.Sprintf("%s called loginPage", getSessionIdentifier(r))) |
|
||||||
session, err := store.Get(r, "2fa") |
|
||||||
if err != nil { |
|
||||||
log.LogWarn("Unable to open 2fa session in loginpage") |
|
||||||
} |
|
||||||
loggedIn, _ := detectUser(r, "loginPage") |
|
||||||
if loggedIn { |
|
||||||
session.Values["username"] = nil |
|
||||||
err = session.Save(r, w) |
|
||||||
if err != nil { |
|
||||||
log.LogWarn("Error logging out from loginPage()") |
|
||||||
} |
|
||||||
fmt.Fprint(w, pageBuilder(r, "home")) |
|
||||||
return |
|
||||||
} |
|
||||||
fmt.Fprint(w, pageBuilder(r, "login")) |
|
||||||
} |
|
||||||
|
|
||||||
func notFoundPage(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
go log.LogWarn(fmt.Sprintf("%s triggered notFoundPage", getSessionIdentifier(r))) |
|
||||||
fmt.Fprint(w, topWrapper(r)) |
|
||||||
|
|
||||||
fmt.Fprint(w, card("Oops! That Page Was Not found.", |
|
||||||
"Sorry, a 404 error has occured. The requested page not found! <br><br>"+ |
|
||||||
"<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/t3otBjVZzT0\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>", |
|
||||||
"<div class=\"error-actions\"><a href=\"/\" class=\"btn btn-primary btn-lg\"><span class=\"glyphicon glyphicon-home\"></span>Take Me Home </a> <a href=\"mailto://rudi@nmare.net\" class=\"btn btn-default btn-lg\"><span class=\"glyphicon glyphicon-envelope\"></span> Contact Support </a></div>")) |
|
||||||
|
|
||||||
} |
|
||||||
func card(title string, content string, footer string) string { |
|
||||||
defer log.PanicSafe() |
|
||||||
cardTemplate, err := os.ReadFile("./static/card.tpl") |
|
||||||
if err != nil { |
|
||||||
log.LogError("Unable to open card template") |
|
||||||
return "" |
|
||||||
} |
|
||||||
cardString := string(cardTemplate) |
|
||||||
cardString = strings.Replace(cardString, "$TITLE", title, -1) |
|
||||||
cardString = strings.Replace(cardString, "$CONTENT", content, -1) |
|
||||||
cardString = strings.Replace(cardString, "$FOOTER", footer, -1) |
|
||||||
return cardString |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
func getPending(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
loggedIn, _ := detectUser(r, "getPending") |
|
||||||
if loggedIn { |
|
||||||
pending, err := json.Marshal(config.Verifications) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
fmt.Fprint(w, string(pending)) |
|
||||||
} else { |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
} |
|
||||||
func getConfig(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
loggedIn, _ := detectUser(r, "getConfig") |
|
||||||
if loggedIn { |
|
||||||
pending, err := json.Marshal(config) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
fmt.Fprint(w, string(pending)) |
|
||||||
} else { |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
} |
|
||||||
func getProbations(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
loggedIn, _ := detectUser(r, "getProbations") |
|
||||||
if loggedIn { |
|
||||||
pending, err := json.Marshal(config.Probations) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
fmt.Fprint(w, string(pending)) |
|
||||||
} else { |
|
||||||
notFoundPage(w, r) |
|
||||||
} |
|
||||||
} |
|
||||||
func getVerifications(w http.ResponseWriter, r *http.Request) { |
|
||||||
defer log.PanicSafe() |
|
||||||
loggedIn, _ := detectUser(r, "getVerifications") |
|
||||||
if !loggedIn { |
|
||||||
notFoundPage(w, r) |
|
||||||
return |
|
||||||
} |
|
||||||
var files []string |
|
||||||
root := "./verifications/" |
|
||||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { |
|
||||||
files = append(files, path) |
|
||||||
return nil |
|
||||||
}) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
var v []Verification |
|
||||||
for _, file := range files { |
|
||||||
info := strings.Split(file, "-") |
|
||||||
if len(info) < 2 { |
|
||||||
continue |
|
||||||
} |
|
||||||
var ver Verification |
|
||||||
ver.UserID = strings.Replace(info[0], "verifications/", "", -1) |
|
||||||
ver.Username = info[1] |
|
||||||
ver.Photo = file |
|
||||||
fileStat, _ := os.Stat(file) |
|
||||||
ver.Closed = fileStat.ModTime() |
|
||||||
v = append(v, ver) |
|
||||||
} |
|
||||||
verifications, err := json.Marshal(v) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
fmt.Fprint(w, string(verifications)) |
|
||||||
} |
|
||||||
|
|
||||||
func getUser(w http.ResponseWriter, r *http.Request) { |
|
||||||
loggedIn, _ := detectUser(r, "getVerifications") |
|
||||||
if !loggedIn { |
|
||||||
notFoundPage(w, r) |
|
||||||
return |
|
||||||
} |
|
||||||
vars := mux.Vars(r) |
|
||||||
username := vars["userID"] |
|
||||||
if len(username) == 0 { |
|
||||||
username = r.FormValue("userID") |
|
||||||
} |
|
||||||
m, err := dg.GuildMember(config.GuildID, username) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
ret, err := json.Marshal(m) |
|
||||||
if err != nil { |
|
||||||
log.LogErrorType(err) |
|
||||||
} |
|
||||||
fmt.Fprint(w, string(ret)) |
|
||||||
} |
|
||||||
|
|
||||||
func runWeb() { |
|
||||||
defer log.PanicSafe() |
|
||||||
router := mux.NewRouter().StrictSlash(true) |
|
||||||
log.LogInfo("Adding HandleFuncs to router") |
|
||||||
router.NotFoundHandler = http.HandlerFunc(notFoundPage) |
|
||||||
router.HandleFunc("/pass", passPage) |
|
||||||
router.HandleFunc("/login", loginPage) |
|
||||||
router.HandleFunc("/api/login", tryLogin) |
|
||||||
router.HandleFunc("/api/config", getConfig) |
|
||||||
router.HandleFunc("/api/pending", getPending) |
|
||||||
router.HandleFunc("/api/verifications", getVerifications) |
|
||||||
router.HandleFunc("/api/probations", getProbations) |
|
||||||
router.HandleFunc("/api/passreq", reqPass) |
|
||||||
router.HandleFunc("/api/user", getUser) |
|
||||||
router.HandleFunc("/", greetUser) |
|
||||||
router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))) |
|
||||||
router.PathPrefix("/verifications/").Handler(http.StripPrefix("/verifications/", http.FileServer(http.Dir("./verifications")))) |
|
||||||
log.LogInfo("Starting server") |
|
||||||
log.LogErrorType(http.ListenAndServe(":8080", router)) |
|
||||||
} |
|
@ -1,21 +0,0 @@ |
|||||||
<div class="container"> |
|
||||||
<div class="row"> |
|
||||||
<div class="col-md-12"> |
|
||||||
<div class="error-template"> |
|
||||||
<h1> |
|
||||||
Oops!</h1><br> |
|
||||||
<h2> |
|
||||||
404 Not Found</h2> |
|
||||||
<div class="error-details"> |
|
||||||
Sorry, an error has occured, Requested page not found! |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
<div class="error-actions"> |
|
||||||
<a href="/" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> |
|
||||||
Take Me Home </a> <a href="mailto://rudi@nmare.net" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact Support </a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
</div> |
|
@ -1,21 +0,0 @@ |
|||||||
<div class="container"> |
|
||||||
<div class="row"> |
|
||||||
<div class="col-md-12"> |
|
||||||
<div class="error-template"> |
|
||||||
<h1> |
|
||||||
Oops!</h1><br> |
|
||||||
<h2>Something has gone HORRIBLY wrong! Congrats!</h2> |
|
||||||
<div class="error-details"> |
|
||||||
Not really sorry, but an error has occured. 500 means something went wrong on the server side, but.. Let's be honest. It was really a user malfunction. |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
<div class="error-actions"> |
|
||||||
<a href="/" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> |
|
||||||
Take Me Home </a> <a href="mailto://rudi@nmare.net" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact Support </a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/t3otBjVZzT0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> |
|
||||||
</div> |
|
@ -1,149 +0,0 @@ |
|||||||
|
|
||||||
// Get the modal
|
|
||||||
const modal = document.getElementById("myModal"); |
|
||||||
|
|
||||||
// Get the button that opens the modal
|
|
||||||
const btn = document.getElementById("myBtn"); |
|
||||||
|
|
||||||
// Get the <span> element that closes the modal
|
|
||||||
const span = document.getElementsByClassName("close")[0]; |
|
||||||
var mode = new URLSearchParams(window.location.search).get("mode"); |
|
||||||
|
|
||||||
const archiveLink = document.querySelector("#archive-link") |
|
||||||
const pendingLink = document.querySelector("#pending-link") |
|
||||||
const statusLink = document.querySelector("#status-link") |
|
||||||
function handleForm(event) { event.preventDefault(); } |
|
||||||
|
|
||||||
function main() { |
|
||||||
archiveLink.classList.remove("active"); |
|
||||||
pendingLink.classList.remove("active"); |
|
||||||
statusLink.classList.remove("active"); |
|
||||||
switch (mode) { |
|
||||||
case "status": |
|
||||||
statusLink.classList.add("active"); |
|
||||||
return statusPage(); |
|
||||||
case "pending": |
|
||||||
pendingLink.classList.add("active"); |
|
||||||
break; |
|
||||||
case "verifications": |
|
||||||
archiveLink.classList.add("active"); |
|
||||||
break; |
|
||||||
default: |
|
||||||
console.log("No mode"); |
|
||||||
mode = "verifications" |
|
||||||
archiveLink.classList.add("active"); |
|
||||||
break; |
|
||||||
} |
|
||||||
document.getElementById("main-app").innerHTML = ''; |
|
||||||
fetch(`https://thanos.nightmare.haus/api/${mode}`) |
|
||||||
.then(response => response.json()) |
|
||||||
.then(data => processData(data)); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
function statusPage() { |
|
||||||
document.getElementById("main-app").innerHTML = ''; |
|
||||||
fetch(`https://thanos.nightmare.haus/api/config`) |
|
||||||
.then(response => response.json()) |
|
||||||
.then(data => { |
|
||||||
var node = document.createElement("config-status"); |
|
||||||
|
|
||||||
var upTime = document.createElement("div"); |
|
||||||
upTime.setAttribute("slot", "uptime"); |
|
||||||
upTime.innerText = data.Uptime; |
|
||||||
node.appendChild(upTime); |
|
||||||
|
|
||||||
var bumpTime = document.createElement("div"); |
|
||||||
bumpTime.setAttribute("slot", "lastbump") |
|
||||||
bumpTime.innerText = new Date(data.BumpTime).toLocaleString(); |
|
||||||
node.appendChild(bumpTime); |
|
||||||
|
|
||||||
node.setData(data); |
|
||||||
|
|
||||||
document.getElementById("main-app").appendChild(node); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
function searchPage() { |
|
||||||
var search = document.getElementById("search-bar"); |
|
||||||
fetch('https://thanos.nightmare.haus/api/verifications') |
|
||||||
.then(response => response.json()) |
|
||||||
.then(data => { |
|
||||||
var searchData = []; |
|
||||||
for (user of data) { |
|
||||||
var match = false; |
|
||||||
|
|
||||||
if (user.Username.toLowerCase().includes(search.value.toLowerCase())) { |
|
||||||
match = true; |
|
||||||
} |
|
||||||
if (new Date(user.Closed).toLocaleString().includes(search.value)) { |
|
||||||
match = true; |
|
||||||
} |
|
||||||
if (user.UserID.includes(search.value)) { |
|
||||||
match = true; |
|
||||||
} |
|
||||||
if (match) { |
|
||||||
searchData.push(user); |
|
||||||
} |
|
||||||
} |
|
||||||
processData(searchData); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
function processData(data) { |
|
||||||
document.getElementById("main-app").innerHTML = ''; |
|
||||||
if (data.length == 0) { |
|
||||||
alert("No data."); |
|
||||||
return; |
|
||||||
} |
|
||||||
data = Object.values(data); |
|
||||||
for (user of data) { |
|
||||||
var node = document.createElement("user-card"); |
|
||||||
var nameSlot = document.createElement("div"); |
|
||||||
nameSlot.setAttribute("slot", "username"); |
|
||||||
nameSlot.innerText = user.Username; |
|
||||||
node.appendChild(nameSlot); |
|
||||||
|
|
||||||
var joinDate = document.createElement("div"); |
|
||||||
joinDate.setAttribute("slot", "join-date"); |
|
||||||
joinDate.innerText = mode == "pending" ? new Date(user.Submitted).toLocaleString() : new Date(user.Closed).toLocaleString(); |
|
||||||
node.appendChild(joinDate); |
|
||||||
|
|
||||||
var discordSlot = document.createElement("div"); |
|
||||||
discordSlot.setAttribute("slot", "discord-id"); |
|
||||||
discordSlot.innerText = user.UserID; |
|
||||||
node.appendChild(discordSlot); |
|
||||||
|
|
||||||
var picSlot = document.createElement("div"); |
|
||||||
picSlot.setAttribute("slot", "pic-link"); |
|
||||||
var aNode = document.createElement("a"); |
|
||||||
|
|
||||||
aNode.setAttribute("href", mode == "pending" ? user.Photo : `https://thanos.nightmare.haus/${user.Photo}`); |
|
||||||
aNode.innerText = "Verification Photo"; |
|
||||||
|
|
||||||
picSlot.appendChild(aNode); |
|
||||||
node.appendChild(picSlot); |
|
||||||
document.getElementById("main-app").appendChild(node); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// When the user clicks on <span> (x), close the modal
|
|
||||||
span.onclick = function () { |
|
||||||
modal.style.display = "none"; |
|
||||||
} |
|
||||||
|
|
||||||
// When the user clicks anywhere outside of the modal, close it
|
|
||||||
window.onclick = function (event) { |
|
||||||
if (event.target == modal) { |
|
||||||
modal.style.display = "none"; |
|
||||||
} |
|
||||||
} |
|
||||||
var form = document.getElementById("search-form"); |
|
||||||
form.addEventListener('submit', handleForm); |
|
||||||
|
|
||||||
main(); |
|
@ -1,11 +0,0 @@ |
|||||||
<br><br> |
|
||||||
<div class="container h-100 d-flex justify-content-center align-items-center"> |
|
||||||
|
|
||||||
<div class="card" style="width: 50rem;"> |
|
||||||
<div class="card-body col"> |
|
||||||
<h2 class="card-title">$TITLE</h1> |
|
||||||
<p class="card-text">$CONTENT</p> |
|
||||||
<p class="card-text">$FOOTER</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
@ -1,210 +0,0 @@ |
|||||||
const basicCard = document.createElement('basic-card'); |
|
||||||
const configStatus = document.createElement('status'); |
|
||||||
const style = ` |
|
||||||
<style> |
|
||||||
.column { |
|
||||||
float: left; |
|
||||||
width: 24%; |
|
||||||
height: 100%; |
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.137); |
|
||||||
border-radius: 3%; |
|
||||||
transition: 0.3s; |
|
||||||
margin: 15px 3.33%; |
|
||||||
padding: 12px 16px; |
|
||||||
background-color: #282c34; |
|
||||||
color: #FFFFFF; |
|
||||||
} |
|
||||||
|
|
||||||
.column:hover { |
|
||||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.795); |
|
||||||
} |
|
||||||
|
|
||||||
/* Clear floats after the columns */ |
|
||||||
.row { |
|
||||||
content: ""; |
|
||||||
clear: both; |
|
||||||
display: flex; |
|
||||||
flex-wrap: wrap; |
|
||||||
} |
|
||||||
p { |
|
||||||
text-align: center; |
|
||||||
} |
|
||||||
a { |
|
||||||
text-align: center; |
|
||||||
color: white; |
|
||||||
} |
|
||||||
.card { |
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.137); |
|
||||||
border-radius: 3%; |
|
||||||
transition: 0.3s; |
|
||||||
position: relative; |
|
||||||
width: 250px; |
|
||||||
height: 200px; |
|
||||||
padding: 5px; |
|
||||||
background-color: #282c34; |
|
||||||
color: #FFFFFF; |
|
||||||
} |
|
||||||
.card:hover { |
|
||||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.795); |
|
||||||
} |
|
||||||
.container { |
|
||||||
padding: 6px 16px; |
|
||||||
} |
|
||||||
label{ |
|
||||||
display: inline; |
|
||||||
float: left; |
|
||||||
clear: left; |
|
||||||
width: 250px; |
|
||||||
text-align: left; |
|
||||||
} |
|
||||||
input { |
|
||||||
display: inline; |
|
||||||
float: right; |
|
||||||
} |
|
||||||
</style> |
|
||||||
`;
|
|
||||||
|
|
||||||
basicCard.innerHTML = ` |
|
||||||
${style} |
|
||||||
<div id="card-container" class="container"> |
|
||||||
<div class="card"> |
|
||||||
<h4><p><slot name="username" /></p></h4> |
|
||||||
<div> |
|
||||||
<p><slot name="join-date" /></p> |
|
||||||
<p><slot id="discord-id" name="discord-id" /></p> |
|
||||||
<p><slot id="pic-link" name="pic-link" /></p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
`;
|
|
||||||
|
|
||||||
configStatus.innerHTML = ` |
|
||||||
${style} |
|
||||||
<div class="row"> |
|
||||||
<div class="column"> |
|
||||||
<h4><p>Status</p></h4> |
|
||||||
<p>Uptime: <slot name="uptime" /></p> |
|
||||||
<p>Last Bump was <slot name="lastbump" /></p> |
|
||||||
<p>by <slot id="lastbumper" name="lastbumper" /></p> |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
<div class="column"> |
|
||||||
<h4><p>Config</p></h4> |
|
||||||
<form> |
|
||||||
<label for="Guild">Guild: </label> |
|
||||||
<input type="text" id="Guild" name="Guild" readonly/> |
|
||||||
<label for="AdminChannel">Admin Channel: </label> |
|
||||||
<input type="select" id="AdminChannel" name="AdminChannel"/> |
|
||||||
<label for="AdminRole">Admin Role: </label> |
|
||||||
<input type="select" id="AdminRole" name="AdminRole"/> |
|
||||||
<label for="MonitorChannel">Monitor Channel: </label> |
|
||||||
<input type="select" id="MonitorChannel" name="MonitorChannel"/> |
|
||||||
<label for="MonitorRole">Monitor Role: </label> |
|
||||||
<input type="select" id="MonitorRole" name="MonitorRole"/> |
|
||||||
<label for="IntroChannel">Intro Channel: </label> |
|
||||||
<input type="select" id="IntroChannel" name="IntroChannel"/> |
|
||||||
<label for="VerifiedRole">Verified Role: </label> |
|
||||||
<input type="select" id="VerifiedRole" name="VerifiedRole"/> |
|
||||||
<label for="OutFile">Logging OutFile: </label> |
|
||||||
<input type="text" id="OutFile" name="OutFile" /> |
|
||||||
<label for="KBTeam">KB Team: </label> |
|
||||||
<input type="text" id="KBTeam" name="KBTeam" /> |
|
||||||
<label for="KBChann">KB Channel: </label> |
|
||||||
<input type="text" id="KBChann" name="KBChann" /> |
|
||||||
<label for="level">Logging Level: </label> |
|
||||||
<input type="number" id="Level" name="Level" /> |
|
||||||
<label for="ProgName">Program Name: </label> |
|
||||||
<input type="text" id="ProgName" name="ProgName" /> |
|
||||||
<label for="UseStdout">Use stdout: </label> |
|
||||||
<input type="checkbox" id="UseStdout" name="UseStdout"/> |
|
||||||
<label for="submitchanges"></label> |
|
||||||
<input style="width: 100%;" type="submit" id="submitchanges" name="submitchanges" onClick="alert('Post blocked.')"> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
<br> |
|
||||||
<div id="admin-stats" class="column"> |
|
||||||
<h4><p>Admin Stats</p></h4> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
`;
|
|
||||||
|
|
||||||
class ConfigStatusClass extends HTMLElement { |
|
||||||
constructor() { |
|
||||||
super(); |
|
||||||
this.attachShadow({ mode: 'open' }); |
|
||||||
this.shadowRoot.appendChild(configStatus.cloneNode(true)); |
|
||||||
} |
|
||||||
async setData(data) { |
|
||||||
this.shadowRoot.querySelector("#submitchanges").addEventListener('submit', handleForm); |
|
||||||
this.shadowRoot.querySelector("#Guild").value = data.GuildID; |
|
||||||
this.shadowRoot.querySelector("#AdminChannel").value = data.AdminChannel; |
|
||||||
this.shadowRoot.querySelector("#AdminRole").value = data.AdminRole; |
|
||||||
this.shadowRoot.querySelector("#MonitorChannel").value = data.MonitorChann; |
|
||||||
this.shadowRoot.querySelector("#MonitorRole").value = data.MonitorRole; |
|
||||||
this.shadowRoot.querySelector("#IntroChannel").value = data.IntroChann; |
|
||||||
this.shadowRoot.querySelector("#VerifiedRole").value = data.VerifiedRole; |
|
||||||
this.shadowRoot.querySelector("#OutFile").value = data.LogOpts.OutFile; |
|
||||||
this.shadowRoot.querySelector("#KBTeam").value = data.LogOpts.KBTeam; |
|
||||||
this.shadowRoot.querySelector("#KBChann").value = data.LogOpts.KBChann; |
|
||||||
this.shadowRoot.querySelector("#Level").value = data.LogOpts.Level; |
|
||||||
this.shadowRoot.querySelector("#ProgName").value = data.LogOpts.ProgName; |
|
||||||
this.shadowRoot.querySelector("#UseStdout").checked = data.LogOpts.UseStdout == "true"; |
|
||||||
fetch('https://thanos.nightmare.haus/api/user?userID=' + data.LastBumper) |
|
||||||
.then(response => response.json()) |
|
||||||
.then(userData => { |
|
||||||
this.shadowRoot.querySelector("#lastbumper").innerHTML = userData.user.username; |
|
||||||
}); |
|
||||||
this.loadStats(data.Stats) |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
async loadStats(data) { |
|
||||||
var shadowRoot = this.shadowRoot; |
|
||||||
Object.keys(data).forEach(function(uid) { |
|
||||||
var score = data[uid]; |
|
||||||
fetch('https://thanos.nightmare.haus/api/user?userID=' + uid) |
|
||||||
.then(response => response.json()) |
|
||||||
.then(userData => { |
|
||||||
var stats = shadowRoot.querySelector("#admin-stats"); |
|
||||||
var userName = document.createElement("p"); |
|
||||||
userName.innerText = userData.user.username + ": " + score; |
|
||||||
stats.appendChild(userName); |
|
||||||
}); |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
class UserCard extends HTMLElement { |
|
||||||
constructor() { |
|
||||||
super(); |
|
||||||
this.attachShadow({ mode: 'open' }); |
|
||||||
this.shadowRoot.appendChild(basicCard.cloneNode(true)); |
|
||||||
} |
|
||||||
connectedCallback() { |
|
||||||
this.shadowRoot.querySelector('#card-container').addEventListener('click', () => this.showModal()); |
|
||||||
} |
|
||||||
|
|
||||||
showModal() { |
|
||||||
const userID = this.shadowRoot.querySelector('#discord-id').assignedNodes()[0].textContent; |
|
||||||
const userPic = this.shadowRoot.querySelector("#pic-link").assignedNodes()[0].querySelector("a").getAttribute("href"); |
|
||||||
fetch('https://thanos.nightmare.haus/api/user?userID=' + userID) |
|
||||||
.then(response => response.json()) |
|
||||||
.then(data => { |
|
||||||
if (data === undefined || data === null) { |
|
||||||
alert("User not found."); |
|
||||||
return; |
|
||||||
} |
|
||||||
document.querySelector("#myModal").style.display = "block"; |
|
||||||
document.querySelector('#modal-join').textContent = new Date(data.joined_at).toLocaleString(); |
|
||||||
document.querySelector('#modal-userID').textContent = data.user.username; |
|
||||||
document.querySelector('#modal-avatar').src = `https://cdn.discordapp.com/avatars/${data.user.id}/${data.user.avatar}.png?size=256`; |
|
||||||
document.querySelector('#modal-verification').src = userPic; |
|
||||||
document.querySelector('#modal-verification').style = "max-height: 500px;"; |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
window.customElements.define('user-card', UserCard); |
|
||||||
window.customElements.define('config-status', ConfigStatusClass); |
|
@ -1,44 +0,0 @@ |
|||||||
<!DOCTYPE html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<title>Thanos</title> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> |
|
||||||
<link rel="icon" type="image/png" href="https://lh6.googleusercontent.com/BvczCCYhJUsKIs3dsowl1vuvnBtCGSDcMDekt5PehwQk3cQLfHkEn80cR3IuMxUFmd5Sh_UQ=w16383"> |
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> |
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script> |
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script> |
|
||||||
<link href="/static/css/main.5c7015b9.chunk.css" rel="stylesheet"> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Navigation --> |
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top"> |
|
||||||
<div class="container"> |
|
||||||
<a class="navbar-brand" href="/"> |
|
||||||
<img src="" alt=""> |
|
||||||
</a> |
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> |
|
||||||
<span class="navbar-toggler-icon"></span> |
|
||||||
</button> |
|
||||||
<div class="collapse navbar-collapse" id="navbarResponsive"> |
|
||||||
<ul class="navbar-nav ml-auto"> |
|
||||||
<li class="nav-item active"> |
|
||||||
<a class="nav-link" href="/">Home |
|
||||||
<span class="sr-only">(current)</span> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li class="nav-item"> |
|
||||||
<a class="nav-link" href="/pass">Request Token</a> |
|
||||||
</li> |
|
||||||
<li class="nav-item"> |
|
||||||
<a class="nav-link" href="/login">$LOGIN</a> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</nav> |
|
||||||
|
|
||||||
|
|
||||||
</head> |
|
@ -1,17 +0,0 @@ |
|||||||
<br><br> |
|
||||||
<div class="container h-100 d-flex justify-content-center align-items-center"> |
|
||||||
<div id="react_app"></div> |
|
||||||
|
|
||||||
<div class="container h-100 d-flex justify-content-center align-items-center"> |
|
||||||
<div class="card" style="width: 50rem;"> |
|
||||||
<div class="card-body col"> |
|
||||||
<h2 class="card-title">Cookie Policy</h1> |
|
||||||
<p class="card-text">What website doesn't use cookies nowadays?</p> |
|
||||||
<p class="card-text">This website does not use any 3rd party cookies. All cookies are encrypted and |
|
||||||
only used by this website. </p> |
|
||||||
<p class="card-text">If you are actually reading this, chances are your data isn't valuable enough |
|
||||||
for me to care about tracking you.</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
</div> |
|
@ -1,73 +0,0 @@ |
|||||||
body { |
|
||||||
margin: 0; |
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', |
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', |
|
||||||
sans-serif; |
|
||||||
-webkit-font-smoothing: antialiased; |
|
||||||
-moz-osx-font-smoothing: grayscale; |
|
||||||
} |
|
||||||
|
|
||||||
code { |
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', |
|
||||||
monospace; |
|
||||||
} |
|
||||||
.card { |
|
||||||
/* Add shadows to create the "card" effect */ |
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.137); |
|
||||||
border-radius: 3%; |
|
||||||
transition: 0.3s; |
|
||||||
position: relative; |
|
||||||
width: 300px; |
|
||||||
height: 200px; |
|
||||||
padding: 10px; |
|
||||||
background-color: #282c34; |
|
||||||
color: #FFFFFF; |
|
||||||
} |
|
||||||
|
|
||||||
/* On mouse-over, add a deeper shadow */ |
|
||||||
.card:hover { |
|
||||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.795); |
|
||||||
} |
|
||||||
|
|
||||||
/* Add some padding inside the card container */ |
|
||||||
.container { |
|
||||||
padding: 6px 16px; |
|
||||||
} |
|
||||||
|
|
||||||
/* The Modal (background) */ |
|
||||||
.modal { |
|
||||||
display: none; /* Hidden by default */ |
|
||||||
position: fixed; /* Stay in place */ |
|
||||||
z-index: 1; /* Sit on top */ |
|
||||||
left: 0; |
|
||||||
top: 0; |
|
||||||
width: 100%; /* Full width */ |
|
||||||
height: 100%; /* Full height */ |
|
||||||
overflow: auto; /* Enable scroll if needed */ |
|
||||||
background-color: rgb(0,0,0); /* Fallback color */ |
|
||||||
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ |
|
||||||
} |
|
||||||
|
|
||||||
/* Modal Content/Box */ |
|
||||||
.modal-content { |
|
||||||
background-color: #282c34; |
|
||||||
margin: 15% auto; /* 15% from the top and centered */ |
|
||||||
padding: 20px; |
|
||||||
border: 1px solid #888; |
|
||||||
width: 80%; /* Could be more or less, depending on screen size */ |
|
||||||
color: white; |
|
||||||
} |
|
||||||
|
|
||||||
.close { |
|
||||||
color: #aaa; |
|
||||||
float: right; |
|
||||||
font-size: 28px; |
|
||||||
font-weight: bold; |
|
||||||
} |
|
||||||
|
|
||||||
.close:hover, |
|
||||||
.close:focus { |
|
||||||
color: black; |
|
||||||
text-decoration: none; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
@ -1,91 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html lang="en"> |
|
||||||
|
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
|
||||||
<meta name="description" content="JavaScript web interface for ThanOS API"> |
|
||||||
<meta name="author" content="rudi@nightmare.haus"> |
|
||||||
<link rel="icon" href="https://cdn.discordapp.com/avatars/688025671968096341/7ad6b70b550cec8fb9dba7cec489838e.png?size=32"> |
|
||||||
|
|
||||||
<title>Thanos2</title> |
|
||||||
<!-- Bootstrap core CSS --> |
|
||||||
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet"> |
|
||||||
|
|
||||||
<!-- Custom styles for this template --> |
|
||||||
<link href="https://getbootstrap.com/docs/4.0/examples/starter-template/starter-template.css" rel="stylesheet"> |
|
||||||
|
|
||||||
<!-- My imports --> |
|
||||||
<link href="./static/index.css" rel="stylesheet"> |
|
||||||
|
|
||||||
<!-- End of my imports --> |
|
||||||
|
|
||||||
</head> |
|
||||||
|
|
||||||
<body> |
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> |
|
||||||
<a class="navbar-brand" href="https://git.nightmare.haus/rudi/disgord-Thanos">ThanOS</a> |
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" |
|
||||||
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> |
|
||||||
<span class="navbar-toggler-icon"></span> |
|
||||||
</button> |
|
||||||
|
|
||||||
|
|
||||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault"> |
|
||||||
<ul class="navbar-nav mr-auto"> |
|
||||||
<li class="nav-item active" id="archive-link"> |
|
||||||
<a class="nav-link" href="?mode=verifications">Archive <span class="sr-only">(current)</span></a> |
|
||||||
</li> |
|
||||||
<li class="nav-item" id="pending-link"> |
|
||||||
<a class="nav-link" href="?mode=pending">Pending</a> |
|
||||||
</li> |
|
||||||
<li class="nav-item" id="status-link"> |
|
||||||
<a class="nav-link disabled" href="?mode=status">Status</a> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
<form class="form-inline my-2 my-lg-0" id="search-form"> |
|
||||||
<input class="form-control mr-sm-2" id="search-bar" type="text" placeholder="Search Verifications" |
|
||||||
aria-label="Search"> |
|
||||||
<button class="btn btn-outline-success my-2 my-sm-0" id="search-button" type="submit" onclick="searchPage()">Search</button> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</nav> |
|
||||||
<!-- The Modal --> |
|
||||||
<div id="myModal" class="modal"> |
|
||||||
|
|
||||||
<!-- Modal content --> |
|
||||||
<div class="modal-content"> |
|
||||||
<div class="container"> |
|
||||||
<span class="close">×</span> |
|
||||||
<div class="row"> |
|
||||||
<div class="col-sm"> |
|
||||||
<img id="modal-avatar" alt="Avatar"> |
|
||||||
<p id="modal-join"></p> |
|
||||||
<p id="modal-userID"></p> |
|
||||||
</div> |
|
||||||
<div class="col-sm"> |
|
||||||
<img id="modal-verification" alt="Avatar" style="width: 100%;"> |
|
||||||
</div> |
|
||||||
|
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
</div> |
|
||||||
<div id="main-app" style="display: flex; flex-wrap: wrap;"> |
|
||||||
</div> |
|
||||||
<script src="./static/components.js"></script> |
|
||||||
<script src="./static/app.js"></script> |
|
||||||
<!-- Bootstrap core JavaScript |
|
||||||
================================================== --> |
|
||||||
<!-- Placed at the end of the document so the pages load faster --> |
|
||||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" |
|
||||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" |
|
||||||
crossorigin="anonymous"></script> |
|
||||||
<script>window.jQuery || document.write('<script src="https://getbootstrap.com/docs/4.0/assets/js/vendor/jquery-slim.min.js"><\/script>')</script> |
|
||||||
<script src="https://getbootstrap.com/docs/4.0/assets/js/vendor/popper.min.js"></script> |
|
||||||
<script src="https://getbootstrap.com/docs/4.0/dist/js/bootstrap.min.js"></script> |
|
||||||
</body> |
|
||||||
|
|
||||||
</html> |
|
@ -1,8 +0,0 @@ |
|||||||
|
|
||||||
<div id="react_app"></div> |
|
||||||
<div class="container h-100 d-flex justify-content-center align-items-center"> |
|
||||||
<script>!function (e) { function t(t) { for (var n, l, a = t[0], f = t[1], i = t[2], c = 0, s = []; c < a.length; c++)l = a[c], Object.prototype.hasOwnProperty.call(o, l) && o[l] && s.push(o[l][0]), o[l] = 0; for (n in f) Object.prototype.hasOwnProperty.call(f, n) && (e[n] = f[n]); for (p && p(t); s.length;)s.shift()(); return u.push.apply(u, i || []), r() } function r() { for (var e, t = 0; t < u.length; t++) { for (var r = u[t], n = !0, a = 1; a < r.length; a++) { var f = r[a]; 0 !== o[f] && (n = !1) } n && (u.splice(t--, 1), e = l(l.s = r[0])) } return e } var n = {}, o = { 1: 0 }, u = []; function l(t) { if (n[t]) return n[t].exports; var r = n[t] = { i: t, l: !1, exports: {} }; return e[t].call(r.exports, r, r.exports, l), r.l = !0, r.exports } l.m = e, l.c = n, l.d = function (e, t, r) { l.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: r }) }, l.r = function (e) { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }) }, l.t = function (e, t) { if (1 & t && (e = l(e)), 8 & t) return e; if (4 & t && "object" == typeof e && e && e.__esModule) return e; var r = Object.create(null); if (l.r(r), Object.defineProperty(r, "default", { enumerable: !0, value: e }), 2 & t && "string" != typeof e) for (var n in e) l.d(r, n, function (t) { return e[t] }.bind(null, n)); return r }, l.n = function (e) { var t = e && e.__esModule ? function () { return e.default } : function () { return e }; return l.d(t, "a", t), t }, l.o = function (e, t) { return Object.prototype.hasOwnProperty.call(e, t) }, l.p = "/"; var a = this.webpackJsonpthanos = this.webpackJsonpthanos || [], f = a.push.bind(a); a.push = t, a = a.slice(); for (var i = 0; i < a.length; i++)t(a[i]); var p = f; r() }([])</script> |
|
||||||
<script src="/static/js/2.55237e37.chunk.js"></script> |
|
||||||
<script src="/static/js/main.a24cc14e.chunk.js"></script> |
|
||||||
</div> |
|
||||||
</body> |
|
@ -1,31 +0,0 @@ |
|||||||
<div class="container-fluid"> |
|
||||||
<div class="row no-gutter"> |
|
||||||
<div class="d-none d-md-flex col-md-4 col-lg-6 bg-image"></div> |
|
||||||
<div class="col-md-8 col-lg-6"> |
|
||||||
<div class="login d-flex align-items-center py-5"> |
|
||||||
<div class="container"> |
|
||||||
<div class="row"> |
|
||||||
<div class="col-md-9 col-lg-8 mx-auto"> |
|
||||||
<h3 class="login-heading mb-4">Thanos OTP Login</h3> |
|
||||||
<form action="/api/login"> |
|
||||||
<div class="form-label-group"> |
|
||||||
<input type="text" name="UserName" id="Username" class="form-control" placeholder="Username" required autofocus> |
|
||||||
<label for="inputEmail">Username</label> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="form-label-group"> |
|
||||||
<input type="password" name="TempPass" id="TempPassword" class="form-control" placeholder="Do Not Use Your Discord Password" required> |
|
||||||
<label for="inputPassword">Temporary Password</label> |
|
||||||
</div> |
|
||||||
|
|
||||||
<button class="btn btn-lg btn-primary btn-block btn-login text-uppercase font-weight-bold mb-2" type="submit">Sign in</button> |
|
||||||
<div class="text-center"> |
|
||||||
<a class="small" href="/pass">Need to request a password?</a></div> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
@ -1,31 +0,0 @@ |
|||||||
<body> |
|
||||||
<br><br> |
|
||||||
<div class="row h-100 justify-content-center align-items-center"> |
|
||||||
<div class="card"> |
|
||||||
<div class="container"> |
|
||||||
<form action="/api/passreq"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<td> |
|
||||||
Discord User: |
|
||||||
</td> |
|
||||||
<td> |
|
||||||
<input type="text" name="UserName" value=""> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td> |
|
||||||
</td> |
|
||||||
<td> |
|
||||||
<input type="submit" value="Submit" class="btn btn-primary" style="float: right;"> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</form> |
|
||||||
|
|
||||||
<p>Click the "Submit" button and a temporary password will be sent to the Discord User.</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -1,51 +0,0 @@ |
|||||||
package tools |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"os/signal" |
|
||||||
"syscall" |
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
token string |
|
||||||
dg *discordgo.Session |
|
||||||
guild string |
|
||||||
) |
|
||||||
|
|
||||||
func init() { |
|
||||||
flag.StringVar(&token, "t", "", "Bot Token") |
|
||||||
flag.StringVar(&guild, "g", "", "Guild ID") |
|
||||||
flag.Parse() |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
if token == "" { |
|
||||||
fmt.Printf("No token provided. Please run: disgord-thanos -t <bot token>") |
|
||||||
} |
|
||||||
dg, _ = discordgo.New("Bot " + token) |
|
||||||
dg.AddHandler(messageCreate) |
|
||||||
_ = dg.Open() |
|
||||||
sc := make(chan os.Signal, 1) |
|
||||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) |
|
||||||
<-sc |
|
||||||
dg.Close() |
|
||||||
} |
|
||||||
|
|
||||||
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { |
|
||||||
if guild != "" { |
|
||||||
if m.GuildID != guild { |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
jsonMsg, err := json.Marshal(m) |
|
||||||
if err != nil { |
|
||||||
jsonMsg = append(jsonMsg, '0') |
|
||||||
} |
|
||||||
log.Printf("----------\n%+v: %+v\n\n%+v\n------------------------------\n\n", m.Author.Username, m.Content, string(jsonMsg)) |
|
||||||
} |
|
@ -1,37 +0,0 @@ |
|||||||
package tools |
|
||||||
|
|
||||||
import ( |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
token string |
|
||||||
dg *discordgo.Session |
|
||||||
guild string |
|
||||||
) |
|
||||||
|
|
||||||
func init() { |
|
||||||
flag.StringVar(&token, "t", "", "Bot Token") |
|
||||||
flag.StringVar(&guild, "g", "", "Guild ID") |
|
||||||
flag.Parse() |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
if token == "" { |
|
||||||
fmt.Printf("No token provided. Please run: disgord-thanos -t <bot token>") |
|
||||||
} |
|
||||||
dg, _ = discordgo.New("Bot " + token) |
|
||||||
_ = dg.Open() |
|
||||||
runFunction() |
|
||||||
dg.Close() |
|
||||||
} |
|
||||||
|
|
||||||
func runFunction() { |
|
||||||
bans, _ := dg.GuildBans(guild) |
|
||||||
for _, v := range bans { |
|
||||||
dg.GuildBanDelete(guild, v.User.ID) |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue