diff --git a/config.toml.example b/config.toml.example index ab8c2ed..abbe7c2 100644 --- a/config.toml.example +++ b/config.toml.example @@ -1,2 +1,24 @@ -DISCORD_BOT_TOKEN = "your_bot_token" -DISCORD_SERVER_ID = "your_server_id" +[DISCORD] + BOT_TOKEN = "" + +[[SERVERS]] + SERVER_ID = "" + OUTPUT_CHANNEL_ID = "" + PREFIX_ENABLED = true + [SERVERS.COIN_REGEXES] + Bitcoin = "[13][a-km-zA-HJ-NP-Z1-9]{25,34}" + Ethereum = "0x[a-fA-F0-9]{40}" + [SERVERS.CHANNEL_BLACKLIST] + CHANNELS = [""] + +[[SERVERS]] + SERVER_ID = "" + OUTPUT_CHANNEL_ID = "" + PREFIX_ENABLED = false + [SERVERS.COIN_REGEXES] + Ethereum = "0x[a-fA-F0-9]{40}" + Solana = "[1-9A-HJ-NP-Za-km-z]{32,44}" + [SERVERS.CHANNEL_BLACKLIST] + CHANNELS = [] + + diff --git a/main.go b/main.go index 0c0901e..fb56513 100644 --- a/main.go +++ b/main.go @@ -1,102 +1,159 @@ - package main +package main - import ( - "fmt" - "os" - "regexp" +import ( + "fmt" + "os" + "regexp" - "github.com/BurntSushi/toml" - "github.com/bwmarrin/discordgo" - ) + "github.com/BurntSushi/toml" + "github.com/bwmarrin/discordgo" +) - var ( - Token string - ServerID string - OutputChannelID string - ) +var ( + Token string + Servers []ServerConfig + CoinRegexes map[string]*regexp.Regexp + ChannelBlacklist map[string][]string + PrefixEnabled bool +) - func init() { - var config struct { - Token string `toml:"DISCORD_BOT_TOKEN"` - ServerID string `toml:"DISCORD_SERVER_ID"` - OutputChannelID string `toml:"OUTPUT_CHANNEL_ID"` - } +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"` +} - if _, err := toml.DecodeFile("config.toml", &config); err != nil { - fmt.Println("Error loading config:", err) - os.Exit(1) - } - - Token = config.Token - ServerID = config.ServerID - OutputChannelID = config.OutputChannelID - - if Token == "" { - fmt.Println("No token provided in config.toml.") - os.Exit(1) - } - - if ServerID == "" { - fmt.Println("No server ID provided in config.toml.") - os.Exit(1) - } - - if OutputChannelID == "" { - fmt.Println("No output channel ID in config.toml") - os.Exit(1) - } +func init() { + var config struct { + Discord struct { + BotToken string `toml:"BOT_TOKEN"` + } `toml:"DISCORD"` + Servers []ServerConfig `toml:"SERVERS"` } - 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 {} + if _, err := toml.DecodeFile("config.toml", &config); err != nil { + fmt.Println("Error loading config:", err) + os.Exit(1) } - func ready(s *discordgo.Session, event *discordgo.Ready) { - s.UpdateGameStatus(0, "Monitoring messages") + Token = config.Discord.BotToken + Servers = config.Servers + + CoinRegexes = make(map[string]*regexp.Regexp) + ChannelBlacklist = make(map[string][]string) + + 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 } - func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { - if m.Author.ID == s.State.User.ID { - return - } + if Token == "" { + fmt.Println("No token provided in config.toml.") + os.Exit(1) + } +} - channel, err := s.State.Channel(m.ChannelID) - if err != nil { - fmt.Println("Error getting channel:", err) - return - } +func main() { + dg, err := discordgo.New("Bot " + Token) + if err != nil { + fmt.Println("Error creating Discord session:", err) + return + } - if channel.GuildID != ServerID { - return - } + dg.AddHandler(ready) + dg.AddHandler(messageCreate) - fmt.Printf("Message from %s: %s\n", m.Author.Username, m.Content) + dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages | discordgo.IntentMessageContent + err = dg.Open() + if err != nil { + fmt.Println("Error opening connection:", err) + return + } - re := regexp.MustCompile(`\b\w{36,44}\b`) - match := re.FindStringSubmatch(m.Content) - if len(match) > 0 { - matchedWord := match[0] - message := fmt.Sprintf("%s", matchedWord) - s.ChannelMessageSend(OutputChannelID, message) + 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 + } + + checkMessageContent(s, server, m) + checkEmbeds(s, server, m) + return + } + } +} + +func checkMessageContent(s *discordgo.Session, server ServerConfig, m *discordgo.MessageCreate) { + for coin, regex := range CoinRegexes { + match := regex.FindStringSubmatch(m.Content) + if len(match) > 0 { + matchedAddress := match[0] + message := formatMessage(server, coin, m.Author.Username, matchedAddress) + s.ChannelMessageSend(server.OutputChannelID, message) + } + } +} + +func checkEmbeds(s *discordgo.Session, server ServerConfig, m *discordgo.MessageCreate) { + 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] + message := formatMessage(server, coin, m.Author.Username, matchedAddress) + s.ChannelMessageSend(server.OutputChannelID, message) + } + } + } + } +} + +func formatMessage(server ServerConfig, coin, username, address string) string { + if server.PrefixEnabled { + return fmt.Sprintf("%s: %s", coin, address) + } + return address +} + +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 +} +