Compare commits

...

3 Commits

Author SHA1 Message Date
eleksir
a9935abf53 More details in ban log message 2023-10-19 21:44:59 +03:00
eleksir
75b9ab8a8b Use warn loglevel for message about ban 2023-10-19 09:56:29 +03:00
eleksir
e48be3936e Add golangci-lint and fix a bit of errors 2023-10-15 18:16:45 +03:00
6 changed files with 147 additions and 24 deletions

69
.golangci.yml Normal file
View File

@@ -0,0 +1,69 @@
run:
tests: false
skip-dirs:
- data
- vendor
modules-download-mode: readonly
allow-parallel-runners: true
go: '1.21'
output:
sort-results: true
linters-settings:
gosec:
excludes:
# Оно не используется для повышения безопасности или каких-то таких секъюрых вещей, оно используется для выборки
# произвольного элемента из массива, так что ИДИ НАХУЙ с этой проверкой и не еби мозги липовой безопасностью.
- G404 # Insecure random number source (rand)
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- asasalint
- asciicheck
- bodyclose
- containedctx
- contextcheck
- decorder
- durationcheck
- errchkjson
- errorlint
- exhaustive
- exhaustruct
- exportloopref
- ginkgolinter
- gci
- gocheckcompilerdirectives
- gocritic
- godot
- goerr113
- gofmt
- goimports
- gosec
- gosmopolitan
- grouper
- importas
- ireturn
- makezero
- mirror
- nakedret
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- nonamedreturns
- predeclared
- promlinter
- reassign
- revive
- rowserrcheck
- stylecheck
- unconvert
- wastedassign
- whitespace
- wsl

View File

@@ -5,7 +5,7 @@ FILELIST=collection.go types.go globals.go lib.go event_parser.go buny.go comman
BINARY=buny-jabber-bot BINARY=buny-jabber-bot
# На windows имя бинарника может зависеть не только от платформы, но и от выранной цели, для linux-а суффикс .exe # На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe
# не нужен # не нужен
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
ifeq ($(strip $(GOOS)),) ifeq ($(strip $(GOOS)),)
@@ -23,10 +23,10 @@ define IFS
endef endef
# Используем классические таргеты, где первый встречаемый является таргетом по-умолчанию ## Используем классические таргеты, где первый встречаемый является таргетом по-умолчанию
all: clean build all: clean build
## Этот таргет собирает бинарь
build: build:
# Ну и дальше просто билдим бинарник средствами гошки # Ну и дальше просто билдим бинарник средствами гошки
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
@@ -45,12 +45,12 @@ else
endif endif
# Удаляем бинарник средствами go ## Удаляем бинарник средствами go
clean: clean:
go clean go clean
# Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом. ## Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом.
upgrade: upgrade:
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
# вариант с jetbrains golang на windows или powershell на windows # вариант с jetbrains golang на windows или powershell на windows

View File

@@ -13,8 +13,8 @@
Имеет возможность заносить пользователей в бан-лист, согласно заданным в чёрном списке правилам: по совпадению с Имеет возможность заносить пользователей в бан-лист, согласно заданным в чёрном списке правилам: по совпадению с
регулярными выражениями в nick-е или jid-е злодея, а также по регулярным выражениям характерных фраз. Правила можно регулярными выражениями в nick-е или jid-е злодея, а также по регулярным выражениям характерных фраз. Правила можно
настроить как глобально, для всех комнат, где присутсвует бот, так и для каждой комнаты отдельно. При изменении списка настроить как глобально, для всех комнат, где присутствует бот, так и для каждой комнаты отдельно. При изменении списка
правил бота надо перезапускать. правил бота не надо перезапускать, достаточно отдать ему команду rehash либо в приват, либо прям в чатике.
## Что он не может? ## Что он не может?
@@ -46,7 +46,7 @@ make
Почему нельзя оставить комнату анонимной? А тут всё просто, в банлист заносится реальный jid пользователя, а не его ник. Почему нельзя оставить комнату анонимной? А тут всё просто, в банлист заносится реальный jid пользователя, а не его ник.
Соответственно, бот должен видеть этот самый реальный jid. В анонимной комнате бот не сможет увидеть реальный jid. Соответственно, бот должен видеть этот самый реальный jid. В анонимной комнате бот не сможет увидеть реальный jid.
А автокик - это конечно хорошо, но есть нюанс: можно, например, гадить ником. А автокик - это конечно хорошо, но есть нюанс: можно, например, гадить ником, поэтому бот в автокик не умеет.
## Как работает бан? ## Как работает бан?

