Fix filling presence db, fix ban by useragent
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
"user_agent": [
|
"user_agent": [
|
||||||
{
|
{
|
||||||
"software": "BadUserAgent",
|
"name": "BadUserAgent",
|
||||||
"version": "0.666.0",
|
"version": "0.666.0",
|
||||||
"os": "DeathStarOS"
|
"os": "DeathStarOS"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,6 +204,8 @@
|
|||||||
# логгирует то, что пишется "в провод"
|
# логгирует то, что пишется "в провод"
|
||||||
"lib": false,
|
"lib": false,
|
||||||
# Дебаг периодических пингов. Мало полезная вещь, разве что для выявления сетевых аномалий.
|
# Дебаг периодических пингов. Мало полезная вещь, разве что для выявления сетевых аномалий.
|
||||||
"ping": false
|
"ping": false,
|
||||||
|
# Дебаг работы presence db.
|
||||||
|
"presence_db": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/hjson/hjson-go"
|
"github.com/hjson/hjson-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,13 +125,13 @@ func (j *Jabber) ReadBlacklist() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
whitelistJSONPath := filepath.Dir(executablePath) + "/data/blacklist.json"
|
blacklistJSONPath := filepath.Dir(executablePath) + "/data/blacklist.json"
|
||||||
|
|
||||||
locations := []string{
|
locations := []string{
|
||||||
"~/.bunyPresense-jabber-bot-blacklist.json",
|
"~/.buny-jabber-bot-blacklist.json",
|
||||||
"~/bunyPresense-jabber-bot-blacklist.json",
|
"~/buny-jabber-bot-blacklist.json",
|
||||||
"/etc/bunyPresense-jabber-bot-blacklist.json",
|
"/etc/buny-jabber-bot-blacklist.json",
|
||||||
whitelistJSONPath,
|
blacklistJSONPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, location := range locations {
|
for _, location := range locations {
|
||||||
@@ -188,7 +190,19 @@ func (j *Jabber) ReadBlacklist() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
j.BlackList = sampleBlacklist
|
for _, entry := range sampleBlacklist.Blacklist {
|
||||||
|
for str := range strings.SplitSeq(spew.Sdump(entry), "\n") {
|
||||||
|
log.Debug(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вообще говоря, нас уверяют, что простого "=" хватает, но на практике оказывается, что вложенные стуктуры
|
||||||
|
// могут и не скопироваться.
|
||||||
|
tmpjson, _ := json.Marshal(sampleBlacklist) //nolint: errchkjson // Да блять, сколько можно
|
||||||
|
// доёбываться, эти данные 100500 раз перекодировались, там ошибка возможна только если есть ошибка в
|
||||||
|
// encoding/json, но в этом случае мы в любом случае ничего поделать не можем, вот всяком случае в рантайме.
|
||||||
|
_ = json.Unmarshal(tmpjson, &j.BlackList)
|
||||||
|
|
||||||
blacklistLoaded = true
|
blacklistLoaded = true
|
||||||
|
|
||||||
log.Infof("Using %s as blacklist file", location)
|
log.Infof("Using %s as blacklist file", location)
|
||||||
|
|||||||
@@ -403,28 +403,42 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
if v.From != "" {
|
if v.From != "" {
|
||||||
// На всякий случай: себя никогда не баним, явным образом.
|
// На всякий случай: себя никогда не баним, явным образом.
|
||||||
if v.From == j.Talk.JID() {
|
if v.From == j.Talk.JID() {
|
||||||
|
log.Debugf("Skipping useragent blacklist check for myself")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
room := strings.SplitN(v.From, "/", 2)[0]
|
room := strings.SplitN(v.From, "/", 2)[0]
|
||||||
|
|
||||||
var (
|
|
||||||
presenceJSONStrings []string
|
|
||||||
)
|
|
||||||
|
|
||||||
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONStrings = InterfaceToStringSlice(presenceJSONInterface)
|
presenceJSON, ok := presenceJSONInterface.([]byte)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Looking up %s in presence db", v.From)
|
var presences []xmpp.Presence
|
||||||
|
|
||||||
for _, presenceJSONString := range presenceJSONStrings {
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
var p xmpp.Presence
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
_ = json.Unmarshal([]byte(presenceJSONString), &p)
|
return nil //nolint: nilerr // Это не критическая ошибка, её не надо возвращать.
|
||||||
|
}
|
||||||
|
|
||||||
if v.From == p.From {
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
log.Infof("Found jid of %s in presence db: %s", v.From, p.JID)
|
// Если находим, что у нас уже есть клиент с таким же From, то есть полным nick-ом (для groupchat)
|
||||||
|
// пропускаем его.
|
||||||
|
if p.From != v.From {
|
||||||
|
log.Debugf("Skip check for %s because it is not %s", p.From, v.From)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Found jid of %s in presence db: %s", v.From, p.JID)
|
||||||
|
}
|
||||||
|
|
||||||
if p.Affiliation == "admin" || p.Affiliation == "owner" {
|
if p.Affiliation == "admin" || p.Affiliation == "owner" {
|
||||||
log.Infof("Skipping useragent blacklist check for %s because his affiliation is %s", v.From, p.Affiliation)
|
log.Infof("Skipping useragent blacklist check for %s because his affiliation is %s", v.From, p.Affiliation)
|
||||||
@@ -442,7 +456,7 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
log.Debug("Useragent is not owner or moderator, proceeding with check...")
|
log.Debug("Useragent is not owner or moderator, proceeding with check...")
|
||||||
|
|
||||||
// Lookup in global blacklist.
|
// Lookup in global blacklist.
|
||||||
log.Debug("Find our room in connected room list...")
|
log.Debug("Searching our room in connected room list...")
|
||||||
|
|
||||||
for _, cRoom := range j.RoomsConnected {
|
for _, cRoom := range j.RoomsConnected {
|
||||||
if cRoom == room {
|
if cRoom == room {
|
||||||
@@ -452,12 +466,15 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
// Обработаем правила глобального чёрного списка.
|
// Обработаем правила глобального чёрного списка.
|
||||||
if bEntry.RoomName == "" {
|
if bEntry.RoomName == "" {
|
||||||
log.Debugf("Check in global blacklist")
|
log.Debugf("Check in global blacklist")
|
||||||
|
log.Debugf("We have useragent struct with Name=%s, Version=%s, OS=%s", ver.Name, ver.Version, ver.Os)
|
||||||
|
|
||||||
for _, useragent := range bEntry.UserAgent {
|
for _, useragent := range bEntry.UserAgent {
|
||||||
|
log.Debugf("We have useragent blacklist entry Name=%s, Version=%s, OS=%s", useragent.Name, useragent.Version, useragent.Os)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case useragent.Name != "" && useragent.Version != "" && useragent.Os != "":
|
case useragent.Name != "" && useragent.Version != "" && useragent.Os != "":
|
||||||
if ver.Name == useragent.Name && ver.Version == useragent.Version && ver.Os == useragent.Os {
|
if ver.Name == useragent.Name && ver.Version == useragent.Version && ver.Os == useragent.Os {
|
||||||
log.Debug("Found all 3 components in black list, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name, Version and OS match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -474,9 +491,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Name != "" && useragent.Version != "":
|
case useragent.Name != "" && useragent.Version != "" && useragent.Os == "":
|
||||||
if ver.Name == useragent.Name && ver.Version == useragent.Version {
|
if ver.Name == useragent.Name && ver.Version == useragent.Version {
|
||||||
log.Debug("Found sw name and version in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name and Version match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -493,9 +510,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Name != "":
|
case useragent.Name != "" && useragent.Version == "" && useragent.Os == "":
|
||||||
if ver.Name == useragent.Name {
|
if ver.Name == useragent.Name {
|
||||||
log.Debug("Found sw name in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -512,9 +529,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Version != "":
|
case useragent.Name == "" && useragent.Version != "" && useragent.Os == "":
|
||||||
if ver.Version == useragent.Version {
|
if ver.Version == useragent.Version {
|
||||||
log.Debug("Found sw version in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Version match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -532,16 +549,20 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("No matches in global software versions blacklist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if bEntry.RoomName == room {
|
if bEntry.RoomName == room {
|
||||||
log.Debug("Found blacklist entries for room")
|
log.Debug("Found blacklist entries for room")
|
||||||
|
|
||||||
for _, useragent := range bEntry.UserAgent {
|
for _, useragent := range bEntry.UserAgent {
|
||||||
|
log.Debugf("We have useragent blacklist entry Name=%s, Version=%s, OS=%s", useragent.Name, useragent.Version, useragent.Os)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case useragent.Name != "" && useragent.Version != "" && useragent.Os != "":
|
case useragent.Name != "" && useragent.Version != "" && useragent.Os != "":
|
||||||
if ver.Name == useragent.Name && ver.Version == useragent.Version && ver.Os == useragent.Os {
|
if ver.Name == useragent.Name && ver.Version == useragent.Version && ver.Os == useragent.Os {
|
||||||
log.Debug("Found all 3 components in black list, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name, Version and OS match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -558,9 +579,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Name != "" && useragent.Version != "":
|
case useragent.Name != "" && useragent.Version != "" && useragent.Os == "":
|
||||||
if ver.Name == useragent.Name && ver.Version == useragent.Version {
|
if ver.Name == useragent.Name && ver.Version == useragent.Version {
|
||||||
log.Debug("Found sw name and version in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name and Version match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -577,9 +598,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Name != "":
|
case useragent.Name != "" && useragent.Version == "" && useragent.Os == "":
|
||||||
if ver.Name == useragent.Name {
|
if ver.Name == useragent.Name {
|
||||||
log.Debug("Found sw name in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Name match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -596,9 +617,9 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case useragent.Version != "":
|
case useragent.Name == "" && useragent.Version != "" && useragent.Os == "":
|
||||||
if ver.Version == useragent.Version {
|
if ver.Version == useragent.Version {
|
||||||
log.Debug("Found sw version in blacklist, it is ban")
|
log.Warnf("Hammer falls on %s (%s): Software Version match entry in blacklist", p.From, p.JID)
|
||||||
|
|
||||||
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, p.JID, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
@@ -616,6 +637,8 @@ func (j *Jabber) BunySoftwareVersion(v xmpp.IQ, ver IqResultSoftwareVersion) err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debugf("No matches in software versions blacklist for %s", room)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -632,8 +632,8 @@ func (j *Jabber) ParseEvent(e any) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Infof(
|
log.Infof(
|
||||||
"Presence notification, Type: %s, From: %s, To: %s Show: %s, Status: %s, Affiliation: %s, Role: %s, JID: %s",
|
"Presence notification, Type: %s, From: %s, To: %s Show: %s, Status: %s, Affiliation: %s, Role: %s, JID: %s, Priority: %s",
|
||||||
v.Type, v.From, v.To, v.Show, v.Status, v.Affiliation, v.Role, v.JID,
|
v.Type, v.From, v.To, v.Show, v.Status, v.Affiliation, v.Role, v.JID, v.Priority,
|
||||||
)
|
)
|
||||||
|
|
||||||
if !strings.Contains(v.From, "/") {
|
if !strings.Contains(v.From, "/") {
|
||||||
@@ -642,6 +642,12 @@ func (j *Jabber) ParseEvent(e any) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v.JID == "" {
|
||||||
|
log.Info("Useless presence notification without JID field, skipping")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
room := strings.SplitN(v.From, "/", 2)[0]
|
room := strings.SplitN(v.From, "/", 2)[0]
|
||||||
nick := strings.SplitN(v.From, "/", 2)[1]
|
nick := strings.SplitN(v.From, "/", 2)[1]
|
||||||
|
|
||||||
@@ -651,8 +657,7 @@ func (j *Jabber) ParseEvent(e any) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Это наш собственный Presence.
|
// На всякий случай добавим комнату, из которой пришло уведомление в список тех, в которые вхож бот.
|
||||||
if v.Show == "" && v.Status == "" {
|
|
||||||
if nick == j.GetBotNickFromRoomConfig(room) {
|
if nick == j.GetBotNickFromRoomConfig(room) {
|
||||||
j.RoomsConnected = append(j.RoomsConnected, room)
|
j.RoomsConnected = append(j.RoomsConnected, room)
|
||||||
// На всякий случай дедуплицируем список комнат, к которым мы заджойнились.
|
// На всякий случай дедуплицируем список комнат, к которым мы заджойнились.
|
||||||
@@ -660,59 +665,159 @@ func (j *Jabber) ParseEvent(e any) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
j.RoomsConnected = slices.Compact(j.RoomsConnected)
|
j.RoomsConnected = slices.Compact(j.RoomsConnected)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch v.Role {
|
switch v.Role {
|
||||||
// Участник ушёл.
|
// Участник ушёл.
|
||||||
case "none":
|
case "none":
|
||||||
|
var (
|
||||||
|
newPresences = make([]xmpp.Presence, 0)
|
||||||
|
presenceJSON []byte
|
||||||
|
ok bool
|
||||||
|
presences []xmpp.Presence
|
||||||
|
)
|
||||||
|
|
||||||
|
// Обновлять базу имеет смысл только если есть хоть какая-то запись о комнате в ней.
|
||||||
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONStrings := InterfaceToStringSlice(presenceJSONInterface)
|
presenceJSON, ok = presenceJSONInterface.([]byte)
|
||||||
|
|
||||||
var newPresenceJSONStrings []string
|
if !ok {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
for _, presenceJSONstring := range presenceJSONStrings {
|
return
|
||||||
var p xmpp.Presence
|
}
|
||||||
|
|
||||||
_ = json.Unmarshal([]byte(presenceJSONstring), &p)
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
|
// Если находим, что у нас уже есть клиент с таким же From, то есть полным nick-ом (для groupchat)
|
||||||
|
// пропускаем его.
|
||||||
if p.From == v.From {
|
if p.From == v.From {
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Skipping presence for %s in room %s", v.JID, room)
|
||||||
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newPresenceJSONStrings = append(newPresenceJSONStrings, presenceJSONstring)
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Appending presence for %s in room %s", v.JID, room)
|
||||||
}
|
}
|
||||||
|
|
||||||
j.RoomPresences.Set(room, newPresenceJSONStrings)
|
newPresences = append(newPresences, p)
|
||||||
}
|
}
|
||||||
// Участник пришёл.
|
|
||||||
|
presenceJSON, _ = json.Marshal(newPresences) //nolint: errchkjson
|
||||||
|
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Updating presence db for room %s", room)
|
||||||
|
}
|
||||||
|
|
||||||
|
j.RoomPresences.Set(room, presenceJSON)
|
||||||
|
|
||||||
|
// Больше нам, похоже с этим уведомлением нечего.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Участник пришёл или изменил свой статус.
|
||||||
default:
|
default:
|
||||||
var (
|
var (
|
||||||
presenceJSONStrings []string
|
newPresences = make([]xmpp.Presence, 0)
|
||||||
newPresenceJSONStrings []string
|
presenceJSON []byte
|
||||||
presenceJSONBytes []byte
|
ok bool
|
||||||
|
presences []xmpp.Presence
|
||||||
|
skip bool
|
||||||
)
|
)
|
||||||
|
|
||||||
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONStrings = InterfaceToStringSlice(presenceJSONInterface)
|
presenceJSON, ok = presenceJSONInterface.([]byte)
|
||||||
|
if !ok {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, presenceJSONString := range presenceJSONStrings {
|
// Если мы нашли запись о комнате, то её надо обновить.
|
||||||
var p xmpp.Presence
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
_ = json.Unmarshal([]byte(presenceJSONString), &p)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
// Если находим, что у нас уже есть клиент с таким же From, то есть полным nick-ом (для groupchat)
|
// Если находим, что у нас уже есть клиент с таким же From, то есть полным nick-ом (для groupchat)
|
||||||
// просто замещаем его.
|
// запоминаем его и добавим позднее.
|
||||||
if p.From == v.From {
|
if p.From == v.From {
|
||||||
|
// Запоминаем участника только если его роль не поменялась на outcast. (То есть если это не
|
||||||
|
// бан.)
|
||||||
|
if v.Role == "outcast" {
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Let's forget about %s because it is outcast/banned", p.JID)
|
||||||
|
}
|
||||||
|
|
||||||
|
skip = true
|
||||||
|
} else if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Skip adding %s to presences for %s, add as last one", p.JID, room)
|
||||||
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newPresenceJSONStrings = append(newPresenceJSONStrings, presenceJSONString)
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Appending presence for %s in room %s", v.JID, room)
|
||||||
}
|
}
|
||||||
|
|
||||||
presenceJSONBytes, _ = json.Marshal(v) //nolint:errchkjson
|
newPresences = append(newPresences, p)
|
||||||
newPresenceJSONStrings = append(newPresenceJSONStrings, string(presenceJSONBytes))
|
}
|
||||||
j.RoomPresences.Set(room, newPresenceJSONStrings)
|
}
|
||||||
|
|
||||||
|
if !skip {
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Appending presence for %s in room %s", v.JID, room)
|
||||||
|
}
|
||||||
|
|
||||||
|
newPresences = append(newPresences, v)
|
||||||
|
} else if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Skip Appending outcast presence for %s in room %s", v.JID, room)
|
||||||
|
}
|
||||||
|
|
||||||
|
presenceJSON, _ = json.Marshal(newPresences) //nolint: errchkjson
|
||||||
|
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("Updating presence db for room %s", room)
|
||||||
|
}
|
||||||
|
|
||||||
|
j.RoomPresences.Set(room, presenceJSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
if j.C.Debug.PresenceDB {
|
||||||
|
log.Debugf("List of presence entries in presence db of %s:", room)
|
||||||
|
|
||||||
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
|
var presences []xmpp.Presence
|
||||||
|
|
||||||
|
presenceJSON, ok := presenceJSONInterface.([]byte)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Debugf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если мы нашли запись о комнате, то её надо обновить.
|
||||||
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
|
log.Debugf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
|
log.Debugf("Found presence for %s from %s", p.JID, room)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, а не злодей ли зашёл? Сделать это мы можем, только если мы находимся в комнате.
|
// Проверяем, а не злодей ли зашёл? Сделать это мы можем, только если мы находимся в комнате.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type (
|
|||||||
Debug struct {
|
Debug struct {
|
||||||
Lib bool `json:"lib,omitempty"`
|
Lib bool `json:"lib,omitempty"`
|
||||||
Ping bool `json:"ping,omitempty"`
|
Ping bool `json:"ping,omitempty"`
|
||||||
|
PresenceDB bool `json:"presence_db,omitempty"`
|
||||||
} `json:"debug"`
|
} `json:"debug"`
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
ExeName string `json:"exe_name,omitempty"`
|
ExeName string `json:"exe_name,omitempty"`
|
||||||
@@ -69,7 +70,7 @@ type (
|
|||||||
// MyWhiteList прототип структурки с белым списком jid-ов.
|
// MyWhiteList прототип структурки с белым списком jid-ов.
|
||||||
MyWhiteList struct {
|
MyWhiteList struct {
|
||||||
Whitelist []struct {
|
Whitelist []struct {
|
||||||
RoomName string `json:"room_name,omitempty"`
|
RoomName string `json:"room_name"`
|
||||||
Jid []string `json:"jid,omitempty"`
|
Jid []string `json:"jid,omitempty"`
|
||||||
WipeBans bool `json:"wipe_bans,omitempty"`
|
WipeBans bool `json:"wipe_bans,omitempty"`
|
||||||
} `json:"whitelist,omitempty"`
|
} `json:"whitelist,omitempty"`
|
||||||
@@ -77,18 +78,24 @@ type (
|
|||||||
|
|
||||||
// MyBlackList прототип структурки с чёрным списком jid-ов.
|
// MyBlackList прототип структурки с чёрным списком jid-ов.
|
||||||
MyBlackList struct {
|
MyBlackList struct {
|
||||||
Blacklist []struct {
|
Blacklist []MyBlackListEntry `json:"blacklist"`
|
||||||
RoomName string `json:"room_name,omitempty"`
|
}
|
||||||
JidRe []string `json:"jid_re,omitempty"`
|
|
||||||
NickRe []string `json:"nick_re,omitempty"`
|
// MyBlackListEntry вложенная структура для MyBlackList.
|
||||||
PhraseRe []string `json:"phrase_re,omitempty"`
|
MyBlackListEntry struct {
|
||||||
UserAgent []struct {
|
RoomName string `json:"room_name"`
|
||||||
Name string `json:"name,omitempty"`
|
JidRe []string `json:"jid_re"`
|
||||||
Version string `json:"version,omitempty"`
|
NickRe []string `json:"nick_re"`
|
||||||
Os string `json:"os,omitempty"`
|
PhraseRe []string `json:"phrase_re"`
|
||||||
} `json:"user_agent"`
|
UserAgent []MyBlackListEntryUserAgent `json:"user_agent"`
|
||||||
ReasonEnable bool `json:"reason_enable,omitempty"`
|
ReasonEnable bool `json:"reason_enable,omitempty"`
|
||||||
} `json:"blacklist"`
|
}
|
||||||
|
|
||||||
|
// MyBlackListEntryUserAgent вложенная структура для MyBlackListEntry.
|
||||||
|
MyBlackListEntryUserAgent struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Os string `json:"os"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jabber основная структура-объект, содержащая стейты и проч.
|
// Jabber основная структура-объект, содержащая стейты и проч.
|
||||||
|
|||||||
@@ -45,23 +45,30 @@ func InterfaceToStringSlice(iface any) []string {
|
|||||||
// GetRealJIDfromNick достаёт из запомненных presence-ов по даденному nick-у real jid с resource-ом. Nick должен
|
// GetRealJIDfromNick достаёт из запомненных presence-ов по даденному nick-у real jid с resource-ом. Nick должен
|
||||||
// содержать имя конфы, откуда участник.
|
// содержать имя конфы, откуда участник.
|
||||||
func (j *Jabber) GetRealJIDfromNick(fullNick string) string {
|
func (j *Jabber) GetRealJIDfromNick(fullNick string) string {
|
||||||
var p xmpp.Presence
|
var (
|
||||||
|
presenceJSON []byte
|
||||||
|
ok bool
|
||||||
|
presences []xmpp.Presence
|
||||||
|
)
|
||||||
|
|
||||||
room := (strings.SplitN(fullNick, "/", 2))[0]
|
room := (strings.SplitN(fullNick, "/", 2))[0]
|
||||||
|
|
||||||
// Достанем presence участника.
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONInterface, present := j.RoomPresences.Get(room)
|
presenceJSON, ok = presenceJSONInterface.([]byte)
|
||||||
|
if !ok {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
// Никого нет дома.
|
|
||||||
if !present {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
presenceJSONStrings := InterfaceToStringSlice(presenceJSONInterface)
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
|
|
||||||
for _, presepresenceJSONString := range presenceJSONStrings {
|
|
||||||
_ = json.Unmarshal([]byte(presepresenceJSONString), &p)
|
|
||||||
|
|
||||||
if p.From == fullNick {
|
if p.From == fullNick {
|
||||||
return p.JID
|
return p.JID
|
||||||
}
|
}
|
||||||
@@ -191,17 +198,29 @@ func (j *Jabber) JoinMuc(room string) error {
|
|||||||
j.GTomb.Go(func() error { return j.RotateStatus(room) })
|
j.GTomb.Go(func() error { return j.RotateStatus(room) })
|
||||||
|
|
||||||
// Время проверить участников на предмет злобности.
|
// Время проверить участников на предмет злобности.
|
||||||
namesInterface, present := j.RoomPresences.Get(room)
|
presenceJSONInterface, present := j.RoomPresences.Get(room)
|
||||||
|
|
||||||
// Если room есть в списке presence-ов, то фигачим. room там должен быть, просто обязан.
|
|
||||||
if present {
|
if present {
|
||||||
for _, name := range InterfaceToStringSlice(namesInterface) {
|
presenceJSON, ok := presenceJSONInterface.([]byte)
|
||||||
var v xmpp.Presence
|
|
||||||
|
|
||||||
_ = json.Unmarshal([]byte(name), &v)
|
if !ok {
|
||||||
log.Infof("Fake presence forged for %s just for on-enter check", v.JID)
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var presences []xmpp.Presence
|
||||||
|
|
||||||
|
if err := json.Unmarshal(presenceJSON, &presences); err != nil {
|
||||||
|
log.Errorf("Looks like we have corrupted entry in presence db")
|
||||||
|
|
||||||
|
return nil //nolint: nilerr // If presence db is corrupted it is a bad thing, but we log it anyway.
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range presences { //nolint: gocritic // Развели тут, блять, страну советов, напиши что надо сделать кодом, сука.
|
||||||
|
log.Infof("Fake presence forged for %s just for on-enter check", p.JID)
|
||||||
// Оно там внутри всё само обработает, если вдруг возникнет wire error, то зарекконетится.
|
// Оно там внутри всё само обработает, если вдруг возникнет wire error, то зарекконетится.
|
||||||
_ = j.BunyPresense(v)
|
_ = j.BunyPresense(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user