Compare commits

...

93 Commits

Author SHA1 Message Date
Gregory Rudolph 87939c32ef
Update deps 1 year ago
Gregory Rudolph fcc806eb77
Remove deprecated io/ioutil import and calls 1 year ago
Gregory Rudolph dd433f44ad
Formatting 1 year ago
Gregory Rudolph 99e6f7066b
Formatting 1 year ago
Gregory Rudolph 139d378d1a
Remove deprecated io/ioutil import and calls 1 year ago
Gregory Rudolph bddd283127
Formatting 1 year ago
Gregory Rudolph 31ca1cb243
Formatting 1 year ago
Gregory Rudolph 5eb7920ed2
New reaction for admins 2 years ago
Gregory Rudolph f79b842e17
Add mention when link is deleted 2 years ago
Gregory Rudolph bd493223ca
Clean up welcome messages 2 years ago
Gregory Rudolph bdbc2a1196
Reconnect bumpTimer 2 years ago
Gregory Rudolph 5ae7a96c3e
Show channel + author mention for removed messages 2 years ago
Gregory Rudolph f5c59af2b4
Log deleted link 2 years ago
Gregory Rudolph 8af3e9656d
No blank links 2 years ago
Gregory Rudolph c2646ad280
Cleaning up commandwork 2 years ago
Gregory Rudolph a93d4a727b
Only look for commands directly after @Thanos 2 years ago
Gregory Rudolph 706c2b516b
trim domain 2 years ago
Gregory Rudolph efbe429824
trim domain 2 years ago
Gregory Rudolph d68f027f42
Add domains to output 2 years ago
Gregory Rudolph 59926b6b9b
Add domains to output 2 years ago
Gregory Rudolph dc0bf186ae
Add URL Whitelisting to Thanos since @MEE6 wants us to pay for it 2 years ago
Gregory Rudolph d24ff86d68
Add URL Whitelisting to Thanos since @MEE6 wants us to pay for it 2 years ago
Gregory Rudolph 27d5cf3a62
Don't look for user in bump response 3 years ago
Gregory Rudolph 0c3f4ce74a
Allow filtering by guild 3 years ago
Gregory Rudolph 6d42e0fa54
Add utility to listen to DiscordGo for debugging 3 years ago
Gregory Rudolph 6e1c27ca27
Cleaning 3 years ago
Gregory Rudolph cb38b8e5c4
Clean up status times 3 years ago
Gregory Rudolph 140515f19b
Add return to only run command once 3 years ago
Gregory Rudolph d4fc69cd50
Ignore 'i' value for actual role ID 3 years ago
Gregory Rudolph 6fd9d11417
Add additional logging for member verification roles 3 years ago
Gregory Rudolph 283f8dbf65
Add logging for messages erroring out 3 years ago
Gregory Rudolph cce07513f3
Add logging for messages erroring out 3 years ago
Gregory Rudolph d13ee51aa6
Remove bump chaser 3 years ago
Gregory Rudolph 7713e3fc02 Update last bumper 3 years ago
Gregory Rudolph 084ce2aaae Cleaning and pushing 3 years ago
Gregory Rudolph cf494d4c11 Listen for successful bumps 3 years ago
Gregory Rudolph 46e67b7f98 Help? 3 years ago
Gregory Rudolph 07d51266bb Thanos should ignore his own messages. 3 years ago
Gregory Rudolph 7aa9372eaf Cleaning incoming message processing 3 years ago
Gregory Rudolph 931825bd5a make sure there is embed before trying operations 3 years ago
Gregory Rudolph 5c39cbdafb Fixed mention for automatic bump set 3 years ago
Gregory Rudolph 25ea59bff1 Remove debugging messages. 3 years ago
Gregory Rudolph 908d506f5c Cleaning bump set 3 years ago
Gregory Rudolph b323262213 Cleaning 3 years ago
Gregory Rudolph 0013b1fe2b Add debugging 3 years ago
Gregory Rudolph 09046f48dc Add attempts to automatically fix bump timer. 3 years ago
Gregory Rudolph bd4b4508e5 Make this tool more generic 3 years ago
Gregory Rudolph 6232d9e126
Cleanup 3 years ago
Gregory Rudolph 90c5a1c472
Remove social channel setup 3 years ago
Gregory Rudolph 578174e878
Only accept certain formats. 3 years ago
Gregory Rudolph b85794089f
Add Discord time formatting 3 years ago
Gregory Rudolph d85da5989a
More goroutines? 4 years ago
Gregory Rudolph 6f3896a90b
Clean socials, instead of talk about it 4 years ago
Gregory Rudolph cebc18f0a2
Add social channel cleanup on member leave, but don't delete yet. Testing first! 4 years ago
Gregory Rudolph a97993e830
Clean up bump set formatting 4 years ago
Gregory Rudolph 01f5ae64ea
Clean up code warnings 4 years ago
Gregory Rudolph 21f5d2bb56
Fix formatting 4 years ago
Gregory Rudolph fef2e7f08f
Fix reboot command 4 years ago
Gregory Rudolph 7610f22b57
Add user activity 4 years ago
Gregory Rudolph 0df1fae253
Add user activity 4 years ago
Gregory Rudolph 5222b1b3b6
Add user activity 4 years ago
Gregory Rudolph 53b3aa61ab
Add user activity 4 years ago
Gregory Rudolph ab0455cf5b
Add user activity 4 years ago
Gregory Rudolph 80746f5bff
Fix RetrieveVerification 4 years ago
Gregory Rudolph 304144c607
Fix idFromUsername 4 years ago
Gregory Rudolph 2f5c3b6cf3
Fix Verification filename 4 years ago
Gregory Rudolph 70672fd5fd
Fix parts[] for everyone 4 years ago
Gregory Rudolph 4d8e33058a
Fix parts[] for dbeug set 4 years ago
Gregory Rudolph 3d174fd4f0
Fix parts[] for dbeug set 4 years ago
Gregory Rudolph 160625396c
go vet 4 years ago
Gregory Rudolph 62738d8a88
Cleaning up/Happy path 4 years ago
Gregory Rudolph 37ce86beb7
Cleaning up/Happy path 4 years ago
Gregory Rudolph 6bdc997cbe
Dont show bump request on commands 4 years ago
Gregory Rudolph 42969ca27c
Fix bumpset 4 years ago
Gregory Rudolph b6716eba46
Fix bumpset 4 years ago
Gregory Rudolph 3d6d5c64b9
Add help for a few commands 4 years ago
Gregory Rudolph 2a5fe0ceef
Add debug level command 4 years ago
Gregory Rudolph fa53c8b1da
Fix admin role check 4 years ago
Gregory Rudolph fb2636c9c0
Debugging 4 years ago
Gregory Rudolph 5dc1f53a59
Debugging 4 years ago
Gregory Rudolph fd5d3ce0e7
Debugging 4 years ago
Gregory Rudolph 526af29391
Debugging 4 years ago
Gregory Rudolph 03ce2fe74a
Debugging 4 years ago
Gregory Rudolph 29ab9296ec
Fix bot command detection 4 years ago
Gregory Rudolph 81f7d3ccdc
Cleanup admin check 4 years ago
Gregory Rudolph 77b6e9c780
Only show commands available to the user 4 years ago
Gregory Rudolph 06da80de97
Add command to list commands 4 years ago
Gregory Rudolph 51f9f10b17
Bump as a bool instead of time 4 years ago
Gregory Rudolph 17141a8ea4
Commands for everyone 4 years ago
Gregory Rudolph af81e9ddc8
Commands for everyone 4 years ago
Gregory Rudolph 664daa311a
Start new admin interactions at 1 not 0 4 years ago
Gregory Rudolph 43ceafbea0
Cleanup Status output 4 years ago
Gregory Rudolph 575a07dd01
Added help for commands 4 years ago
  1. 24
      auth.go
  2. 175
      commands.go
  3. 30
      config.go
  4. 19
      discordEvents.go
  5. 108
      discordMessage.go
  6. 12
      go.mod
  7. 24
      go.sum
  8. 68
      main.go
  9. 43
      site-api.go
  10. 51
      tools/listen.go
  11. 11
      tools/runFunction.go
  12. 10
      types.go

