Merge branch 'master' into dev
This commit is contained in:
commit
8ba7596ab5
2
Makefile
2
Makefile
|
@ -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:
|
||||||
|
|
10
telegram/cache/cache.go
vendored
10
telegram/cache/cache.go
vendored
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue