Implement ban by nick regexp (in MUCs)

* Move ban action to separate function
* Implement ban by nick regexp
This commit is contained in:
eleksir
2023-08-20 10:55:02 -07:00
parent 939ceaebfb
commit 39ac09f82a
3 changed files with 133 additions and 93 deletions

166
buny.go
View File

@@ -11,7 +11,7 @@ import (
log "github.com/sirupsen/logrus" 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 var err error
// Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном // Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном
@@ -54,6 +54,12 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
} }
evilJid := strings.SplitN(v.JID, "/", 2)[0] 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 { for _, cRoom := range roomsConnected {
@@ -71,54 +77,34 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
} }
if re.MatchString(evilJid) { if re.MatchString(evilJid) {
log.Infof("Hammer falls on %s", v.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,
)
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) gTomb.Kill(err)
// Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше continue
return nil }
return err
} }
} }
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением for _, nickRegexp := range bEntry.NickRe {
ban := "<item affiliation='outcast' jid='" + evilJid + "'>" re, err := regexp.Compile(nickRegexp)
if bEntry.ReasonEnable { if err != nil {
var t = time.Now() log.Errorf("Incorrect regexp in blacklist: %s, skipping", nickRegexp)
ban += fmt.Sprintf(
"<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>", continue
t.Year(),
t.Month(),
t.Day(),
t.Hour(),
t.Minute(),
t.Second(),
)
} else {
ban += "<reason />"
} }
ban += "</item>" if re.MatchString(evilNick) {
// Баним именно jid
if id, err := talk.RawInformationQuery( if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
talk.JID(),
room,
"ban1",
xmpp.IQTypeSet,
"http://jabber.org/protocol/muc#admin",
ban,
); err != nil {
err := fmt.Errorf( err := fmt.Errorf(
"unable to ban user: id=%s, err=%w", "unable to ban user: id=%s, err=%w",
id, id,
@@ -149,30 +135,93 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
} }
if re.MatchString(evilJid) { if re.MatchString(evilJid) {
log.Infof("Hammer falls on %s", v.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
}
}
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
}
}
}
}
}
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 { if config.Jabber.BanPhrasesEnable {
phrase := randomPhrase(config.Jabber.BanPhrases) phrase := randomPhrase(config.Jabber.BanPhrases)
if _, err := talk.Send( if _, err = talk.Send(
xmpp.Chat{ //nolint:exhaustruct xmpp.Chat{ //nolint:exhaustruct
Remote: room, Remote: room,
Text: phrase, Text: phrase,
Type: v.Type, Type: vType,
}, },
); err != nil { ); err != nil {
err := fmt.Errorf("unable to send phrase to room %s: %w", room, err) err = fmt.Errorf("unable to send phrase to room %s: %w", room, err)
gTomb.Kill(err)
// Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше // Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
return nil return id, err
} }
} }
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением // https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
ban := "<item affiliation='outcast' jid='" + evilJid + "'>" ban := "<item affiliation='outcast' jid='" + jid + "'>"
if bEntry.ReasonEnable { if reasonEnable {
var t = time.Now() var t = time.Now()
ban += fmt.Sprintf( ban += fmt.Sprintf(
"<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>", "<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>",
@@ -189,7 +238,7 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
ban += "</item>" ban += "</item>"
if id, err := talk.RawInformationQuery( if id, err = talk.RawInformationQuery(
talk.JID(), talk.JID(),
room, room,
"ban1", "ban1",
@@ -197,29 +246,14 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
"http://jabber.org/protocol/muc#admin", "http://jabber.org/protocol/muc#admin",
ban, ban,
); err != nil { ); err != nil {
err := fmt.Errorf( err = fmt.Errorf(
"unable to ban user: id=%s, err=%w", "unable to ban user: id=%s, err=%w",
id, id,
err, err,
) )
gTomb.Kill(err)
continue
} }
return err return id, err
}
}
continue
}
}
}
}
}
return err
} }
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

View File

@@ -12,6 +12,11 @@
"^[cC]hris(topher)?@", "^[cC]hris(topher)?@",
"^(his|her)_cat@sweet.home/.*$", "^(his|her)_cat@sweet.home/.*$",
"^(her|his)_dog@.*\\.street/.*" "^(her|his)_dog@.*\\.street/.*"
],
# Список регулярок nick-ов злодеев
"nick_re": [
"^(Annoying_)?[F|f]ly$",
"^Buzzing_Wasp$"
] ]
} }
] ]

View File

@@ -53,6 +53,7 @@ type myBlackList struct {
RoomName string `json:"room_name,omitempty"` RoomName string `json:"room_name,omitempty"`
ReasonEnable bool `json:"reason_enable,omitempty"` ReasonEnable bool `json:"reason_enable,omitempty"`
JidRe []string `json:"jid_re,omitempty"` JidRe []string `json:"jid_re,omitempty"`
NickRe []string `json:"nick_re,omitempty"`
} `json:"blacklist,omitempty"` } `json:"blacklist,omitempty"`
} }