package main import ( "fmt" "os" "regexp" "strings" "github.com/BurntSushi/toml" "github.com/bwmarrin/discordgo" "git.directme.in/Joren/SmsHook/ringbuffer" ) var ( Token string Servers []ServerConfig CoinRegexes map[string]*regexp.Regexp ChannelBlacklist map[string][]string MessageHistory map[string]*ringbuffer.RingBuffer ) type ServerConfig struct { ServerID string `toml:"SERVER_ID"` OutputChannelID string `toml:"OUTPUT_CHANNEL_ID"` CoinRegexes map[string]string `toml:"COIN_REGEXES"` ChannelBlacklist struct { Channels []string `toml:"CHANNELS"` } `toml:"CHANNEL_BLACKLIST"` PrefixEnabled bool `toml:"PREFIX_ENABLED"` AllowDuplicates bool `toml:"ALLOW_DUPLICATES"` ServerIDEnabled bool `toml:"SERVER_ID_ENABLED"` ChannelIDEnabled bool `toml:"CHANNEL_ID_ENABLED"` MessageLinkEnabled bool `toml:"MESSAGE_LINK_ENABLED"` } func init() { var config struct { Discord struct { BotToken string `toml:"BOT_TOKEN"` } `toml:"DISCORD"` Servers []ServerConfig `toml:"SERVERS"` } if _, err := toml.DecodeFile("config.toml", &config); err != nil { fmt.Println("Error loading config:", err) os.Exit(1) } Token = config.Discord.BotToken Servers = config.Servers CoinRegexes = make(map[string]*regexp.Regexp) ChannelBlacklist = make(map[string][]string) MessageHistory = make(map[string]*ringbuffer.RingBuffer) for _, server := range Servers { for coin, regex := range server.CoinRegexes { fullRegex := fmt.Sprintf(`\b%s\b`, regex) CoinRegexes[coin] = regexp.MustCompile(fullRegex) } ChannelBlacklist[server.ServerID] = server.ChannelBlacklist.Channels MessageHistory[server.ServerID] = ringbuffer.NewRingBuffer(4096) } if Token == "" { fmt.Println("No token provided in config.toml.") os.Exit(1) } } func main() { dg, err := discordgo.New("Bot " + Token) if err != nil { fmt.Println("Error creating Discord session:", err) return } dg.AddHandler(ready) dg.AddHandler(messageCreate) dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages | discordgo.IntentMessageContent err = dg.Open() if err != nil { fmt.Println("Error opening connection:", err) return } fmt.Println("Bot is now running. Press CTRL+C to exit.") select {} } func ready(s *discordgo.Session, event *discordgo.Ready) { s.UpdateGameStatus(0, "Monitoring messages") } func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Author.ID == s.State.User.ID { return } for _, server := range Servers { if m.GuildID == server.ServerID { channel, err := s.State.Channel(m.ChannelID) if err != nil { fmt.Println("Error getting channel:", err) return } if isChannelBlacklisted(server.ServerID, channel.ID) { return } guild, err := s.Guild(m.GuildID) if err != nil { fmt.Println("Error getting guild:", err) return } checkMessageContent(s, server, m, guild.Name) checkEmbeds(s, server, m, guild.Name) return } } } func checkMessageContent(s *discordgo.Session, server ServerConfig, m *discordgo.MessageCreate, serverName string) { for coin, regex := range CoinRegexes { match := regex.FindStringSubmatch(m.Content) if len(match) > 0 { matchedAddress := match[0] matchedAddress = strings.TrimSpace(matchedAddress) message := formatMessage(server, coin, m.Author.Username, matchedAddress, serverName, m) if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(matchedAddress) { return } s.ChannelMessageSend(server.OutputChannelID, message) MessageHistory[server.ServerID].Add(matchedAddress) } } } func checkEmbeds(s *discordgo.Session, server ServerConfig, m *discordgo.MessageCreate, serverName string) { for _, embed := range m.Message.Embeds { if embed.Type == "rich" && embed.Description != "" { for coin, regex := range CoinRegexes { match := regex.FindStringSubmatch(embed.Description) if len(match) > 0 { matchedAddress := match[0] matchedAddress = strings.TrimSpace(matchedAddress) message := formatMessage(server, coin, m.Author.Username, matchedAddress, serverName, m) if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(matchedAddress) { return } s.ChannelMessageSend(server.OutputChannelID, message) MessageHistory[server.ServerID].Add(matchedAddress) } } } } } func formatMessage(server ServerConfig, coin, username, address, serverName string, m *discordgo.MessageCreate) string { message := address if server.PrefixEnabled { message = fmt.Sprintf("%s: %s", coin, address) } if server.ServerIDEnabled { message = fmt.Sprintf("%s (Server: %s)", message, serverName) } if server.ChannelIDEnabled { message = fmt.Sprintf("%s (From: <#%s>)", message, m.ChannelID) } if server.MessageLinkEnabled { message = fmt.Sprintf("%s ([Link]())", message, m.GuildID, m.ChannelID, m.ID) } return message } func isChannelBlacklisted(serverID, channelID string) bool { blacklistedChannels, ok := ChannelBlacklist[serverID] if !ok { return false } for _, id := range blacklistedChannels { if id == channelID { return true } } return false }