ImplMessageMonitor #1
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| config.toml | ||||
							
								
								
									
										29
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								README.md
									
									
									
									
									
								
							| @@ -0,0 +1,29 @@ | ||||
| # Discord Regex Monitor | ||||
|  | ||||
| ### Example Config | ||||
| ```toml | ||||
| [DISCORD] | ||||
|   BOT_TOKEN = "" | ||||
|  | ||||
| [[SERVERS]] | ||||
|   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}" | ||||
|   [SERVERS.CHANNEL_BLACKLIST] | ||||
|     CHANNELS = ["1250537334550827078"] | ||||
|  | ||||
| [[SERVERS]] | ||||
|   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}" | ||||
|   [SERVERS.CHANNEL_BLACKLIST] | ||||
|     CHANNELS = [] | ||||
| ``` | ||||
|   | ||||
							
								
								
									
										24
									
								
								config.toml.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								config.toml.example
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| [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 = [] | ||||
|  | ||||
|  | ||||
							
								
								
									
										6
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							| @@ -2,7 +2,11 @@ module git.directme.in/Joren/SolMonitor | ||||
|  | ||||
| go 1.22.4 | ||||
|  | ||||
| require github.com/bwmarrin/discordgo v0.28.1 | ||||
| require ( | ||||
| 	git.directme.in/Joren/SmsHook v1.0.2 | ||||
| 	github.com/BurntSushi/toml v1.4.0 | ||||
| 	github.com/bwmarrin/discordgo v0.28.1 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/gorilla/websocket v1.4.2 // indirect | ||||
|   | ||||
							
								
								
									
										139
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								main.go
									
									
									
									
									
								
							| @@ -3,19 +3,66 @@ package main | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"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 | ||||
| 	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"` | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	Token = os.Getenv("DISCORD_BOT_TOKEN") | ||||
| 	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. Please set DISCORD_BOT_TOKEN environment variable.") | ||||
| 		fmt.Println("No token provided in config.toml.") | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| } | ||||
| @@ -28,8 +75,9 @@ 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 { | ||||
| @@ -42,6 +90,89 @@ 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 | ||||
| 	} | ||||
|  | ||||
| 	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) | ||||
|  | ||||
| 			if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(message) { | ||||
| 				return  | ||||
| 			} | ||||
|  | ||||
| 			s.ChannelMessageSend(server.OutputChannelID, message) | ||||
| 			MessageHistory[server.ServerID].Add(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) | ||||
|  | ||||
| 					if !server.AllowDuplicates && MessageHistory[server.ServerID].ContainsItem(message) { | ||||
| 						return  | ||||
| 					} | ||||
|  | ||||
| 					s.ChannelMessageSend(server.OutputChannelID, message) | ||||
| 					MessageHistory[server.ServerID].Add(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 | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user