Merge branch 'master' into dev

This commit is contained in:
Bohdan Horbeshko 2023-08-26 08:59:14 -04:00
commit 8ba7596ab5
8 changed files with 131 additions and 52 deletions

View file

@ -2,7 +2,7 @@
COMMIT := $(shell git rev-parse --short HEAD) COMMIT := $(shell git rev-parse --short HEAD)
TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1" TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1"
VERSION := "v1.7.2" VERSION := "v1.8.0-dev"
MAKEOPTS := "-j4" MAKEOPTS := "-j4"
all: all:

View file

@ -133,3 +133,13 @@ func (cache *Cache) SetStatus(id int64, show string, status string) {
Description: status, Description: status,
} }
} }
// Destruct splits a cached status into show, description and type
func (status *Status) Destruct() (show, description, typ string) {
show, description = status.XMPP, status.Description
if show == "unavailable" {
typ = show
show = ""
}
return
}

View file

@ -384,7 +384,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string
} }
case "config": case "config":
if len(args) > 1 { if len(args) > 1 {
if !gateway.MessageOutgoingPermission && args[0] == "carbons" && args[1] == "true" { if gateway.MessageOutgoingPermissionVersion == 0 && args[0] == "carbons" && args[1] == "true" {
return "The server did not allow to enable carbons" return "The server did not allow to enable carbons"
} }
@ -658,7 +658,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
} }
if messages != nil && messages.Messages != nil { if messages != nil && messages.Messages != nil {
for _, message := range messages.Messages { for _, message := range messages.Messages {
c.ProcessIncomingMessage(targetChatId, message, "") c.ProcessIncomingMessage(targetChatId, message)
} }
} }
// print vCard // print vCard

View file

@ -205,27 +205,24 @@ func (c *Client) updateChatLastMessage(update *client.UpdateChatLastMessage) {
func (c *Client) updateNewMessage(update *client.UpdateNewMessage) { func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
chatId := update.Message.ChatId chatId := update.Message.ChatId
c.SendMessageLock.Lock()
c.SendMessageLock.Unlock()
xmppId, err := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, chatId, update.Message.Id)
var ignoredResource string
if err == nil {
ignoredResource = c.popFromOutbox(xmppId)
} else {
log.Infof("Couldn't retrieve XMPP message ids for %v, an echo may happen", update.Message.Id)
}
// guarantee sequential message delivering per chat // guarantee sequential message delivering per chat
lock := c.getChatMessageLock(chatId) lock := c.getChatMessageLock(chatId)
go func() { go func() {
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
// ignore self outgoing messages
if update.Message.IsOutgoing &&
update.Message.SendingState != nil &&
update.Message.SendingState.MessageSendingStateType() == client.TypeMessageSendingStatePending {
return
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"chat_id": chatId, "chat_id": chatId,
}).Warn("New message from chat") }).Warn("New message from chat")
c.ProcessIncomingMessage(chatId, update.Message, ignoredResource) c.ProcessIncomingMessage(chatId, update.Message)
c.updateLastMessageHash(update.Message.ChatId, update.Message.Id, update.Message.Content) c.updateLastMessageHash(update.Message.ChatId, update.Message.Id, update.Message.Content)
}() }()

View file