24
auth.go

@ -17,14 +17,14 @@ func reqPass(w http.ResponseWriter, r *http.Request) {
username := r.URL.Query()["UserName"][0] username := r.URL.Query()["UserName"][0]
log.LogInfo("reqPass username is %+v.", username) log.LogInfo("reqPass username is %+v.", username)
var userID string var userID string
if &dg == nil { if dg == nil {
log.LogError("Discord session was nill.") log.LogError("Discord session was nill.")
} }
g, err := dg.GuildMembers(config.GuildID, "", 1000) g, err := dg.GuildMembers(config.GuildID, "", 1000)
log.LogInfo("reqPass guild is %+v.", config.GuildID) log.LogInfo("reqPass guild is %+v.", config.GuildID)
if err == nil { if err == nil {
for _, m := range g { for _, m := range g {
if strings.ToUpper(m.Nick) == strings.ToUpper(username) { if strings.EqualFold(m.Nick, username) {
for _, r := range m.Roles { for _, r := range m.Roles {
if r == config.AdminRole { if r == config.AdminRole {
userID = m.User.ID userID = m.User.ID
@ -40,7 +40,7 @@ func reqPass(w http.ResponseWriter, r *http.Request) {
log.LogInfo("reqPass IP is %+v.", ipaddr) log.LogInfo("reqPass IP is %+v.", ipaddr)
log.LogInfo(fmt.Sprintf("reqPass called:```username: %s\nip : %s```", username, ipaddr)) log.LogInfo(fmt.Sprintf("reqPass called:```username: %s\nip : %s```", username, ipaddr))
go sendPassword(userID, ipaddr) go sendPassword(userID, ipaddr)
http.Redirect(w, r, "/login", 302) http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
} }
func tryLogin(w http.ResponseWriter, r *http.Request) { func tryLogin(w http.ResponseWriter, r *http.Request) {
@ -147,7 +147,6 @@ func getSessionIdentifier(r *http.Request) string {
func detectUser(r *http.Request, callFunc string) (bool, string) { func detectUser(r *http.Request, callFunc string) (bool, string) {
defer log.PanicSafe() defer log.PanicSafe()
log.LogInfo(fmt.Sprintf("%s called detectUser", getSessionIdentifier(r))) log.LogInfo(fmt.Sprintf("%s called detectUser", getSessionIdentifier(r)))
ip := r.Header.Get("X-Real-IP")
session, err := store.Get(r, "2fa") session, err := store.Get(r, "2fa")
if err != nil { if err != nil {
log.LogDebug(fmt.Sprintf("Unable to open 2fa session in %s", callFunc)) log.LogDebug(fmt.Sprintf("Unable to open 2fa session in %s", callFunc))
@ -155,9 +154,6 @@ func detectUser(r *http.Request, callFunc string) (bool, string) {
if session.Values["username"] != nil { if session.Values["username"] != nil {
return true, fmt.Sprintf("%s", session.Values["username"]) return true, fmt.Sprintf("%s", session.Values["username"])
} }
if ip == "154.27.199.33" {
return true, "rudi"
}
return false, "" return false, ""
} }
@ -176,7 +172,7 @@ func idFromUsername(username string) string {
log.LogInfo("reqPass guild is %+v.", config.GuildID) log.LogInfo("reqPass guild is %+v.", config.GuildID)
if err == nil { if err == nil {
for _, m := range g { for _, m := range g {
if strings.ToUpper(m.Nick) == strings.ToUpper(username) { if strings.EqualFold(m.User.Username, username) {
userID = m.User.ID userID = m.User.ID
log.LogInfo("User ID found for %+v as %+v", username, userID) log.LogInfo("User ID found for %+v as %+v", username, userID)
} }
@ -186,3 +182,15 @@ func idFromUsername(username string) string {
} }
return userID 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
}

175
commands.go

@ -5,14 +5,19 @@ import (
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/rudi9719/loggy"
) )
func setupCommands() { func setupCommands() {
reboot := Command{ reboot := Command{
Name: "Reboot", Name: "Reboot",
RequiresAdmin: true,
Help: "Reboot me, requires token from logs.",
Keywords: []string{"reboot", "re", "restart"}, Keywords: []string{"reboot", "re", "restart"},
Exec: Reboot, Exec: Reboot,
} }
@ -20,6 +25,8 @@ func setupCommands() {
bumpset := Command{ bumpset := Command{
Name: "BumpSet", Name: "BumpSet",
RequiresAdmin: true,
Help: "Set the bump timer (requires time in minutes until next bump).",
Keywords: []string{"bs", "bumpset", "bumps"}, Keywords: []string{"bs", "bumpset", "bumps"},
Exec: BumpSet, Exec: BumpSet,
} }
@ -27,6 +34,8 @@ func setupCommands() {
retrieveVerification := Command{ retrieveVerification := Command{
Name: "Retrieve Verification", Name: "Retrieve Verification",
RequiresAdmin: true,
Help: "Retrieve verification either by discord ID or by nickname",
Keywords: []string{"veri", "verification", "retrieve"}, Keywords: []string{"veri", "verification", "retrieve"},
Exec: RetrieveVerification, Exec: RetrieveVerification,
} }
@ -34,6 +43,7 @@ func setupCommands() {
addQuote := Command{ addQuote := Command{
Name: "Add Quote", Name: "Add Quote",
RequiresAdmin: true,
Keywords: []string{"quote", "addq", "q"}, Keywords: []string{"quote", "addq", "q"},
Exec: AddQuote, Exec: AddQuote,
} }
@ -41,6 +51,8 @@ func setupCommands() {
snap := Command{ snap := Command{
Name: "Snap", Name: "Snap",
Help: "Trigger a purge!",
RequiresAdmin: false,
Keywords: []string{"snap", "purge", "sn"}, Keywords: []string{"snap", "purge", "sn"},
Exec: Snap, Exec: Snap,
} }
@ -48,10 +60,73 @@ func setupCommands() {
status := Command{ status := Command{
Name: "Status", Name: "Status",
RequiresAdmin: true,
Help: "Show the current status of Thanos/Verifications and probations",
Keywords: []string{"st", "status", "stats"}, Keywords: []string{"st", "status", "stats"},
Exec: Status, Exec: Status,
} }
commands = append(commands, 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 { func Reboot(b BotCommand) bool {
@ -63,33 +138,71 @@ func Reboot(b BotCommand) bool {
return false 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 { func BumpSet(b BotCommand) bool {
defer log.PanicSafe() defer log.PanicSafe()
bump = false bump = false
parts := strings.Split(b.Message.Content, " ") timer, err := strconv.Atoi(b.Parts[0])
timer, err := strconv.Atoi(parts[1])
if err != nil { if err != nil {
b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("Unable to decode timer: %+v", parts[1])) b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("Unable to decode timer: %+v", b.Parts[0]))
return false return false
} }
config.BumpTime = time.Now().Add(time.Duration(timer) * time.Minute).Add(-2 * time.Hour) config.BumpTime = time.Now().Add(time.Duration(timer) * time.Minute).Add(-2 * time.Hour)
b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("New bump time: %+v, expecting bump at %+v", config.BumpTime, config.BumpTime.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 return true
} }
func RetrieveVerification(b BotCommand) bool { func RetrieveVerification(b BotCommand) bool {
defer log.PanicSafe() defer log.PanicSafe()
s := b.Session discordId := b.Parts[0]
m := b.Message
parts := strings.Split(m.Content, " ")
discordId := parts[1]
_, err := strconv.Atoi(discordId) _, err := strconv.Atoi(discordId)
if err != nil { if err != nil {
discordId = idFromUsername(discordId) discordId = idFromUsername(discordId)
} }
user, err := s.GuildMember(config.GuildID, discordId) user, err := b.Session.GuildMember(config.GuildID, discordId)
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
return false
} }
matches, err := filepath.Glob(fmt.Sprintf("./verifications/*%+v*", discordId)) matches, err := filepath.Glob(fmt.Sprintf("./verifications/*%+v*", discordId))
@ -98,7 +211,7 @@ func RetrieveVerification(b BotCommand) bool {
return false return false
} }
if len(matches) != 1 { if len(matches) != 1 {
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Error finding verification for ID %+v", discordId)) b.Session.ChannelMessageSend(b.Message.ChannelID, fmt.Sprintf("Error finding verification for ID %+v", discordId))
return false return false
} }
@ -108,7 +221,7 @@ func RetrieveVerification(b BotCommand) bool {
return false return false
} }
msg := fmt.Sprintf("``` %+v\nJoined: %+v\n```", user.User.Username, user.JoinedAt) msg := fmt.Sprintf("``` %+v\nJoined: %+v\n```", user.User.Username, user.JoinedAt)
s.ChannelFileSendWithMessage(m.ChannelID, msg, fmt.Sprintf("%+v Verification", discordId), verificationImage) b.Session.ChannelFileSendWithMessage(b.Message.ChannelID, msg, matches[0], verificationImage)
return true return true
} }
@ -128,36 +241,38 @@ func Snap(b BotCommand) bool {
func Status(b BotCommand) bool { func Status(b BotCommand) bool {
defer log.PanicSafe() defer log.PanicSafe()
status := fmt.Sprintf("Uptime: %+v\n", time.Since(startupTime)) status := fmt.Sprintf("Uptime: %+v\n", time.Since(startupTime))
status += fmt.Sprintf("Last bump: %+v\n", time.Since(config.BumpTime)) status += fmt.Sprintf("Last active time: %+v\n", time.Since(lastActiveTime))
status += fmt.Sprintf("Last bumper: <@%+v>\n", userFromID(config.LastBumper).Username) 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) status += fmt.Sprintf("Bump needed: %+v\n", bump)
if len(config.Unverified) > 0 { if len(config.Unverified) > 0 {
status += "Unverified users:\n```" status += "Unverified users:\n"
for k, v := range config.Unverified { for k, v := range config.Unverified {
uvUser := userFromID(k) uvUser := userFromID(k)
status += fmt.Sprintf("\n%+v will be removed in %+v", uvUser.Username, time.Until(v.Add(1*time.Hour))) status += fmt.Sprintf("\n%+v will be removed at <t:%+v:t>", uvUser.Username, v.Add(1*time.Hour).Unix())
} }
status += "```" status += "\n"
} else { } else {
status += "There are no unverified users.\n" status += "There are no unverified users.\n"
} }
if len(config.Verifications) > 0 { if len(config.Verifications) > 0 {
status += "Pending verifications:\n" status += "Pending verifications:\n"
status += "```"
for _, v := range config.Verifications { for _, v := range config.Verifications {
status += fmt.Sprintf("%+v has submitted a verification.", v.Username) status += fmt.Sprintf("%+v has submitted a verification.", v.Username)
} }
status += "```" status += "\n"
} else { } else {
status += "There are no pending verifications." status += "There are no pending verifications.\n"
} }
if len(config.Probations) > 0 { if len(config.Probations) > 0 {
status += "\nThe following users are on probation: \n```" status += "\nThe following users are on probation: \n"
for uid, join := range config.Probations { for uid, join := range config.Probations {
probationUser := userFromID(uid) probationUser := userFromID(uid)
status += fmt.Sprintf("%+v for another %+v\n", probationUser.Username, time.Until(join.Add(2*time.Hour))) status += fmt.Sprintf("%+v for until <t:%+v:t>\n", probationUser.Username, join.Add(2*time.Hour).Unix())
} }
status += "```" status += "\n"
} else {
status += "There are no users on probation.\n"
} }
b.Session.ChannelMessageSend(config.AdminChannel, status) b.Session.ChannelMessageSend(config.AdminChannel, status)
statistics := "```" statistics := "```"
@ -174,3 +289,19 @@ func Status(b BotCommand) bool {
go runPurge(b.Session) go runPurge(b.Session)
return true 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
}

30
config.go

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -16,7 +15,7 @@ import (
func loadConfig() { func loadConfig() {
var c Config var c Config
confFile, _ := ioutil.ReadFile(configFile) confFile, _ := os.ReadFile(configFile)
err := json.Unmarshal([]byte(confFile), &c) err := json.Unmarshal([]byte(confFile), &c)
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
@ -52,26 +51,42 @@ func saveConfig() {
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
} }
err = ioutil.WriteFile(configFile, file, 0600) err = os.WriteFile(configFile, file, 0600)
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
} }
} }
func adminInteraction(s *discordgo.Session, m string) { func adminInteraction(s *discordgo.Session, m string) {
defer log.PanicSafe()
admin, _ := s.GuildMember(config.GuildID, m) admin, _ := s.GuildMember(config.GuildID, m)
counter, ok := config.Stats[admin.User.ID] counter, ok := config.Stats[admin.User.ID]
if !ok { if !ok {
config.Stats[admin.User.ID] = 0 config.Stats[admin.User.ID] = 1
} else { } else {
config.Stats[admin.User.ID] = counter + 1 config.Stats[admin.User.ID] = counter + 1
} }
} }
func activeInteraction(s *discordgo.Session, m string) {
defer log.PanicSafe()
if config.Activity == nil {
config.Activity = make(map[string]int)
}
user, _ := s.GuildMember(config.GuildID, m)
counter, ok := config.Activity[user.User.ID]
if !ok {
config.Activity[user.User.ID] = 1
} else {
config.Activity[user.User.ID] = counter + 1
}
}
func rebootBump() { func rebootBump() {
time.Sleep(time.Until(config.BumpTime.Add(2 * time.Hour))) time.Sleep(time.Until(config.BumpTime.Add(2 * time.Hour)))
dg.ChannelMessageSend(config.AdminChannel, "!d bump is ready") dg.ChannelMessageSend(config.AdminChannel, "/bump is ready")
} }
@ -82,10 +97,7 @@ func bumpTimer(s *discordgo.Session) {
bump = false bump = false
config.BumpTime = time.Now() config.BumpTime = time.Now()
time.Sleep(2 * time.Hour) time.Sleep(2 * time.Hour)
if time.Since(lastActiveTime) < (5*time.Minute) && lastActiveChan != config.AdminChannel { s.ChannelMessageSend(config.AdminChannel, "/bump is ready.")
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 bump = true
} }

19
discordEvents.go

@ -9,29 +9,34 @@ import (
func ready(s *discordgo.Session, event *discordgo.Ready) { func ready(s *discordgo.Session, event *discordgo.Ready) {
// Set the playing status. // Set the playing status.
s.UpdateGameStatus(0, fmt.Sprintf("DreamDaddy v%+v %+v", version, gitCommit)) s.UpdateGameStatus(0, fmt.Sprintf("DreamDaddy rev %+v", gitCommit))
} }
func guildMemberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) { func guildMemberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) {
defer log.PanicSafe() defer log.PanicSafe()
for role := range m.Roles { log.LogDebug("Member %+v has been updated", m.User.Username)
for _, role := range m.Roles {
if fmt.Sprintf("%+v", role) == config.MonitorRole { if fmt.Sprintf("%+v", role) == config.MonitorRole {
s.ChannelMessageSend(config.AdminChannel, "New unverified user detected.") 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())) 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.Unverified[m.User.ID] = time.Now()
config.Probations[m.User.ID] = time.Now() config.Probations[m.User.ID] = time.Now()
saveConfig() saveConfig()
return
} }
log.LogDebug("Monitor Role not found: %+v != %+v", fmt.Sprintf("%+v", role), config.MonitorRole)
} }
} }
func guildMemberAdd(s *discordgo.Session, m *discordgo.GuildMemberAdd) { func guildMemberAdd(s *discordgo.Session, m *discordgo.GuildMemberAdd) {
defer log.PanicSafe() defer log.PanicSafe()
log.LogDebug("Adding user to Unverified and Probations")
config.Unverified[m.User.ID] = time.Now() config.Unverified[m.User.ID] = time.Now()
config.Probations[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) s.GuildMemberRoleAdd(config.GuildID, m.User.ID, config.MonitorRole)
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())) log.LogDebug("Calling saveConfig")
saveConfig() saveConfig()
} }
@ -105,8 +110,12 @@ func readReaction(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
requestAge(s, user) requestAge(s, user)
log.LogInfo("%+v has requested ASL for user %+v.", admin.User.Username, user.Username) log.LogInfo("%+v has requested ASL for user %+v.", admin.User.Username, user.Username)
return 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 == "⛔" { } else if m.Emoji.Name == "⛔" {
s.GuildBanCreateWithReason(config.GuildID, user.ID, fmt.Sprintf("Underage or too many failed verifications. %+v", admin.User.Username), 5) s.GuildBanCreateWithReason(config.GuildID, user.ID, fmt.Sprintf("Underage, female, or too many failed verifications. %+v", admin.User.Username), 5)
verification.Status = "Banned" verification.Status = "Banned"
} else { } else {
return return

108
discordMessage.go

@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"regexp"
"strings" "strings"
"time" "time"
@ -10,68 +11,114 @@ import (
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
defer log.PanicSafe() defer log.PanicSafe()
var b BotCommand
if strings.HasPrefix(m.Content, s.State.User.Mention()) { if m.Author.ID == "302050872383242240" && len(m.Embeds) > 0 {
b = BotCommand{ if strings.Contains(m.Embeds[0].Description, "minutes until the server can be bumped") {
Session: s, 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, Message: m,
Parts: strings.Split(m.Content, " ")[1:], Session: s,
Parts: strings.Split(m.Content, " ")[2:],
})
} else {
go bumpTimer(s)
} }
return
} }
if m.Author.ID == s.State.User.ID || m.Author.Bot { if m.Author.Bot || m.Author.ID == s.State.User.ID {
return return
} }
if m.GuildID == "" { if m.GuildID == "" {
handlePM(s, m) handlePM(s, m)
return return
} }
if m.ChannelID == config.MonitorChann {
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 { 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())) s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%+v send me a private message for verification.", m.Author.Mention()))
} }
return return
} }
for role := range m.Member.Roles {
if fmt.Sprintf("%+v", role) == config.AdminRole {
adminInteraction(s, m.Author.ID)
}
}
if m.ChannelID != config.AdminChannel { if m.ChannelID != config.AdminChannel {
lastActiveChan = m.ChannelID
lastActiveTime = time.Now() lastActiveTime = time.Now()
if len(m.Attachments) > 0 {
activeInteraction(s, m.Author.ID)
} }
if strings.HasPrefix(m.Content, "!d bump") {
if time.Since(config.BumpTime) < 2*time.Hour {
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Sorry, <@%+v> already claimed the bump. Better luck next time!", config.LastBumper))
return
} }
config.LastBumper = m.Author.ID if strings.Contains(m.Content, "http") {
go bumpTimer(s) safe := false
return 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))
} }
if time.Since(config.BumpTime) > 2*time.Hour {
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%+v please say \"!d bump\" without the quotes to bump our server :)", m.Author.Mention()))
} }
if m.ChannelID == config.AdminChannel { }
if strings.HasPrefix(m.Content, s.State.User.Mention()) { 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 _, cmd := range commands {
for _, keyword := range cmd.Keywords { for _, keyword := range cmd.Keywords {
if strings.Contains(m.Content, keyword) { log.LogDebug("Checking if %+v contains %+v", m.Content, keyword)
if strings.Contains(parts[1], keyword) {
log.LogDebug("%+v found!", keyword)
b.Command = keyword b.Command = keyword
if !cmd.RequiresAdmin {
log.LogDebug("%+v does not require admin, running!", cmd.Name)
if !cmd.Exec(b) { if !cmd.Exec(b) {
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("There was an error running %+v\n%+v", cmd.Name, cmd.Help)) 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) { func handlePM(s *discordgo.Session, m *discordgo.MessageCreate) {
defer log.PanicSafe() defer log.PanicSafe()
if strings.Contains(m.Content, "Rule") || strings.Contains(m.Content, "rule") { 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.") 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 { for _, uid := range config.Verifications {
user := userFromID(uid.UserID) user := userFromID(uid.UserID)
@ -90,6 +137,14 @@ func handlePM(s *discordgo.Session, m *discordgo.MessageCreate) {
s.ChannelMessageSend(m.ChannelID, "You have tried to send an unsupported file (HEIC). Please try again using an image (jpeg, jpg, png, etc).") s.ChannelMessageSend(m.ChannelID, "You have tried to send an unsupported file (HEIC). Please try again using an image (jpeg, jpg, png, etc).")
return 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) delete(config.Unverified, m.Author.ID)
var v Verification var v Verification
v.Submitted = time.Now() v.Submitted = time.Now()
@ -100,6 +155,7 @@ func handlePM(s *discordgo.Session, m *discordgo.MessageCreate) {
msg, _ := s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v\n%+v", v.Username, v.Photo)) msg, _ := s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v\n%+v", v.Username, v.Photo))
config.Verifications[msg.ID] = v 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, "👍")
s.MessageReactionAdd(config.AdminChannel, msg.ID, "👶") s.MessageReactionAdd(config.AdminChannel, msg.ID, "👶")
s.MessageReactionAdd(config.AdminChannel, msg.ID, "⛔") s.MessageReactionAdd(config.AdminChannel, msg.ID, "⛔")

12
go.mod

@ -1,10 +1,18 @@
module git.nightmare.haus/rudi/disgord-thanos module git.nightmare.haus/rudi/disgord-thanos
go 1.15 go 1.21
require ( require (
github.com/bwmarrin/discordgo v0.23.2 github.com/bwmarrin/discordgo v0.27.1
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/gorilla/sessions v1.2.1 github.com/gorilla/sessions v1.2.1
github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a 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
)

24
go.sum

@ -1,16 +1,26 @@
github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= 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 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 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 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 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 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 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 h1:4rkaWoLCWOmra5Mw/dLAWjtDLT/+i5uTX1qhlMVL8WA=
github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a/go.mod h1:s1ANCN8bF6HwwTpJLR458MFVGua9oqKKDbph/2jptL4= github.com/rudi9719/loggy v0.0.0-20201031035735-9438c484de9a/go.mod h1:s1ANCN8bF6HwwTpJLR458MFVGua9oqKKDbph/2jptL4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
samhofi.us/x/keybase v0.0.0-20200129212102-e05e93be9f3f h1:MHSEiuiRFrFi7BTw46lC22PMk3Fit8IvVRM4xANTt20= 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 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=

68
main.go

@ -15,21 +15,18 @@ import (
var ( var (
startupTime time.Time startupTime time.Time
setupToken = fmt.Sprintf("!setup %+v", rand.Intn(9999)+1000) setupToken = fmt.Sprintf("%+v", rand.Intn(9999)+1000)
rebootToken = fmt.Sprintf("!reboot %+v", rand.Intn(9999)+1000) rebootToken = fmt.Sprintf("%+v", rand.Intn(9999)+1000)
bump = true bump = true
config Config config Config
log = loggy.NewLogger(config.LogOpts) log = loggy.NewLogger(config.LogOpts)
lastActiveChan string
lastActiveTime time.Time lastActiveTime time.Time
token string token string
configFile string configFile string
setupMsg string
dg *discordgo.Session dg *discordgo.Session
lastPM = make(map[string]time.Time) lastPM = make(map[string]time.Time)
introMsg = make(map[string]string) introMsg = make(map[string]string)
quotes = []string{"The hardest choices require the strongest wills.", "You're strong, but I could snap my fingers and you'd all cease to exist.", "Fun isn't something one considers when balancing the universe. But this... does put a smile on my face.", "Perfectly balanced, as all things should be.", "I am inevitable."} quotes = []string{"The hardest choices require the strongest wills.", "You're strong, but I could snap my fingers and you'd all cease to exist.", "Fun isn't something one considers when balancing the universe. But this... does put a smile on my face.", "Perfectly balanced, as all things should be.", "I am inevitable."}
version = "3.0"
gitCommit string gitCommit string
commands []Command commands []Command
) )
@ -51,7 +48,6 @@ func main() {
log = loggy.NewLogger(config.LogOpts) log = loggy.NewLogger(config.LogOpts)
startupTime = time.Now() startupTime = time.Now()
lastActiveTime = time.Now() lastActiveTime = time.Now()
lastActiveChan = config.AdminChannel
if token == "" { if token == "" {
log.LogPanic("No token provided. Please run: disgord-thanos -t <bot token>") log.LogPanic("No token provided. Please run: disgord-thanos -t <bot token>")
} }
@ -84,7 +80,7 @@ func main() {
go purgeTimer(dg) go purgeTimer(dg)
go rebootBump() go rebootBump()
sc := make(chan os.Signal, 1) sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-sc <-sc
saveConfig() saveConfig()
dg.Close() dg.Close()
@ -126,7 +122,7 @@ func runPurge(s *discordgo.Session) {
lastPM[k] = time.Now() lastPM[k] = time.Now()
pmChann, _ := s.UserChannelCreate(k) pmChann, _ := s.UserChannelCreate(k)
s.ChannelMessageSend(pmChann.ID, s.ChannelMessageSend(pmChann.ID,
fmt.Sprintf("This is a reminder that you have not verified with me and will be removed in %+v. You may reply to this message for verification instructions.", time.Until(v.Add(1*time.Hour)))) fmt.Sprintf("This is a reminder that you have not verified with me and will be removed at <t:%+v:t>. You may reply to this message for verification instructions.", v.Add(1*time.Hour).Unix()))
if time.Since(v) > (time.Hour * 1) { if time.Since(v) > (time.Hour * 1) {
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v was removed.", m.Mention())) s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v was removed.", m.Mention()))
s.GuildMemberDeleteWithReason(config.GuildID, k, fmt.Sprintf("Unverified user %+v.", v)) s.GuildMemberDeleteWithReason(config.GuildID, k, fmt.Sprintf("Unverified user %+v.", v))
@ -152,32 +148,74 @@ func runPurge(s *discordgo.Session) {
s.ChannelMessageDelete(config.MonitorChann, message.ID) s.ChannelMessageDelete(config.MonitorChann, message.ID)
} }
} }
go cleanSocials(s)
saveConfig() saveConfig()
} }
func cleanSocials(s *discordgo.Session) {
for _, channel := range config.SocialChanns {
go func(channel string, s *discordgo.Session) {
messages, _ := s.ChannelMessages(channel, 100, "", "", "")
for _, message := range messages {
_, err := s.GuildMember(config.GuildID, message.Author.ID)
if err != nil {
s.ChannelMessageDelete(channel, message.ID)
}
}
}(channel, s)
}
}
func verifyMember(s *discordgo.Session, u discordgo.User) { func verifyMember(s *discordgo.Session, u discordgo.User) {
defer log.PanicSafe() defer log.PanicSafe()
log.LogDebug("Adding verified roll")
s.GuildMemberRoleAdd(config.GuildID, u.ID, config.VerifiedRole) s.GuildMemberRoleAdd(config.GuildID, u.ID, config.VerifiedRole)
log.LogDebug("Removing monitor role")
s.GuildMemberRoleRemove(config.GuildID, u.ID, config.MonitorRole) s.GuildMemberRoleRemove(config.GuildID, u.ID, config.MonitorRole)
st, _ := s.UserChannelCreate(u.ID) log.LogDebug("Creating PM channel")
st, err := s.UserChannelCreate(u.ID)
if err != nil {
log.LogErrorType(err)
}
log.LogDebug("Sending acceptance message!")
s.ChannelMessageSend(st.ID, "Your verification has been accepted, welcome!") s.ChannelMessageSend(st.ID, "Your verification has been accepted, welcome!")
m, _ := s.ChannelMessageSend(config.IntroChann, fmt.Sprintf("Welcome %+v please introduce yourself! :) feel free to check out <#710557387937022034> to tag your roles. Also please mute any channels you are not interested in!", u.Mention())) log.LogDebug("Sending Intro message")
m, err := s.ChannelMessageSend(config.IntroChann, fmt.Sprintf("Welcome %+v please introduce yourself! :) feel free to check out <#710557387937022034> to tag your roles. Also please mute any channels you are not interested in!", u.Mention()))
if err != nil {
log.LogErrorType(err)
}
log.LogDebug("Storing introMsg ID to be deleted later")
introMsg[u.ID] = m.ID introMsg[u.ID] = m.ID
} }
func rejectVerification(s *discordgo.Session, u discordgo.User) { func rejectVerification(s *discordgo.Session, u discordgo.User) {
defer log.PanicSafe() defer log.PanicSafe()
st, _ := s.UserChannelCreate(u.ID) st, err := s.UserChannelCreate(u.ID)
if err != nil {
log.LogErrorType(err)
}
if st != nil { if st != nil {
s.ChannelMessageSend(st.ID, fmt.Sprintf("Your verification has been rejected. This means it did not clearly show your face, with your pinkie finger held to the corner of your mouth, or the photo looked edited/filtered. No filters will be accepted.\n\nPlease try again before %+v", time.Until(time.Now().Add(1*time.Hour)))) s.ChannelMessageSend(st.ID, fmt.Sprintf("Your verification has been rejected. This means it did not clearly show your face, with your pinkie finger held to the corner of your mouth, or the photo looked edited/filtered. No filters will be accepted.\n\nPlease try again before <t:%+v:t>", time.Now().Add(1*time.Hour).Unix()))
} }
config.Unverified[u.ID] = time.Now() config.Unverified[u.ID] = time.Now()
} }
func requestAge(s *discordgo.Session, u discordgo.User) { func requestAge(s *discordgo.Session, u discordgo.User) {
defer log.PanicSafe() defer log.PanicSafe()
st, _ := s.UserChannelCreate(u.ID) st, err := s.UserChannelCreate(u.ID)
s.ChannelMessageSend(st.ID, "What is your ASL? (Age/Sex/Language) Please note, this is NOT requesting your gender, but your biological sex. Gender is a social construct, sex is biology and in the context of pornographic images more important.") if err != nil {
log.LogErrorType(err)
}
s.ChannelMessageSend(st.ID, "What is your ASL? (Age/Sex/Language) Please note, this is NOT requesting your gender, but your biological sex. Gender is a social construct, sex is measurable and in the context of pornographic images more important.")
} }
func requestReupload(s *discordgo.Session, u discordgo.User) {
defer log.PanicSafe()
st, err := s.UserChannelCreate(u.ID)
if err != nil {
log.LogErrorType(err)
}
s.ChannelMessageSend(st.ID, "Hello! Your verification has been denied because it failed to load. Please try again! The instructions will follow this message:")
rejectVerification(s, u)
}

43
site-api.go

@ -3,7 +3,6 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -16,12 +15,11 @@ import (
var ( var (
store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY"))) store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
toks = make(map[string]Tokens) toks = make(map[string]Tokens)
acctLinks = make(map[string]linkedAccount)
) )
func topWrapper(r *http.Request) string { func topWrapper(r *http.Request) string {
defer log.PanicSafe() defer log.PanicSafe()
headerTemplate, err := ioutil.ReadFile("./static/header.tpl") headerTemplate, err := os.ReadFile("./static/header.tpl")
if err != nil { if err != nil {
log.LogError(fmt.Sprintf("Unable to open header template: ```%+v```", err)) log.LogError(fmt.Sprintf("Unable to open header template: ```%+v```", err))
return "" return ""
@ -38,7 +36,7 @@ func topWrapper(r *http.Request) string {
func bodyWrapper(r *http.Request, template string) string { func bodyWrapper(r *http.Request, template string) string {
defer log.PanicSafe() defer log.PanicSafe()
bodyTemplate, err := ioutil.ReadFile(fmt.Sprintf("./static/%+v.tpl", template)) bodyTemplate, err := os.ReadFile(fmt.Sprintf("./static/%+v.tpl", template))
if err != nil { if err != nil {
log.LogError(fmt.Sprintf("Attempt to load %s.tpl failed. ```%+v```", template, err)) log.LogError(fmt.Sprintf("Attempt to load %s.tpl failed. ```%+v```", template, err))
return bodyWrapper(r, "404") return bodyWrapper(r, "404")
@ -59,17 +57,17 @@ func greetUser(w http.ResponseWriter, r *http.Request) {
loggedIn, _ := detectUser(r, "Homepage") loggedIn, _ := detectUser(r, "Homepage")
if loggedIn { if loggedIn {
bodyTemplate, _ := ioutil.ReadFile("./static/index.html") bodyTemplate, _ := os.ReadFile("./static/index.html")
fmt.Fprintf(w, string(bodyTemplate)) fmt.Fprint(w, string(bodyTemplate))
} else { } else {
fmt.Fprintf(w, pageBuilder(r, "home")) fmt.Fprint(w, pageBuilder(r, "home"))
} }
} }
func passPage(w http.ResponseWriter, r *http.Request) { func passPage(w http.ResponseWriter, r *http.Request) {
defer log.PanicSafe() defer log.PanicSafe()
log.LogInfo(fmt.Sprintf("%s called passPage", getSessionIdentifier(r))) log.LogInfo(fmt.Sprintf("%s called passPage", getSessionIdentifier(r)))
fmt.Fprintf(w, pageBuilder(r, "pass")) fmt.Fprint(w, pageBuilder(r, "pass"))
} }
func loginPage(w http.ResponseWriter, r *http.Request) { func loginPage(w http.ResponseWriter, r *http.Request) {
defer log.PanicSafe() defer log.PanicSafe()
@ -85,18 +83,18 @@ func loginPage(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
log.LogWarn("Error logging out from loginPage()") log.LogWarn("Error logging out from loginPage()")
} }
fmt.Fprintf(w, pageBuilder(r, "home")) fmt.Fprint(w, pageBuilder(r, "home"))
return return
} }
fmt.Fprintf(w, pageBuilder(r, "login")) fmt.Fprint(w, pageBuilder(r, "login"))
} }
func notFoundPage(w http.ResponseWriter, r *http.Request) { func notFoundPage(w http.ResponseWriter, r *http.Request) {
defer log.PanicSafe() defer log.PanicSafe()
go log.LogWarn(fmt.Sprintf("%s triggered notFoundPage", getSessionIdentifier(r))) go log.LogWarn(fmt.Sprintf("%s triggered notFoundPage", getSessionIdentifier(r)))
fmt.Fprintf(w, topWrapper(r)) fmt.Fprint(w, topWrapper(r))
fmt.Fprintf(w, card("Oops! That Page Was Not found.", fmt.Fprint(w, card("Oops! That Page Was Not found.",
"Sorry, a 404 error has occured. The requested page not found! <br><br>"+ "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>", "<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>")) "<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>"))
@ -104,7 +102,7 @@ func notFoundPage(w http.ResponseWriter, r *http.Request) {
} }
func card(title string, content string, footer string) string { func card(title string, content string, footer string) string {
defer log.PanicSafe() defer log.PanicSafe()
cardTemplate, err := ioutil.ReadFile("./static/card.tpl") cardTemplate, err := os.ReadFile("./static/card.tpl")
if err != nil { if err != nil {
log.LogError("Unable to open card template") log.LogError("Unable to open card template")
return "" return ""
@ -126,7 +124,7 @@ func getPending(w http.ResponseWriter, r *http.Request) {
log.LogErrorType(err) log.LogErrorType(err)
notFoundPage(w, r) notFoundPage(w, r)
} }
fmt.Fprintf(w, string(pending)) fmt.Fprint(w, string(pending))
} else { } else {
notFoundPage(w, r) notFoundPage(w, r)
} }
@ -140,7 +138,7 @@ func getConfig(w http.ResponseWriter, r *http.Request) {
log.LogErrorType(err) log.LogErrorType(err)
notFoundPage(w, r) notFoundPage(w, r)
} }
fmt.Fprintf(w, string(pending)) fmt.Fprint(w, string(pending))
} else { } else {
notFoundPage(w, r) notFoundPage(w, r)
} }
@ -154,7 +152,7 @@ func getProbations(w http.ResponseWriter, r *http.Request) {
log.LogErrorType(err) log.LogErrorType(err)
notFoundPage(w, r) notFoundPage(w, r)
} }
fmt.Fprintf(w, string(pending)) fmt.Fprint(w, string(pending))
} else { } else {
notFoundPage(w, r) notFoundPage(w, r)
} }
@ -193,7 +191,7 @@ func getVerifications(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
} }
fmt.Fprintf(w, string(verifications)) fmt.Fprint(w, string(verifications))
} }
func getUser(w http.ResponseWriter, r *http.Request) { func getUser(w http.ResponseWriter, r *http.Request) {
@ -215,16 +213,7 @@ func getUser(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
log.LogErrorType(err) log.LogErrorType(err)
} }
fmt.Fprintf(w, string(ret)) fmt.Fprint(w, string(ret))
}
func getVerification(w http.ResponseWriter, r *http.Request) {
loggedIn, _ := detectUser(r, "getVerification")
if !loggedIn {
notFoundPage(w, r)
return
}
http.ServeFile(w, r, r.URL.Path)
} }
func runWeb() { func runWeb() {

51
tools/listen.go

@ -0,0 +1,51 @@
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))
}

11
tools/unban.go → tools/runFunction.go

@ -1,4 +1,4 @@
package main package tools
import ( import (
"flag" "flag"
@ -9,14 +9,13 @@ import (
var ( var (
token string token string
configFile string
dg *discordgo.Session dg *discordgo.Session
guild = "451553644161138712" guild string
) )
func init() { func init() {
flag.StringVar(&token, "t", "", "Bot Token") flag.StringVar(&token, "t", "", "Bot Token")
flag.StringVar(&configFile, "c", "", "Config file") flag.StringVar(&guild, "g", "", "Guild ID")
flag.Parse() flag.Parse()
} }
@ -26,11 +25,11 @@ func main() {
} }
dg, _ = discordgo.New("Bot " + token) dg, _ = discordgo.New("Bot " + token)
_ = dg.Open() _ = dg.Open()
unbanAll() runFunction()
dg.Close() dg.Close()
} }
func unbanAll() { func runFunction() {
bans, _ := dg.GuildBans(guild) bans, _ := dg.GuildBans(guild)
for _, v := range bans { for _, v := range bans {
dg.GuildBanDelete(guild, v.User.ID) dg.GuildBanDelete(guild, v.User.ID)

10
types.go

@ -18,6 +18,7 @@ type BotCommand struct {
// Command is the type to store commands // Command is the type to store commands
type Command struct { type Command struct {
Name string Name string
RequiresAdmin bool
Help string Help string
Keywords []string Keywords []string
Exec func(BotCommand) bool Exec func(BotCommand) bool
@ -31,14 +32,17 @@ type Config struct {
MonitorRole string MonitorRole string
IntroChann string IntroChann string
MonitorChann string MonitorChann string
SocialChanns []string
VerifiedRole string VerifiedRole string
BumpTime time.Time BumpTime time.Time
LastBumper string LastBumper string
Stats map[string]int Stats map[string]int
Activity map[string]int
Unverified map[string]time.Time Unverified map[string]time.Time
Verifications map[string]Verification Verifications map[string]Verification
Probations map[string]time.Time Probations map[string]time.Time
LogOpts loggy.LogOpts LogOpts loggy.LogOpts
WhitelistURLs []string
} }
// Verification struct used for storing and logging // Verification struct used for storing and logging
@ -52,12 +56,6 @@ type Verification struct {
Closed time.Time Closed time.Time
} }
type linkedAccount struct {
domainUser string
discordUser string
sigHash string
}
// Tokens are the Login Token struct // Tokens are the Login Token struct
type Tokens struct { type Tokens struct {
Username string Username string

Loading…
Cancel
Save