package main import ( "github.com/bwmarrin/discordgo" "sync" "os" "os/signal" "fmt" "regexp" "strings" ) var ( WORD_REGEX = regexp.MustCompile(`[a-z'’]+`) mu = sync.RWMutex{} words = map[string]struct{}{} channel string ) func getWords(m *discordgo.Message) []string { result := WORD_REGEX.FindAllString(strings.ToLower(m.Content), -1) return result } func add(m *discordgo.Message) { if m.ChannelID != channel || m.Author.Bot { return } mu.Lock() for _, word := range getWords(m) { words[word] = struct{}{} } mu.Unlock() } func report() { mu.RLock() fmt.Printf("at %d words now\n", len(words)) mu.RUnlock() } func confer(s *discordgo.Session, m *discordgo.Message) { if m.ChannelID != channel || m.Author.Bot { return } mu.RLock() abominable := []string{} for _, word := range getWords(m) { if _, ok := words[word]; ok { abominable = append(abominable, word) } } mu.RUnlock() if len(abominable) > 0 { builder := strings.Builder{} for i, abomination := range abominable { if i > 0 { builder.WriteString(", ") } fmt.Fprintf(&builder, "**%s**", abomination) } _, e := s.ChannelMessageSendReply(m.ChannelID, builder.String(), m.Reference()) yell(e) } } func must(e error) { if e != nil { panic(e) } } func yell(e error) { if e != nil { fmt.Fprintln(os.Stderr, e) } } func respond(session *discordgo.Session, message *discordgo.Message) { switch message.Type { case discordgo.MessageTypeDefault, discordgo.MessageTypeReply: confer(session, message) go func() { add(message) report() }() } } func main() { var ok bool channel, ok = os.LookupEnv("CHANNEL") if !ok { panic(ok) } session, e := discordgo.New(fmt.Sprintf("Bot %s", os.Getenv("TOKEN"))) must(e) session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) { respond(s, m.Message) }) session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageUpdate) { respond(s, m.Message) }) must(session.Open()) var ( last string count = 0 ) for { got, e := session.ChannelMessages(channel, 100, last, "", "") if e != nil { yell(e) continue } if len(got) == 0 { break } last = got[len(got)-1].ID count += len(got) fmt.Printf("msgs: %d >= %s\n", count, last) go func() { for _, m := range got { add(m) } report() }() } fmt.Printf("done! (%d msgs)\n", count) mu.RLock() for k := range words { fmt.Printf("%s ", k) } fmt.Println() mu.RUnlock() broken := make(chan os.Signal, 1) signal.Notify(broken, os.Interrupt, os.Kill) <-broken must(session.Close()) }