@ -243,15 +243,33 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
cachedStatus, ok := c.cache.GetStatus(chatID) cachedStatus, ok := c.cache.GetStatus(chatID)
if status == "" { if status == "" {
if ok { if ok {
show, status = cachedStatus.XMPP, cachedStatus.Description var typ string
show, status, typ = cachedStatus.Destruct()
if presenceType == "" {
presenceType = typ
}
log.WithFields(log.Fields{
"show": show,
"status": status,
"presenceType": presenceType,
}).Debug("Cached status")
} else if user != nil && user.Status != nil { } else if user != nil && user.Status != nil {
show, status, presenceType = c.userStatusToText(user.Status, chatID) show, status, presenceType = c.userStatusToText(user.Status, chatID)
log.WithFields(log.Fields{
"show": show,
"status": status,
"presenceType": presenceType,
}).Debug("Status to text")
} else { } else {
show, status = "chat", chat.Title show, status = "chat", chat.Title
} }
} }
c.cache.SetStatus(chatID, show, status) cacheShow := show
if presenceType == "unavailable" {
cacheShow = presenceType
}
c.cache.SetStatus(chatID, cacheShow, status)
newArgs := []args.V{ newArgs := []args.V{
gateway.SPFrom(strconv.FormatInt(chatID, 10)), gateway.SPFrom(strconv.FormatInt(chatID, 10)),
@ -837,7 +855,7 @@ func (c *Client) messageToPrefix(message *client.Message, previewString string,
if err != nil { if err != nil {
log.Errorf("Could not determine if chat is PM: %v", err) log.Errorf("Could not determine if chat is PM: %v", err)
} }
isCarbonsEnabled := gateway.MessageOutgoingPermission && c.Session.Carbons isCarbonsEnabled := gateway.MessageOutgoingPermissionVersion > 0 && c.Session.Carbons
// with carbons, hide for all messages in PM and only for outgoing in group chats // with carbons, hide for all messages in PM and only for outgoing in group chats
hideSender := isCarbonsEnabled && (message.IsOutgoing || isPM) hideSender := isCarbonsEnabled && (message.IsOutgoing || isPM)
@ -914,18 +932,9 @@ func (c *Client) ensureDownloadFile(file *client.File) *client.File {
} }
// ProcessIncomingMessage transfers a message to XMPP side and marks it as read on Telegram side // ProcessIncomingMessage transfers a message to XMPP side and marks it as read on Telegram side
func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message, ignoredResource string) { func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
var isCarbon bool isCarbon := gateway.MessageOutgoingPermissionVersion > 0 && c.Session.Carbons && message.IsOutgoing
isOutgoing := message.IsOutgoing jids := c.getCarbonFullJids(isCarbon, "")
if gateway.MessageOutgoingPermission && c.Session.Carbons {
isCarbon = isOutgoing
}
jids := c.getCarbonFullJids(isOutgoing, ignoredResource)
if len(jids) == 0 {
log.Info("The only resource is ignored, aborting")
return
}
var text, oob, auxText string var text, oob, auxText string
@ -1369,12 +1378,26 @@ func (c *Client) UpdateChatNicknames() {
for _, id := range c.cache.ChatsKeys() { for _, id := range c.cache.ChatsKeys() {
chat, ok := c.cache.GetChat(id) chat, ok := c.cache.GetChat(id)
if ok { if ok {
newArgs := []args.V{
gateway.SPFrom(strconv.FormatInt(id, 10)),
gateway.SPNickname(chat.Title),
}
cachedStatus, ok := c.cache.GetStatus(id)
if ok {
show, status, typ := cachedStatus.Destruct()
newArgs = append(newArgs, gateway.SPShow(show), gateway.SPStatus(status))
if typ != "" {
newArgs = append(newArgs, gateway.SPType(typ))
}
}
gateway.SendPresence( gateway.SendPresence(
c.xmpp, c.xmpp,
c.jid, c.jid,
gateway.SPFrom(strconv.FormatInt(id, 10)), newArgs...,
gateway.SPNickname(chat.Title),
) )
gateway.SetNickname(c.jid, strconv.FormatInt(id, 10), chat.Title, c.xmpp) gateway.SetNickname(c.jid, strconv.FormatInt(id, 10), chat.Title, c.xmpp)
} }
} }

View file

@ -154,12 +154,19 @@ type CarbonSent struct {
} }
// ComponentPrivilege is from XEP-0356 // ComponentPrivilege is from XEP-0356
type ComponentPrivilege struct { type ComponentPrivilege1 struct {
XMLName xml.Name `xml:"urn:xmpp:privilege:1 privilege"` XMLName xml.Name `xml:"urn:xmpp:privilege:1 privilege"`
Perms []ComponentPerm `xml:"perm"` Perms []ComponentPerm `xml:"perm"`
Forwarded stanza.Forwarded `xml:"urn:xmpp:forward:0 forwarded"` Forwarded stanza.Forwarded `xml:"urn:xmpp:forward:0 forwarded"`
} }
// ComponentPrivilege is from XEP-0356
type ComponentPrivilege2 struct {
XMLName xml.Name `xml:"urn:xmpp:privilege:2 privilege"`
Perms []ComponentPerm `xml:"perm"`
Forwarded stanza.Forwarded `xml:"urn:xmpp:forward:0 forwarded"`
}
// ComponentPerm is from XEP-0356 // ComponentPerm is from XEP-0356
type ComponentPerm struct { type ComponentPerm struct {
XMLName xml.Name `xml:"perm"` XMLName xml.Name `xml:"perm"`
@ -227,7 +234,12 @@ func (c CarbonSent) Namespace() string {
} }
// Namespace is a namespace! // Namespace is a namespace!
func (c ComponentPrivilege) Namespace() string { func (c ComponentPrivilege1) Namespace() string {
return c.XMLName.Space
}
// Namespace is a namespace!
func (c ComponentPrivilege2) Namespace() string {
return c.XMLName.Space return c.XMLName.Space
} }
@ -297,11 +309,17 @@ func init() {
"sent", "sent",
}, CarbonSent{}) }, CarbonSent{})
// component privilege // component privilege v1
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{ stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
"urn:xmpp:privilege:1", "urn:xmpp:privilege:1",
"privilege", "privilege",
}, ComponentPrivilege{}) }, ComponentPrivilege1{})
// component privilege v2
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
"urn:xmpp:privilege:2",
"privilege",
}, ComponentPrivilege2{})
// message edit // message edit
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{ stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{

View file

@ -38,8 +38,8 @@ var IdsDB badger.IdsDB
// were changed and need to be re-flushed to the YamlDB // were changed and need to be re-flushed to the YamlDB
var DirtySessions = false var DirtySessions = false
// MessageOutgoingPermission allows to fake outgoing messages by foreign JIDs // MessageOutgoingPermissionVersion contains a XEP-0356 version to fake outgoing messages by foreign JIDs
var MessageOutgoingPermission = false var MessageOutgoingPermissionVersion = 0
// SendMessage creates and sends a message stanza // SendMessage creates and sends a message stanza
func SendMessage(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, isCarbon bool) { func SendMessage(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, isCarbon bool) {
@ -142,11 +142,19 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
To: toJid.Domain, To: toJid.Domain,
}, },
} }
privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege{ if MessageOutgoingPermissionVersion == 2 {
privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege2{
Forwarded: stanza.Forwarded{ Forwarded: stanza.Forwarded{
Stanza: carbonMessage, Stanza: carbonMessage,
}, },
}) })
} else {
privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege1{
Forwarded: stanza.Forwarded{
Stanza: carbonMessage,
},
})
}
sendMessage(&privilegeMessage, component) sendMessage(&privilegeMessage, component)
} else { } else {
sendMessage(&message, component) sendMessage(&message, component)

View file

@ -15,6 +15,7 @@ import (
"dev.narayana.im/narayana/telegabber/xmpp/gateway" "dev.narayana.im/narayana/telegabber/xmpp/gateway"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/soheilhy/args"
"gosrc.io/xmpp" "gosrc.io/xmpp"
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
@ -148,7 +149,12 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
"end": body.End, "end": body.End,
}).Warn(errors.Wrap(err, "Failed to parse fallback end!")) }).Warn(errors.Wrap(err, "Failed to parse fallback end!"))
} }
text = text[:start] + text[end:]
fullRunes := []rune(text)
cutRunes := make([]rune, 0, len(text)-int(end-start))
cutRunes = append(cutRunes, fullRunes[:start]...)
cutRunes = append(cutRunes, fullRunes[end:]...)
text = string(cutRunes)
} }
} }
var replaceId int64 var replaceId int64
@ -183,7 +189,6 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
if err != nil { if err != nil {
log.Errorf("Failed to save ids %v/%v %v", toID, tgMessageId, msg.Id) log.Errorf("Failed to save ids %v/%v %v", toID, tgMessageId, msg.Id)
} }
session.AddToOutbox(msg.Id, resource)
} }
} else { } else {
/* /*
@ -210,14 +215,25 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
} }
if msg.Body == "" { if msg.Body == "" {
var privilege extensions.ComponentPrivilege var privilege1 extensions.ComponentPrivilege1
if ok := msg.Get(&privilege); ok { if ok := msg.Get(&privilege1); ok {
log.Debugf("privilege: %#v", privilege) log.Debugf("privilege1: %#v", privilege1)
} }
for _, perm := range privilege.Perms { for _, perm := range privilege1.Perms {
if perm.Access == "message" && perm.Type == "outgoing" { if perm.Access == "message" && perm.Type == "outgoing" {
gateway.MessageOutgoingPermission = true gateway.MessageOutgoingPermissionVersion = 1
}
}
var privilege2 extensions.ComponentPrivilege2
if ok := msg.Get(&privilege2); ok {
log.Debugf("privilege2: %#v", privilege2)
}
for _, perm := range privilege2.Perms {
if perm.Access == "message" && perm.Type == "outgoing" {
gateway.MessageOutgoingPermissionVersion = 2
} }
} }
} }
@ -339,11 +355,18 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
log.Error(errors.Wrap(err, "TDlib connection failure")) log.Error(errors.Wrap(err, "TDlib connection failure"))
} else { } else {
for status := range session.StatusesRange() { for status := range session.StatusesRange() {
show, description, typ := status.Destruct()
newArgs := []args.V{
gateway.SPImmed(false),
}
if typ != "" {
newArgs = append(newArgs, gateway.SPType(typ))
}
go session.ProcessStatusUpdate( go session.ProcessStatusUpdate(
status.ID, status.ID,
status.Description, description,
status.XMPP, show,
gateway.SPImmed(false), newArgs...,
) )
} }
session.UpdateChatNicknames() session.UpdateChatNicknames()