74
buny.go
View File

@@ -86,7 +86,16 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
log.Debugf("Checking jid %s vs global blacklist regex %s", evilJid, jidRegexp) log.Debugf("Checking jid %s vs global blacklist regex %s", evilJid, jidRegexp)
if re.MatchString(evilJid) { if re.MatchString(evilJid) {
if id, err := squash(room, evilJid, room+"/"+evilNick, bEntry.ReasonEnable, v.Type); err != nil { log.Warnf(
"Hammer falls on %s (%s): jid matches with global blacklist entry: %s",
v.From,
evilJid,
jidRegexp,
)
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
if 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,
@@ -116,8 +125,17 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
log.Debugf("Checking nick %s vs global blacklist regex %s", evilNick, nickRegexp) log.Debugf("Checking nick %s vs global blacklist regex %s", evilNick, nickRegexp)
if re.MatchString(evilNick) { if re.MatchString(evilNick) {
log.Warnf(
"Hammer falls on %s (%s): nick matches with global blacklist entry: %s",
v.From,
evilJid,
nickRegexp,
)
// Баним именно jid // Баним именно jid
if id, err := squash(room, evilJid, room+"/"+evilNick, bEntry.ReasonEnable, v.Type); err != nil { id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
if 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,
@@ -152,7 +170,16 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
log.Debugf("Checking jid %s vs room %s blacklist regex %s", evilJid, room, jidRegexp) log.Debugf("Checking jid %s vs room %s blacklist regex %s", evilJid, room, jidRegexp)
if re.MatchString(evilJid) { if re.MatchString(evilJid) {
if id, err := squash(room, evilJid, room+"/"+evilNick, bEntry.ReasonEnable, v.Type); err != nil { log.Warnf(
"Hammer falls on %s (%s): jid matches with room blacklist entry: %s",
v.From,
evilJid,
jidRegexp,
)
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
if 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,
@@ -183,8 +210,17 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
log.Debugf("Checking nick %s vs room %s blacklist regex %s", evilJid, room, nickRegexp) log.Debugf("Checking nick %s vs room %s blacklist regex %s", evilJid, room, nickRegexp)
if re.MatchString(evilNick) { if re.MatchString(evilNick) {
log.Warnf(
"Hammer falls on %s (%s): nick matches with room blacklist entry: %s",
v.From,
evilJid,
nickRegexp,
)
// Баним именно jid // Баним именно jid
if id, err := squash(room, evilJid, room+"/"+evilNick, bEntry.ReasonEnable, v.Type); err != nil { id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
if 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,
@@ -209,7 +245,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
return err return err
} }
// bunyChat проиводит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого // bunyChat производит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого
// шаблона банит участника чата. // шаблона банит участника чата.
func bunyChat(v xmpp.Chat) error { func bunyChat(v xmpp.Chat) error {
var ( var (
@@ -239,7 +275,17 @@ func bunyChat(v xmpp.Chat) error {
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp) log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
if re.MatchString(v.Text) { if re.MatchString(v.Text) {
if id, err := squash(room, getRealJIDfromNick(v.Remote), v.Remote, bEntry.ReasonEnable, v.Type); err != nil { realJID := getRealJIDfromNick(v.Remote)
log.Warnf(
"Hammer falls on %s (%s): phrase matches with global blacklist entry: %s vs %s",
v.Remote,
realJID,
v.Text,
phraseRegexp,
)
if id, err := squash(room, realJID, bEntry.ReasonEnable, v.Type); 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,
@@ -272,7 +318,17 @@ func bunyChat(v xmpp.Chat) error {
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp) log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
if re.MatchString(v.Text) { if re.MatchString(v.Text) {
if id, err := squash(room, getRealJIDfromNick(v.Remote), v.Remote, bEntry.ReasonEnable, v.Type); err != nil { realJID := getRealJIDfromNick(v.Remote)
log.Warnf(
"Hammer falls on %s (%s): phrase matches with room blacklist entry: %s vs %s",
v.Remote,
realJID,
v.Text,
phraseRegexp,
)
if id, err := squash(room, realJID, bEntry.ReasonEnable, v.Type); 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,
@@ -298,14 +354,12 @@ func bunyChat(v xmpp.Chat) error {
// squash банит указанный jid в указанной комнате. // squash банит указанный jid в указанной комнате.
// reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую // reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую
// умеет бот). // умеет бот).
func squash(room, jid string, nick string, reasonEnable bool, vType string) (string, error) { func squash(room, jid string, reasonEnable bool, vType string) (string, error) {
var ( var (
id string id string
err error err error
) )
log.Infof("Hammer falls on %s(%s)", nick, jid)
if config.Jabber.BanPhrasesEnable { if config.Jabber.BanPhrasesEnable {
phrase := randomPhrase(config.Jabber.BanPhrases) phrase := randomPhrase(config.Jabber.BanPhrases)

View File

@@ -54,7 +54,7 @@ func cmd(v xmpp.Chat) error {
return err return err
} }
case v.Text == fmt.Sprintf("%srehash", config.CSign): case v.Text == fmt.Sprintf("%srehash", config.CSign): //nolint:wsl
/* Эта команда может прилетать из приватной беседы с realjid-ом, из приватной беседы с chat-nick-ом, а также из /* Эта команда может прилетать из приватной беседы с realjid-ом, из приватной беседы с chat-nick-ом, а также из
* чятика. * чятика.
* Groupchat мы можем определить по v.Type (groupchat) и тогда понятно что делать. * Groupchat мы можем определить по v.Type (groupchat) и тогда понятно что делать.

View File

@@ -1,14 +1,14 @@
{ {
"blacklist": [ "blacklist": [
{ {
# Пустой список означает глобальные баны, которые применяются ко всем комнатам, где присутствует бот # Пустой список означает глобальные баны, которые применяются ко всем комнатам, где присутствует бот.
"room_name": "", "room_name": "",
# Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss # Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss.
# Если не задано, то false # Если не задано, то false
"reason_enable": false, "reason_enable": false,
# Список регулярок JID-ов, которых надо банить # Список регулярок JID-ов, которых надо банить.
"jid_re": [ "jid_re": [
"^[Mm]ary@server.tld/resource1$", "^[Mm]ary@server.tld/resource1$",
"^[cC]hris(topher)?@", "^[cC]hris(topher)?@",
@@ -16,13 +16,13 @@
"^(her|his)_dog@.*\\.street/.*" "^(her|his)_dog@.*\\.street/.*"
], ],
# Список регулярок nick-ов злодеев # Список регулярок nick-ов злодеев.
"nick_re": [ "nick_re": [
"^(Annoying_)?[F|f]ly$", "^(Annoying_)?[F|f]ly$",
"^Buzzing_Wasp$" "^Buzzing_Wasp$"
], ],
# Список регулярок, запрещённых к упоминанию в чяте # Список регулярок, запрещённых к упоминанию в чяте.
"phrase_re": [ "phrase_re": [
"^Exterminate.$" "^Exterminate.$"
] ]