Compare commits
3 Commits
c5f011dabc
...
a9935abf53
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9935abf53 | ||
|
|
75b9ab8a8b | ||
|
|
e48be3936e |
69
.golangci.yml
Normal file
69
.golangci.yml
Normal 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
|
||||
10
Makefile
10
Makefile
@@ -5,7 +5,7 @@ FILELIST=collection.go types.go globals.go lib.go event_parser.go buny.go comman
|
||||
|
||||
BINARY=buny-jabber-bot
|
||||
|
||||
# На windows имя бинарника может зависеть не только от платформы, но и от выранной цели, для linux-а суффикс .exe
|
||||
# На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe
|
||||
# не нужен
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifeq ($(strip $(GOOS)),)
|
||||
@@ -23,10 +23,10 @@ define IFS
|
||||
|
||||
endef
|
||||
|
||||
# Используем классические таргеты, где первый встречаемый является таргетом по-умолчанию
|
||||
## Используем классические таргеты, где первый встречаемый является таргетом по-умолчанию
|
||||
all: clean build
|
||||
|
||||
|
||||
## Этот таргет собирает бинарь
|
||||
build:
|
||||
# Ну и дальше просто билдим бинарник средствами гошки
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@@ -45,12 +45,12 @@ else
|
||||
endif
|
||||
|
||||
|
||||
# Удаляем бинарник средствами go
|
||||
## Удаляем бинарник средствами go
|
||||
clean:
|
||||
go clean
|
||||
|
||||
|
||||
# Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом.
|
||||
## Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом.
|
||||
upgrade:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# вариант с jetbrains golang на windows или powershell на windows
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
Имеет возможность заносить пользователей в бан-лист, согласно заданным в чёрном списке правилам: по совпадению с
|
||||
регулярными выражениями в nick-е или jid-е злодея, а также по регулярным выражениям характерных фраз. Правила можно
|
||||
настроить как глобально, для всех комнат, где присутсвует бот, так и для каждой комнаты отдельно. При изменении списка
|
||||
правил бота надо перезапускать.
|
||||
настроить как глобально, для всех комнат, где присутствует бот, так и для каждой комнаты отдельно. При изменении списка
|
||||
правил бота не надо перезапускать, достаточно отдать ему команду rehash либо в приват, либо прям в чатике.
|
||||
|
||||
## Что он не может?
|
||||
|
||||
@@ -46,7 +46,7 @@ make
|
||||
|
||||
Почему нельзя оставить комнату анонимной? А тут всё просто, в банлист заносится реальный jid пользователя, а не его ник.
|
||||
Соответственно, бот должен видеть этот самый реальный jid. В анонимной комнате бот не сможет увидеть реальный jid.
|
||||
А автокик - это конечно хорошо, но есть нюанс: можно, например, гадить ником.
|
||||
А автокик - это конечно хорошо, но есть нюанс: можно, например, гадить ником, поэтому бот в автокик не умеет.
|
||||
|
||||
## Как работает бан?
|
||||
|
||||
|
||||
74
buny.go
74
buny.go
@@ -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)
|
||||
|
||||
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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
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)
|
||||
|
||||
if re.MatchString(evilNick) {
|
||||
log.Warnf(
|
||||
"Hammer falls on %s (%s): nick matches with global blacklist entry: %s",
|
||||
v.From,
|
||||
evilJid,
|
||||
nickRegexp,
|
||||
)
|
||||
|
||||
// Баним именно 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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
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)
|
||||
|
||||
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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
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)
|
||||
|
||||
if re.MatchString(evilNick) {
|
||||
log.Warnf(
|
||||
"Hammer falls on %s (%s): nick matches with room blacklist entry: %s",
|
||||
v.From,
|
||||
evilJid,
|
||||
nickRegexp,
|
||||
)
|
||||
|
||||
// Баним именно 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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
id,
|
||||
@@ -209,7 +245,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
||||
return err
|
||||
}
|
||||
|
||||
// bunyChat проиводит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого
|
||||
// bunyChat производит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого
|
||||
// шаблона банит участника чата.
|
||||
func bunyChat(v xmpp.Chat) error {
|
||||
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)
|
||||
|
||||
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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
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)
|
||||
|
||||
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(
|
||||
"unable to ban user: id=%s, err=%w",
|
||||
id,
|
||||
@@ -298,14 +354,12 @@ func bunyChat(v xmpp.Chat) error {
|
||||
// squash банит указанный jid в указанной комнате.
|
||||
// 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 (
|
||||
id string
|
||||
err error
|
||||
)
|
||||
|
||||
log.Infof("Hammer falls on %s(%s)", nick, jid)
|
||||
|
||||
if config.Jabber.BanPhrasesEnable {
|
||||
phrase := randomPhrase(config.Jabber.BanPhrases)
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ func cmd(v xmpp.Chat) error {
|
||||
return err
|
||||
}
|
||||
|
||||
case v.Text == fmt.Sprintf("%srehash", config.CSign):
|
||||
case v.Text == fmt.Sprintf("%srehash", config.CSign): //nolint:wsl
|
||||
/* Эта команда может прилетать из приватной беседы с realjid-ом, из приватной беседы с chat-nick-ом, а также из
|
||||
* чятика.
|
||||
* Groupchat мы можем определить по v.Type (groupchat) и тогда понятно что делать.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"blacklist": [
|
||||
{
|
||||
# Пустой список означает глобальные баны, которые применяются ко всем комнатам, где присутствует бот
|
||||
# Пустой список означает глобальные баны, которые применяются ко всем комнатам, где присутствует бот.
|
||||
"room_name": "",
|
||||
|
||||
# Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss
|
||||
# Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss.
|
||||
# Если не задано, то false
|
||||
"reason_enable": false,
|
||||
|
||||
# Список регулярок JID-ов, которых надо банить
|
||||
# Список регулярок JID-ов, которых надо банить.
|
||||
"jid_re": [
|
||||
"^[Mm]ary@server.tld/resource1$",
|
||||
"^[cC]hris(topher)?@",
|
||||
@@ -16,13 +16,13 @@
|
||||
"^(her|his)_dog@.*\\.street/.*"
|
||||
],
|
||||
|
||||
# Список регулярок nick-ов злодеев
|
||||
# Список регулярок nick-ов злодеев.
|
||||
"nick_re": [
|
||||
"^(Annoying_)?[F|f]ly$",
|
||||
"^Buzzing_Wasp$"
|
||||
],
|
||||
|
||||
# Список регулярок, запрещённых к упоминанию в чяте
|
||||
# Список регулярок, запрещённых к упоминанию в чяте.
|
||||
"phrase_re": [
|
||||
"^Exterminate.$"
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user