132 lines
3.3 KiB
Go
132 lines
3.3 KiB
Go
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()
|