You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
6.6 KiB
221 lines
6.6 KiB
package main |
|
|
|
import ( |
|
"flag" |
|
"fmt" |
|
"math/rand" |
|
"os" |
|
"os/signal" |
|
"syscall" |
|
"time" |
|
|
|
"github.com/bwmarrin/discordgo" |
|
"github.com/rudi9719/loggy" |
|
) |
|
|
|
var ( |
|
startupTime time.Time |
|
setupToken = fmt.Sprintf("%+v", rand.Intn(9999)+1000) |
|
rebootToken = fmt.Sprintf("%+v", rand.Intn(9999)+1000) |
|
bump = true |
|
config Config |
|
log = loggy.NewLogger(config.LogOpts) |
|
lastActiveTime time.Time |
|
token string |
|
configFile string |
|
dg *discordgo.Session |
|
lastPM = make(map[string]time.Time) |
|
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."} |
|
gitCommit string |
|
commands []Command |
|
) |
|
|
|
func init() { |
|
flag.StringVar(&token, "t", "", "Bot Token") |
|
flag.StringVar(&configFile, "c", "", "Config file") |
|
flag.Parse() |
|
} |
|
|
|
func main() { |
|
go runWeb() |
|
defer log.PanicSafe() |
|
if configFile == "" { |
|
configFile = "config.json" |
|
} else { |
|
loadConfig() |
|
} |
|
log = loggy.NewLogger(config.LogOpts) |
|
startupTime = time.Now() |
|
lastActiveTime = time.Now() |
|
if token == "" { |
|
log.LogPanic("No token provided. Please run: disgord-thanos -t <bot token>") |
|
} |
|
|
|
log.LogCritical("SetupToken: %+v\nRebootToken: %+v", setupToken, rebootToken) |
|
var err error |
|
dg, err = discordgo.New("Bot " + token) |
|
if err != nil { |
|
log.LogErrorType(err) |
|
log.LogPanic("Unable to create bot using token.") |
|
} |
|
|
|
dg.AddHandler(ready) |
|
dg.AddHandler(guildMemberRemove) |
|
dg.AddHandler(guildMemberAdd) |
|
dg.AddHandler(guildMemberBanned) |
|
go setupCommands() |
|
dg.AddHandler(messageCreate) |
|
dg.AddHandler(readReaction) |
|
dg.AddHandler(guildMemberUpdate) |
|
dg.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAll) |
|
|
|
err = dg.Open() |
|
if err != nil { |
|
log.LogErrorType(err) |
|
log.LogPanic("Unable to open websocket.") |
|
} |
|
|
|
log.LogInfo("Thanos is now running. Press CTRL-C to exit.") |
|
go purgeTimer(dg) |
|
go rebootBump() |
|
sc := make(chan os.Signal, 1) |
|
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) |
|
<-sc |
|
saveConfig() |
|
dg.Close() |
|
} |
|
|
|
func exit(s *discordgo.Session) { |
|
s.Close() |
|
saveConfig() |
|
os.Exit(0) |
|
} |
|
|
|
func runPurge(s *discordgo.Session) { |
|
defer log.PanicSafe() |
|
if time.Since(config.BumpTime) > 2*time.Hour { |
|
bump = true |
|
} |
|
for uid, join := range config.Probations { |
|
if time.Since(join) > 2*time.Hour { |
|
delete(config.Probations, uid) |
|
s.ChannelMessageDelete(config.IntroChann, introMsg[uid]) |
|
} |
|
} |
|
for k, v := range config.Unverified { |
|
isUnverified := false |
|
m, err := s.GuildMember(config.GuildID, k) |
|
if err != nil { |
|
delete(config.Unverified, k) |
|
continue |
|
} |
|
for _, role := range m.Roles { |
|
if role == config.MonitorRole { |
|
isUnverified = true |
|
} |
|
} |
|
if isUnverified { |
|
if val, ok := lastPM[k]; ok && time.Since(val) < 5*time.Minute { |
|
continue |
|
} |
|
lastPM[k] = time.Now() |
|
pmChann, _ := s.UserChannelCreate(k) |
|
s.ChannelMessageSend(pmChann.ID, |
|
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) { |
|
s.ChannelMessageSend(config.AdminChannel, fmt.Sprintf("%+v was removed.", m.Mention())) |
|
s.GuildMemberDeleteWithReason(config.GuildID, k, fmt.Sprintf("Unverified user %+v.", v)) |
|
} |
|
} else { |
|
delete(config.Unverified, k) |
|
} |
|
} |
|
messages, _ := s.ChannelMessages(config.MonitorChann, 100, "", "", "") |
|
for _, message := range messages { |
|
found := false |
|
for user := range config.Unverified { |
|
if message.Author.ID == user { |
|
found = true |
|
} |
|
for _, mention := range message.Mentions { |
|
if mention.ID == user { |
|
found = true |
|
} |
|
} |
|
} |
|
if !found { |
|
s.ChannelMessageDelete(config.MonitorChann, message.ID) |
|
} |
|
} |
|
go cleanSocials(s) |
|
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) { |
|
defer log.PanicSafe() |
|
log.LogDebug("Adding verified roll") |
|
s.GuildMemberRoleAdd(config.GuildID, u.ID, config.VerifiedRole) |
|
log.LogDebug("Removing monitor role") |
|
s.GuildMemberRoleRemove(config.GuildID, u.ID, config.MonitorRole) |
|
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!") |
|
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 |
|
} |
|
|
|
func rejectVerification(s *discordgo.Session, u discordgo.User) { |
|
defer log.PanicSafe() |
|
st, err := s.UserChannelCreate(u.ID) |
|
if err != nil { |
|
log.LogErrorType(err) |
|
} |
|
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 <t:%+v:t>", time.Now().Add(1*time.Hour).Unix())) |
|
} |
|
config.Unverified[u.ID] = time.Now() |
|
} |
|
|
|
func requestAge(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, "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.") |
|
|
|
} |
|
|
|
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) |
|
}
|
|
|