From 74e4f921da3cad5d45bfb93856264077d3bff75b Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 16:29:58 +0200 Subject: [PATCH 1/9] aa --- go.mod | 5 ++++- main.go | 47 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e12cebf..fcc43de 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module git.directme.in/Joren/SolMonitor go 1.22.4 -require github.com/bwmarrin/discordgo v0.28.1 +require ( + github.com/BurntSushi/toml v1.4.0 + github.com/bwmarrin/discordgo v0.28.1 +) require ( github.com/gorilla/websocket v1.4.2 // indirect diff --git a/main.go b/main.go index 49e4195..70ca308 100644 --- a/main.go +++ b/main.go @@ -4,18 +4,36 @@ import ( "fmt" "os" - + "github.com/BurntSushi/toml" "github.com/bwmarrin/discordgo" ) var ( - Token string + Token string + ServerID string ) func init() { - Token = os.Getenv("DISCORD_BOT_TOKEN") + var config struct { + Token string `toml:"DISCORD_BOT_TOKEN"` + ServerID string `toml:"DISCORD_SERVER_ID"` + } + + if _, err := toml.DecodeFile("config.toml", &config); err != nil { + fmt.Println("Error loading config:", err) + os.Exit(1) + } + + Token = config.Token + ServerID = config.ServerID + if Token == "" { - fmt.Println("No token provided. Please set DISCORD_BOT_TOKEN environment variable.") + 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) } } @@ -28,6 +46,7 @@ func main() { } dg.AddHandler(ready) + dg.AddHandler(messageCreate) dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages @@ -42,6 +61,24 @@ func main() { } func ready(s *discordgo.Session, event *discordgo.Ready) { - s.UpdateGameStatus(0, "Monitoring addresses") + s.UpdateGameStatus(0, "Monitoring messages") +} + +func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.ID == s.State.User.ID { + return + } + + channel, err := s.State.Channel(m.ChannelID) + if err != nil { + fmt.Println("Error getting channel:", err) + return + } + + if channel.GuildID != ServerID { + return + } + + fmt.Printf("Message from %s: %s\n", m.Author.Username, m.Content) } From 4f9fed5655dc2816fdd8ac397dfb1ecdc134f17d Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 16:30:12 +0200 Subject: [PATCH 2/9] aa --- .gitignore | 1 + config.toml.example | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 .gitignore create mode 100644 config.toml.example diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b6c096 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.toml diff --git a/config.toml.example b/config.toml.example new file mode 100644 index 0000000..ab8c2ed --- /dev/null +++ b/config.toml.example @@ -0,0 +1,2 @@ +DISCORD_BOT_TOKEN = "your_bot_token" +DISCORD_SERVER_ID = "your_server_id" From 74ddfb5b529dafe6dcecf47472c5cd233a19bd24 Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 16:50:31 +0200 Subject: [PATCH 3/9] Monitor every message --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 70ca308..e36e4f9 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ func main() { dg.AddHandler(ready) dg.AddHandler(messageCreate) - dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages + dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages | discordgo.IntentMessageContent err = dg.Open() if err != nil { From 1b9cbd88c412d0c6071f375222ac739a3baf5575 Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:06:13 +0200 Subject: [PATCH 4/9] Add monitor --- main.go | 160 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 71 deletions(-) diff --git a/main.go b/main.go index e36e4f9..0c0901e 100644 --- a/main.go +++ b/main.go @@ -1,84 +1,102 @@ -package main + package main -import ( - "fmt" - "os" + 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 -) + var ( + Token string + ServerID string + OutputChannelID string + ) -func init() { - var config struct { - Token string `toml:"DISCORD_BOT_TOKEN"` - ServerID string `toml:"DISCORD_SERVER_ID"` + func init() { + var config struct { + Token string `toml:"DISCORD_BOT_TOKEN"` + ServerID string `toml:"DISCORD_SERVER_ID"` + OutputChannelID string `toml:"OUTPUT_CHANNEL_ID"` + } + + 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) + } } - if _, err := toml.DecodeFile("config.toml", &config); err != nil { - fmt.Println("Error loading config:", err) - 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 {} } - Token = config.Token - ServerID = config.ServerID - - if Token == "" { - fmt.Println("No token provided in config.toml.") - os.Exit(1) + func ready(s *discordgo.Session, event *discordgo.Ready) { + s.UpdateGameStatus(0, "Monitoring messages") } - if ServerID == "" { - fmt.Println("No server ID provided in config.toml.") - os.Exit(1) - } -} + func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.ID == s.State.User.ID { + return + } -func main() { - dg, err := discordgo.New("Bot " + Token) - if err != nil { - fmt.Println("Error creating Discord session:", err) - return + channel, err := s.State.Channel(m.ChannelID) + if err != nil { + fmt.Println("Error getting channel:", err) + return + } + + if channel.GuildID != ServerID { + return + } + + fmt.Printf("Message from %s: %s\n", m.Author.Username, m.Content) + + + 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) + } } - 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 - } - - channel, err := s.State.Channel(m.ChannelID) - if err != nil { - fmt.Println("Error getting channel:", err) - return - } - - if channel.GuildID != ServerID { - return - } - - fmt.Printf("Message from %s: %s\n", m.Author.Username, m.Content) -} - From 06b66dd76f89d041d84e892e33b3184d5a4495d9 Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:26:44 +0200 Subject: [PATCH 5/9] Add option for multiple regexes to be matched --- config.toml.example | 26 +++++- main.go | 223 +++++++++++++++++++++++++++----------------- 2 files changed, 164 insertions(+), 85 deletions(-) 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 +} + From dca627e422544956b1d9ec481f9e75126201dfe5 Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:31:53 +0200 Subject: [PATCH 6/9] readme --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index e69de29..4ead4e2 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,27 @@ +# Discord Regex Monitor + +### Example Config +```toml +[DISCORD] + BOT_TOKEN = "" + +[[SERVERS]] + SERVER_ID = "1050204101826334999" + OUTPUT_CHANNEL_ID = "1250585834726621999" + 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 = ["1250537334550827078"] + +[[SERVERS]] + SERVER_ID = "1250885747062345999" + OUTPUT_CHANNEL_ID = "1250585834726621999" + PREFIX_ENABLED = true + [SERVERS.COIN_REGEXES] + Ethereum = "0x[a-fA-F0-9]{40}" + Solana = "[1-9A-HJ-NP-Za-km-z]{32,44}" + [SERVERS.CHANNEL_BLACKLIST] + CHANNELS = [] +``` From 8fb0838cc070af61d48a212eacf36574d6d89e2c Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:52:38 +0200 Subject: [PATCH 7/9] Add option to allow dupes --- go.mod | 1 + main.go | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index fcc43de..9d5647b 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.directme.in/Joren/SolMonitor go 1.22.4 require ( + git.directme.in/Joren/SmsHook v1.0.2 github.com/BurntSushi/toml v1.4.0 github.com/bwmarrin/discordgo v0.28.1 ) diff --git a/main.go b/main.go index fb56513..39f9d8c 100644 --- a/main.go +++ b/main.go @@ -5,16 +5,19 @@ import ( "os" "regexp" + "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 - PrefixEnabled bool + MessageHistory map[string]*ringbuffer.RingBuffer ) type ServerConfig struct { @@ -24,7 +27,8 @@ type ServerConfig struct { ChannelBlacklist struct { Channels []string `toml:"CHANNELS"` } `toml:"CHANNEL_BLACKLIST"` - PrefixEnabled bool `toml:"PREFIX_ENABLED"` + PrefixEnabled bool `toml:"PREFIX_ENABLED"` + AllowDuplicates bool `toml:"ALLOW_DUPLICATES"` } func init() { @@ -45,6 +49,7 @@ func init() { 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 { @@ -52,6 +57,9 @@ func init() { CoinRegexes[coin] = regexp.MustCompile(fullRegex) } ChannelBlacklist[server.ServerID] = server.ChannelBlacklist.Channels + + // Initialize MessageHistory for each server + MessageHistory[server.ServerID] = ringbuffer.NewRingBuffer(100) // Adjust buffer size as needed } if Token == "" { @@ -116,7 +124,13 @@ func checkMessageContent(s *discordgo.Session, server ServerConfig, m *discordgo if len(match) > 0 { matchedAddress := match[0] message := formatMessage(server, coin, m.Author.Username, matchedAddress) + + if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(message) { + return // Skip sending if duplicates are not allowed and message is in history + } + s.ChannelMessageSend(server.OutputChannelID, message) + MessageHistory[server.ServerID].Add(message) } } } @@ -129,7 +143,13 @@ func checkEmbeds(s *discordgo.Session, server ServerConfig, m *discordgo.Message if len(match) > 0 { matchedAddress := match[0] message := formatMessage(server, coin, m.Author.Username, matchedAddress) + + if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(message) { + return + } + s.ChannelMessageSend(server.OutputChannelID, message) + MessageHistory[server.ServerID].Add(message) } } } From db09b0af99e9ed3125b4e5526ec7e31febdebe17 Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:53:19 +0200 Subject: [PATCH 8/9] Increase buffer siwe --- main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 39f9d8c..b96be03 100644 --- a/main.go +++ b/main.go @@ -57,9 +57,8 @@ func init() { CoinRegexes[coin] = regexp.MustCompile(fullRegex) } ChannelBlacklist[server.ServerID] = server.ChannelBlacklist.Channels - - // Initialize MessageHistory for each server - MessageHistory[server.ServerID] = ringbuffer.NewRingBuffer(100) // Adjust buffer size as needed + + MessageHistory[server.ServerID] = ringbuffer.NewRingBuffer(4096) } if Token == "" { @@ -126,7 +125,7 @@ func checkMessageContent(s *discordgo.Session, server ServerConfig, m *discordgo message := formatMessage(server, coin, m.Author.Username, matchedAddress) if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(message) { - return // Skip sending if duplicates are not allowed and message is in history + return } s.ChannelMessageSend(server.OutputChannelID, message) From 74198b8930b36e3b6bdd85cc155dbf74952e17dd Mon Sep 17 00:00:00 2001 From: Joren Date: Tue, 18 Jun 2024 17:54:12 +0200 Subject: [PATCH 9/9] Update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4ead4e2..b0fc2e1 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ SERVER_ID = "1050204101826334999" OUTPUT_CHANNEL_ID = "1250585834726621999" PREFIX_ENABLED = true + ALLOW_DUPLICATES = false [SERVERS.COIN_REGEXES] Bitcoin = "[13][a-km-zA-HJ-NP-Z1-9]{25,34}" Ethereum = "0x[a-fA-F0-9]{40}" @@ -19,6 +20,7 @@ SERVER_ID = "1250885747062345999" OUTPUT_CHANNEL_ID = "1250585834726621999" PREFIX_ENABLED = true + ALLOW_DUPLICATES = false [SERVERS.COIN_REGEXES] Ethereum = "0x[a-fA-F0-9]{40}" Solana = "[1-9A-HJ-NP-Za-km-z]{32,44}"