diff --git a/buny.go b/buny.go
index b286d93..3b4af9a 100644
--- a/buny.go
+++ b/buny.go
@@ -11,7 +11,7 @@ import (
log "github.com/sirupsen/logrus"
)
-func buny(v xmpp.Presence) error { //nolint:gocognit
+func buny(v xmpp.Presence) error { //nolint:gocognit,gocyclo
var err error
// Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном
@@ -54,6 +54,12 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
}
evilJid := strings.SplitN(v.JID, "/", 2)[0]
+ evilNick := ""
+ evilNicks := strings.SplitN(v.From, "/", 2)
+ // Давайте-ка похэндлим нонсенс - когда у нас в строке нету разделителя
+ if len(evilNicks) > 1 {
+ evilNick = evilNicks[1]
+ }
// Обрабатываем правила чёрного списка
for _, cRoom := range roomsConnected {
@@ -71,54 +77,34 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
}
if re.MatchString(evilJid) {
- log.Infof("Hammer falls on %s", v.JID)
-
- if config.Jabber.BanPhrasesEnable {
- phrase := randomPhrase(config.Jabber.BanPhrases)
-
- if _, err := talk.Send(
- xmpp.Chat{ //nolint:exhaustruct
- Remote: room,
- Text: phrase,
- Type: v.Type,
- },
- ); err != nil {
- err := fmt.Errorf("unable to send phrase to room %s: %w", room, err)
- gTomb.Kill(err)
-
- // Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
- return nil
- }
- }
-
- // https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
- ban := "- "
-
- if bEntry.ReasonEnable {
- var t = time.Now()
- ban += fmt.Sprintf(
- "autoban at %04d.%02d.%02d %02d:%02d:%02d",
- t.Year(),
- t.Month(),
- t.Day(),
- t.Hour(),
- t.Minute(),
- t.Second(),
+ if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
+ err := fmt.Errorf(
+ "unable to ban user: id=%s, err=%w",
+ id,
+ err,
)
- } else {
- ban += ""
+
+ gTomb.Kill(err)
+
+ continue
}
- ban += "
"
+ return err
+ }
+ }
- if id, err := talk.RawInformationQuery(
- talk.JID(),
- room,
- "ban1",
- xmpp.IQTypeSet,
- "http://jabber.org/protocol/muc#admin",
- ban,
- ); err != nil {
+ for _, nickRegexp := range bEntry.NickRe {
+ re, err := regexp.Compile(nickRegexp)
+
+ if err != nil {
+ log.Errorf("Incorrect regexp in blacklist: %s, skipping", nickRegexp)
+
+ continue
+ }
+
+ if re.MatchString(evilNick) {
+ // Баним именно jid
+ if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
err := fmt.Errorf(
"unable to ban user: id=%s, err=%w",
id,
@@ -149,54 +135,7 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
}
if re.MatchString(evilJid) {
- log.Infof("Hammer falls on %s", v.JID)
-
- if config.Jabber.BanPhrasesEnable {
- phrase := randomPhrase(config.Jabber.BanPhrases)
-
- if _, err := talk.Send(
- xmpp.Chat{ //nolint:exhaustruct
- Remote: room,
- Text: phrase,
- Type: v.Type,
- },
- ); err != nil {
- err := fmt.Errorf("unable to send phrase to room %s: %w", room, err)
- gTomb.Kill(err)
-
- // Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
- return nil
- }
- }
-
- // https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
- ban := "- "
-
- if bEntry.ReasonEnable {
- var t = time.Now()
- ban += fmt.Sprintf(
- "autoban at %04d.%02d.%02d %02d:%02d:%02d",
- t.Year(),
- t.Month(),
- t.Day(),
- t.Hour(),
- t.Minute(),
- t.Second(),
- )
- } else {
- ban += ""
- }
-
- ban += "
"
-
- if id, err := talk.RawInformationQuery(
- talk.JID(),
- room,
- "ban1",
- xmpp.IQTypeSet,
- "http://jabber.org/protocol/muc#admin",
- ban,
- ); err != nil {
+ if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
err := fmt.Errorf(
"unable to ban user: id=%s, err=%w",
id,
@@ -212,6 +151,35 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
}
}
+ if bEntry.RoomName == room {
+ for _, nickRegexp := range bEntry.NickRe {
+ re, err := regexp.Compile(nickRegexp)
+
+ if err != nil {
+ log.Errorf("Incorrect regexp in blacklist: %s, skipping", nickRegexp)
+
+ continue
+ }
+
+ if re.MatchString(evilNick) {
+ // Баним именно jid
+ if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
+ err := fmt.Errorf(
+ "unable to ban user: id=%s, err=%w",
+ id,
+ err,
+ )
+
+ gTomb.Kill(err)
+
+ continue
+ }
+
+ return err
+ }
+ }
+ }
+
continue
}
}
@@ -222,4 +190,70 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
return err
}
+// squash банит указанный jid в указанной комнате.
+// reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую
+// умеет бот).
+func squash(room, jid string, reasonEnable bool, vType string) (string, error) {
+ var (
+ id string
+ err error
+ )
+
+ log.Infof("Hammer falls on %s", jid)
+
+ if config.Jabber.BanPhrasesEnable {
+ phrase := randomPhrase(config.Jabber.BanPhrases)
+
+ if _, err = talk.Send(
+ xmpp.Chat{ //nolint:exhaustruct
+ Remote: room,
+ Text: phrase,
+ Type: vType,
+ },
+ ); err != nil {
+ err = fmt.Errorf("unable to send phrase to room %s: %w", room, err)
+
+ // Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
+ return id, err
+ }
+ }
+
+ // https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
+ ban := "- "
+
+ if reasonEnable {
+ var t = time.Now()
+ ban += fmt.Sprintf(
+ "autoban at %04d.%02d.%02d %02d:%02d:%02d",
+ t.Year(),
+ t.Month(),
+ t.Day(),
+ t.Hour(),
+ t.Minute(),
+ t.Second(),
+ )
+ } else {
+ ban += ""
+ }
+
+ ban += "
"
+
+ if id, err = talk.RawInformationQuery(
+ talk.JID(),
+ room,
+ "ban1",
+ xmpp.IQTypeSet,
+ "http://jabber.org/protocol/muc#admin",
+ ban,
+ ); err != nil {
+ err = fmt.Errorf(
+ "unable to ban user: id=%s, err=%w",
+ id,
+ err,
+ )
+ }
+
+ return id, err
+}
+
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
diff --git a/data/sample_blacklist.json b/data/sample_blacklist.json
index 65340e9..2ee8810 100644
--- a/data/sample_blacklist.json
+++ b/data/sample_blacklist.json
@@ -12,6 +12,11 @@
"^[cC]hris(topher)?@",
"^(his|her)_cat@sweet.home/.*$",
"^(her|his)_dog@.*\\.street/.*"
+ ],
+ # Список регулярок nick-ов злодеев
+ "nick_re": [
+ "^(Annoying_)?[F|f]ly$",
+ "^Buzzing_Wasp$"
]
}
]
diff --git a/types.go b/types.go
index 453ebbb..1c885cc 100644
--- a/types.go
+++ b/types.go
@@ -53,6 +53,7 @@ type myBlackList struct {
RoomName string `json:"room_name,omitempty"`
ReasonEnable bool `json:"reason_enable,omitempty"`
JidRe []string `json:"jid_re,omitempty"`
+ NickRe []string `json:"nick_re,omitempty"`
} `json:"blacklist,omitempty"`
}