From 31490b0922f70c552ce14704c03beda67eeaec3a Mon Sep 17 00:00:00 2001 From: eleksir Date: Sun, 5 Nov 2023 16:33:17 +0300 Subject: [PATCH] Add per-chat nick setting, update README.md --- README.md | 15 ++++++++------- data/sample_blacklist.json | 2 +- data/sample_config.json | 4 ++++ event_parser.go | 22 ++++++++++++++-------- lib.go | 16 +++++++++++++--- read_config.go | 7 ++++++- types.go | 1 + 7 files changed, 47 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2895307..a49937a 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,15 @@ ## Что он может? -Имеет возможность соединяться с сервером по протоколу xmpp как с шифрованием, так и без. (Пока что) Шифрование +* Имеет возможность соединяться с сервером по протоколу xmpp как с шифрованием, так и без. (Пока что) Шифрование работает по классическим механикам (шифрованный канал связи, без возможности коммуникации в незашифрованном виде), -без поддержки механизма start tls. Что-то в гошке или на стороне сервера при выборе StartTLS не работает. - -Имеет возможность заносить пользователей в бан-лист, согласно заданным в чёрном списке правилам: по совпадению с -регулярными выражениями в nick-е или jid-е злодея, а также по регулярным выражениям характерных фраз. Правила можно -настроить как глобально, для всех комнат, где присутствует бот, так и для каждой комнаты отдельно. При изменении списка -правил бота не надо перезапускать, достаточно отдать ему команду rehash либо в приват, либо прям в чатике. +без поддержки механизма start tls. (Что-то в гошке или на стороне сервера при выборе StartTLS не работает.) +* Имеет возможность заносить пользователей в бан-лист, согласно заданным в чёрном списке правилам: + - по совпадению с регулярными выражениями в nick-е или jid-е злодея + - по регулярным выражениям характерных фраз. + - Правила можно настроить как глобально, для всех комнат, где присутствует бот, так и для каждой комнаты отдельно. + - При изменении списка правил бота не надо перезапускать, достаточно отдать ему команду rehash либо в приват, либо прям в чатике. +* Есть настройка заходить в разные комнаты под разными никами ## Что он не может? diff --git a/data/sample_blacklist.json b/data/sample_blacklist.json index a8fd61d..a78b505 100644 --- a/data/sample_blacklist.json +++ b/data/sample_blacklist.json @@ -5,7 +5,7 @@ "room_name": "", # Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss. - # Если не задано, то false + # Если не задано, то false. "reason_enable": false, # Список регулярок JID-ов, которых надо банить. diff --git a/data/sample_config.json b/data/sample_config.json index 9ce81d4..60bc0f5 100644 --- a/data/sample_config.json +++ b/data/sample_config.json @@ -71,6 +71,10 @@ # Название канала, обязательное поле "name" : "my_channel@conference.jabber.tld", + # Под каким ником бот зайдёт конкретно на этот канал. Если не задано, будет использован ник, заданный в + # общих настройках Jabber, выше по конфигу. + "nick" : "sailormoon", + # Настройки байесовского классификатора. В виду вероятности ложного срабатывания возможно, имеет смысл # воздержаться от использования. Зависит от использования и от словарей. "bayes": { diff --git a/event_parser.go b/event_parser.go index 618bea6..a2d5222 100644 --- a/event_parser.go +++ b/event_parser.go @@ -33,11 +33,14 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo // Групповой чятик case "groupchat": - log.Debugf("Message from public chat: %s", v.Text) - // room := strings.SplitN(v.Remote, "/", 2)[0] - nick := strings.SplitN(v.Remote, "/", 2)[1] + var ( + room = strings.SplitN(v.Remote, "/", 2)[0] + nick = strings.SplitN(v.Remote, "/", 2)[1] + ) - if nick == config.Jabber.Nick { + log.Debugf("Message from public chat: %s", v.Text) + + if nick == getBotNickFromRoomConfig(room) { log.Debug("Skipping message from myself") return @@ -361,7 +364,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo mucNickMatch := false for _, room := range roomsConnected { - mucNick := fmt.Sprintf("%s/%s", room, config.Jabber.Nick) + mucNick := fmt.Sprintf("%s/%s", room, getBotNickFromRoomConfig(room)) if v.From == mucNick { mucNickMatch = true @@ -384,7 +387,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo mucNickMatch := false for _, room := range roomsConnected { - mucNick := fmt.Sprintf("%s/%s", room, config.Jabber.Nick) + mucNick := fmt.Sprintf("%s/%s", room, getBotNickFromRoomConfig(room)) if v.From == mucNick { mucNickMatch = true @@ -484,8 +487,11 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo if err := xml.Unmarshal(v.Query, &iqErrorCancelNotAcceptable); err == nil { if v.To == talk.JID() { nick := strings.SplitN(v.From, "/", 2)[1] + room := strings.SplitN(v.From, "/", 2)[0] + + if slices.Contains(roomsConnected, iqErrorCancelNotAcceptable.By) && + nick == getBotNickFromRoomConfig(room) { - if slices.Contains(roomsConnected, iqErrorCancelNotAcceptable.By) && nick == config.Jabber.Nick { log.Errorf( "Got Iq error message from: %s to: %s. Looks like i'm not in MUC anymore", v.From, v.To, @@ -577,7 +583,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo // Это наш собственный Presence if v.Show == "" && v.Status == "" { - if nick == config.Jabber.Nick { + if nick == getBotNickFromRoomConfig(room) { roomsConnected = append(roomsConnected, room) // На всякий случай дедуплицируем список комнат, к которым мы заджойнились. sort.Strings(roomsConnected) diff --git a/lib.go b/lib.go index 0a1de2f..273e782 100644 --- a/lib.go +++ b/lib.go @@ -355,7 +355,8 @@ func joinMuc(room string) { } } - if _, err := talk.JoinMUCNoHistory(room, config.Jabber.Nick); err != nil { + // Заходим в конфу, наконец-то + if _, err := talk.JoinMUCNoHistory(room, getBotNickFromRoomConfig(room)); err != nil { log.Errorf("Unable to join to MUC: %s", room) gTomb.Kill(err) @@ -551,14 +552,13 @@ func probeMUCLiveness() { //nolint:gocognit sleepTime := time.Duration(rand.Int63n(1000*config.Jabber.PingSplayDelay)) * time.Millisecond //nolint:gosec time.Sleep(sleepTime) - if err := talk.PingS2S(talk.JID(), room+"/"+config.Jabber.Nick); err != nil { + if err := talk.PingS2S(talk.JID(), room+"/"+getBotNickFromRoomConfig(room)); err != nil { gTomb.Kill(err) return } }(room) */ - var roomMap interface{} roomMap, exist = mucCapsList.Get(room) @@ -697,4 +697,14 @@ func getRealJIDfromNick(fullNick string) string { return "" } +func getBotNickFromRoomConfig(room string) string { + for _, roomStruct := range config.Jabber.Channels { + if roomStruct.Name == room { + return roomStruct.Nick + } + } + + return config.Jabber.Nick +} + /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ diff --git a/read_config.go b/read_config.go index ad05bb1..1ea1cb8 100644 --- a/read_config.go +++ b/read_config.go @@ -187,11 +187,15 @@ func readConfig() error { //nolint:gocognit,gocyclo return errors.New("no jabber channels/rooms defined in config, quitting") //nolint:goerr113 } - for _, channel := range sampleConfig.Jabber.Channels { + for n, channel := range sampleConfig.Jabber.Channels { if channel.Name == "" { return errors.New("no \"name\" entry in jabber channel config") } + if channel.Nick == "" { + sampleConfig.Jabber.Channels[n].Nick = sampleConfig.Jabber.Nick + } + // channel.Password может быть пустым, тогда пароля нет // channel.Bayes.Enabled будет false, если не проставлен @@ -260,6 +264,7 @@ func readConfig() error { //nolint:gocognit,gocyclo config = sampleConfig configLoaded = true + log.Infof("Using %s as config file", location) //nolint:wsl break diff --git a/types.go b/types.go index 6fb6aa6..58e0505 100644 --- a/types.go +++ b/types.go @@ -26,6 +26,7 @@ type myConfig struct { BotMasters []string `json:"bot_masters,omitempty"` Channels []struct { Name string `json:"name,omitempty"` + Nick string `json:"nick,omitempty"` Password string `json:"password,omitempty"` Bayes struct { Enabled bool `json:"enabled,omitempty"`