diff --git a/commands.go b/commands.go index 52543ee..5e84566 100644 --- a/commands.go +++ b/commands.go @@ -60,7 +60,7 @@ func cmd(v xmpp.Chat) error { message.Misc.Fwdcnt = 0 message.Misc.Csign = config.CSign message.Misc.Username = userNick - message.Misc.Botnick = config.Jabber.Nick + message.Misc.Botnick = getBotNickFromRoomConfig(message.Chatid) message.Misc.Msgformat = 0 msgLen := len(v.Text) @@ -323,7 +323,9 @@ func cmd(v xmpp.Chat) error { } // Предполагается что в канале бот должен отвечать, только если к нему обратились, либо это была команда - if regexp.MustCompile(config.Jabber.Nick).Match([]byte(message.Message)) { + botNick := getBotNickFromRoomConfig(message.Chatid) + + if regexp.MustCompile(regexp.QuoteMeta(botNick)).Match([]byte(message.Message)) { message.Misc.Answer = 1 } diff --git a/data/sample_config.json b/data/sample_config.json index 3f2188e..1a6a17c 100644 --- a/data/sample_config.json +++ b/data/sample_config.json @@ -79,8 +79,20 @@ # Jabber-каналы, к которым бот попробует присоединиться при старте "channels": [ - "my_channel@conference.jabber.tld", - "another_channel@conference.jabber.tld" + { + # Название чатрума/конференции + "name": "my_channel@conference.jabber.tld", + + # Под каким ником бот зайдёт конкретно на этот канал. Если не задано, будет использован ник, заданный в + # общих настройках Jabber, выше по конфигу. + "nick": "alice", + + # Пароль, если не задан или пустой, то заход в комнату будет без пароля. (не реализовано) + "password": "secret" + }, + { + "name": "another_channel@conference.jabber.tld" + } ], # Статус, с которым бот запускается. (если всё нормально, этот статус будет видать только в логах сервера и diff --git a/event_parser.go b/event_parser.go index 6e5b31e..919c75b 100644 --- a/event_parser.go +++ b/event_parser.go @@ -33,10 +33,10 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo // Групповой чятик case "groupchat": log.Debugf("Message from public chat: %s", v.Text) - // dest := strings.SplitN(v.Remote, "/", 2)[0] + room := strings.SplitN(v.Remote, "/", 2)[0] nick := strings.SplitN(v.Remote, "/", 2)[1] - if nick == config.Jabber.Nick { + if nick == getBotNickFromRoomConfig(room) { log.Debug("Skipping message from myself") return @@ -354,7 +354,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 @@ -438,9 +438,12 @@ 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] + var ( + room = strings.SplitN(v.From, "/", 2)[0] + nick = strings.SplitN(v.From, "/", 2)[1] + ) - if slices.Contains(roomsConnected, iqErrorCancelNotAcceptable.By) && nick == config.Jabber.Nick { + if slices.Contains(roomsConnected, iqErrorCancelNotAcceptable.By) && nick == getBotNickFromRoomConfig(room) { log.Errorf( "Got Iq error message from: %s to: %s. Looks like i'm not in MUC anymore", v.From, v.To, diff --git a/lib.go b/lib.go index b90e48d..55e26ab 100644 --- a/lib.go +++ b/lib.go @@ -120,7 +120,7 @@ func establishConnection() { // Джойнимся к чятикам, но делаем это в фоне, чтобы не блочиться на ошибках, например, если бота забанили for _, room := range config.Jabber.Channels { - go joinMuc(room) + go joinMuc(room.Name) } go RotateStatus("") @@ -177,7 +177,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) @@ -356,7 +357,7 @@ 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) continue } @@ -554,4 +555,15 @@ func getMucNames(room string) []string { return names } +// getBotNickFromRoomConfig достаёт (короткий) ник бота из настроек чата +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 26b3f65..4133770 100644 --- a/read_config.go +++ b/read_config.go @@ -187,6 +187,18 @@ func readConfig() error { //nolint:gocognit,gocyclo return errors.New("no jabber channels/rooms defined in config, quitting") //nolint:goerr113 } + 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 может быть пустым, тогда пароля нет + } + // Если список фраз с которыми стартует бот пустой, вносим в него 1 запись с пустой строкой if len(sampleConfig.Jabber.StartupStatus) == 0 { sampleConfig.Jabber.StartupStatus[0] = "" @@ -222,6 +234,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 0186a37..2a05674 100644 --- a/types.go +++ b/types.go @@ -30,9 +30,13 @@ type myConfig struct { User string `json:"user,omitempty"` Password string `json:"password,omitempty"` BotMasters []string `json:"bot_masters"` - Channels []string `json:"channels"` - StartupStatus []string `json:"startup_status,omitempty"` - RuntimeStatus struct { + Channels []struct { + Name string `json:"name,omitempty"` + Nick string `json:"nick,omitempty"` + Password string `json:"password,omitempty"` + } `json:"channels,omitempty"` + StartupStatus []string `json:"startup_status,omitempty"` + RuntimeStatus struct { Text []string `json:"text,omitempty"` RotationTime int64 `json:"rotation_time,omitempty"` RotationSplayTime int64 `json:"rotation_splay_time,omitempty"`