204 lines
5.2 KiB
Go
204 lines
5.2 KiB
Go
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](<https://discord.com/channels/%s/%s/%s>))", 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
|
|
}
|
|
|