package domainblock import ( "fmt" "net/url" "regexp" "strings" "git.nakama.town/fmartingr/butterrobot/internal/model" "git.nakama.town/fmartingr/butterrobot/internal/plugin" ) // DomainBlockPlugin is a plugin that blocks messages containing links from specific domains type DomainBlockPlugin struct { plugin.BasePlugin } // Debug helper to check if RequiresConfig is working func (p *DomainBlockPlugin) RequiresConfig() bool { return true } // New creates a new DomainBlockPlugin instance func New() *DomainBlockPlugin { return &DomainBlockPlugin{ BasePlugin: plugin.BasePlugin{ ID: "security.domainblock", Name: "Domain Blocker", Help: "Blocks messages containing links from configured domains", ConfigRequired: true, }, } } // extractDomains extracts domains from a message text func extractDomains(text string) []string { // URL regex pattern urlPattern := regexp.MustCompile(`https?://([^\s/$.?#].[^\s]*)`) matches := urlPattern.FindAllStringSubmatch(text, -1) domains := make([]string, 0, len(matches)) for _, match := range matches { if len(match) < 2 { continue } // Try to parse the URL to extract the domain urlStr := match[0] parsedURL, err := url.Parse(urlStr) if err != nil { continue } // Extract the domain (host) from the URL domain := parsedURL.Host // Remove port if present if i := strings.IndexByte(domain, ':'); i >= 0 { domain = domain[:i] } domains = append(domains, strings.ToLower(domain)) } return domains } // OnMessage processes incoming messages func (p *DomainBlockPlugin) OnMessage(msg *model.Message, config map[string]interface{}) []*model.MessageAction { // Skip messages from bots if msg.FromBot { return nil } // Get blocked domains from config blockedDomainsStr, ok := config["blocked_domains"].(string) if !ok || blockedDomainsStr == "" { return nil // No blocked domains configured } // Split and clean blocked domains blockedDomains := strings.Split(blockedDomainsStr, ",") for i, domain := range blockedDomains { blockedDomains[i] = strings.ToLower(strings.TrimSpace(domain)) } // Extract domains from message messageDomains := extractDomains(msg.Text) if len(messageDomains) == 0 { return nil // No domains in message } // Check if any domains in the message are blocked for _, msgDomain := range messageDomains { for _, blockedDomain := range blockedDomains { if blockedDomain == "" { continue } if strings.HasSuffix(msgDomain, blockedDomain) || msgDomain == blockedDomain { // Domain is blocked, create actions // 1. Create a delete message action deleteAction := &model.MessageAction{ Type: model.ActionDeleteMessage, MessageID: msg.ID, Chat: msg.Chat, Channel: msg.Channel, } // 2. Create a notification message action notificationMsg := &model.Message{ Text: fmt.Sprintf("I don't like links from %s 🙈", blockedDomain), Chat: msg.Chat, Channel: msg.Channel, } sendAction := &model.MessageAction{ Type: model.ActionSendMessage, Message: notificationMsg, Chat: msg.Chat, Channel: msg.Channel, } return []*model.MessageAction{deleteAction, sendAction} } } } return nil } // Plugin is registered in app.go, not using init()