Send recent history on MUC join
This commit is contained in:
parent
c1887e5a1e
commit
e77caf2c42
|
@ -64,6 +64,8 @@ type Client struct {
|
||||||
lastMsgHashes map[int64]uint64
|
lastMsgHashes map[int64]uint64
|
||||||
msgHashSeed maphash.Seed
|
msgHashSeed maphash.Seed
|
||||||
|
|
||||||
|
mucResources map[int64]map[string]bool
|
||||||
|
|
||||||
locks clientLocks
|
locks clientLocks
|
||||||
SendMessageLock sync.Mutex
|
SendMessageLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -73,6 +75,7 @@ type clientLocks struct {
|
||||||
chatMessageLocks map[int64]*sync.Mutex
|
chatMessageLocks map[int64]*sync.Mutex
|
||||||
resourcesLock sync.Mutex
|
resourcesLock sync.Mutex
|
||||||
outboxLock sync.Mutex
|
outboxLock sync.Mutex
|
||||||
|
mucResourcesLock sync.Mutex
|
||||||
lastMsgHashesLock sync.Mutex
|
lastMsgHashesLock sync.Mutex
|
||||||
|
|
||||||
authorizerReadLock sync.Mutex
|
authorizerReadLock sync.Mutex
|
||||||
|
@ -133,6 +136,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
|
||||||
Session: session,
|
Session: session,
|
||||||
resources: make(map[string]bool),
|
resources: make(map[string]bool),
|
||||||
outbox: make(map[string]string),
|
outbox: make(map[string]string),
|
||||||
|
mucResources: make(map[int64]map[string]bool),
|
||||||
content: &conf.Content,
|
content: &conf.Content,
|
||||||
cache: cache.NewCache(),
|
cache: cache.NewCache(),
|
||||||
options: options,
|
options: options,
|
||||||
|
|
|
@ -193,23 +193,6 @@ func (c *Client) unsubscribe(chatID int64) error {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message) {
|
|
||||||
for i := len(messages) - 1; i >= 0; i-- {
|
|
||||||
message := messages[i]
|
|
||||||
reply, _ := c.getMessageReply(message)
|
|
||||||
|
|
||||||
gateway.SendMessage(
|
|
||||||
c.jid,
|
|
||||||
strconv.FormatInt(chatID, 10),
|
|
||||||
c.formatMessage(0, 0, false, message),
|
|
||||||
strconv.FormatInt(message.Id, 10),
|
|
||||||
c.xmpp,
|
|
||||||
reply,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) usernameOrIDToID(username string) (int64, error) {
|
func (c *Client) usernameOrIDToID(username string) (int64, error) {
|
||||||
userID, err := strconv.ParseInt(username, 10, 64)
|
userID, err := strconv.ParseInt(username, 10, 64)
|
||||||
// couldn't parse the id, try to lookup as a username
|
// couldn't parse the id, try to lookup as a username
|
||||||
|
@ -1005,7 +988,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
|
||||||
return err.Error(), true
|
return err.Error(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
c.sendMessagesReverse(chatID, messages.Messages)
|
c.sendMessagesReverse(chatID, messages.Messages, true, "")
|
||||||
// get latest entries from history
|
// get latest entries from history
|
||||||
case "history":
|
case "history":
|
||||||
var limit int32 = 10
|
var limit int32 = 10
|
||||||
|
@ -1016,32 +999,11 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var newMessages *client.Messages
|
messages, err := c.getNLastMessages(chatID, limit)
|
||||||
var messages []*client.Message
|
if err != nil {
|
||||||
var err error
|
return err.Error(), true
|
||||||
var fromId int64
|
|
||||||
for _ = range make([]struct{}, limit) { // safety limit
|
|
||||||
if len(messages) > 0 {
|
|
||||||
fromId = messages[len(messages)-1].Id
|
|
||||||
}
|
|
||||||
|
|
||||||
newMessages, err = c.client.GetChatHistory(&client.GetChatHistoryRequest{
|
|
||||||
ChatId: chatID,
|
|
||||||
FromMessageId: fromId,
|
|
||||||
Limit: limit,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err.Error(), true
|
|
||||||
}
|
|
||||||
|
|
||||||
messages = append(messages, newMessages.Messages...)
|
|
||||||
|
|
||||||
if len(newMessages.Messages) == 0 || len(messages) >= int(limit) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
c.sendMessagesReverse(chatID, messages, true, "")
|
||||||
c.sendMessagesReverse(chatID, messages)
|
|
||||||
// chat members
|
// chat members
|
||||||
case "members":
|
case "members":
|
||||||
var query string
|
var query string
|
||||||
|
|
|
@ -265,7 +265,7 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
||||||
markupFunction,
|
markupFunction,
|
||||||
))
|
))
|
||||||
for _, jid := range jids {
|
for _, jid := range jids {
|
||||||
gateway.SendMessage(jid, strconv.FormatInt(update.ChatId, 10), text, "e"+strconv.FormatInt(update.MessageId, 10), c.xmpp, nil, false)
|
gateway.SendMessage(jid, strconv.FormatInt(update.ChatId, 10), text, "e"+strconv.FormatInt(update.MessageId, 10), c.xmpp, nil, 0, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,12 @@ var replyRegex = regexp.MustCompile("\\A>>? ?([0-9]+)\\n")
|
||||||
const newlineChar string = "\n"
|
const newlineChar string = "\n"
|
||||||
const messageHeaderSeparator string = " | "
|
const messageHeaderSeparator string = " | "
|
||||||
|
|
||||||
|
const (
|
||||||
|
ChatTypeOther byte = iota
|
||||||
|
ChatTypePM
|
||||||
|
ChatTypeGroup
|
||||||
|
)
|
||||||
|
|
||||||
// GetContactByUsername resolves username to user id retrieves user and chat information
|
// GetContactByUsername resolves username to user id retrieves user and chat information
|
||||||
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
|
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
|
||||||
if !c.Online() {
|
if !c.Online() {
|
||||||
|
@ -121,10 +127,10 @@ func (c *Client) GetContactByID(id int64, chat *client.Chat) (*client.Chat, *cli
|
||||||
return chat, user, nil
|
return chat, user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPM checks if a chat is PM
|
// GetChatType checks if a chat is PM or group
|
||||||
func (c *Client) IsPM(id int64) (bool, error) {
|
func (c *Client) GetChatType(id int64) (byte, error) {
|
||||||
if !c.Online() || id == 0 {
|
if !c.Online() || id == 0 {
|
||||||
return false, errOffline
|
return ChatTypeOther, errOffline
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -135,7 +141,7 @@ func (c *Client) IsPM(id int64) (bool, error) {
|
||||||
ChatId: id,
|
ChatId: id,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return ChatTypeOther, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cache.SetChat(id, chat)
|
c.cache.SetChat(id, chat)
|
||||||
|
@ -143,9 +149,12 @@ func (c *Client) IsPM(id int64) (bool, error) {
|
||||||
|
|
||||||
chatType := chat.Type.ChatTypeType()
|
chatType := chat.Type.ChatTypeType()
|
||||||
if chatType == client.TypeChatTypePrivate || chatType == client.TypeChatTypeSecret {
|
if chatType == client.TypeChatTypePrivate || chatType == client.TypeChatTypeSecret {
|
||||||
return true, nil
|
return ChatTypePM, nil
|
||||||
}
|
}
|
||||||
return false, nil
|
if c.IsGroup(chat) {
|
||||||
|
return ChatTypeGroup, nil
|
||||||
|
}
|
||||||
|
return ChatTypeOther, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) userStatusToText(status client.UserStatus, chatID int64) (string, string, string) {
|
func (c *Client) userStatusToText(status client.UserStatus, chatID int64) (string, string, string) {
|
||||||
|
@ -294,25 +303,52 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SendMUCStatuses(chatID int64) {
|
// JoinMUC saves MUC join fact and sends initialization data
|
||||||
|
func (c *Client) JoinMUC(chatId int64, resource string) {
|
||||||
|
// save the nickname in this MUC, also as a marker of join
|
||||||
|
c.locks.mucResourcesLock.Lock()
|
||||||
|
oldMap, ok := c.mucResources[chatId]
|
||||||
|
if ok {
|
||||||
|
_, ok := oldMap[resource]
|
||||||
|
if ok {
|
||||||
|
// already joined, initializing anyway
|
||||||
|
} else {
|
||||||
|
oldMap[resource] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newMap := make(map[string]bool)
|
||||||
|
newMap[resource] = true
|
||||||
|
c.mucResources[chatId] = newMap
|
||||||
|
}
|
||||||
|
c.locks.mucResourcesLock.Unlock()
|
||||||
|
|
||||||
|
c.sendMUCStatuses(chatId)
|
||||||
|
|
||||||
|
messages, err := c.getNLastMessages(chatId, 20)
|
||||||
|
if err == nil {
|
||||||
|
c.sendMessagesReverse(chatId, messages, false, c.jid+"/"+resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) sendMUCStatuses(chatID int64) {
|
||||||
|
sChatId := strconv.FormatInt(chatID, 10)
|
||||||
|
myNickname := "me"
|
||||||
|
if c.me != nil {
|
||||||
|
myNickname := c.me.FirstName
|
||||||
|
if c.me.LastName != "" {
|
||||||
|
myNickname = myNickname + " " + c.me.LastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myAffiliation := "member"
|
||||||
|
|
||||||
members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
|
members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
|
||||||
ChatId: chatID,
|
ChatId: chatID,
|
||||||
Limit: 200,
|
Limit: 200,
|
||||||
Filter: &client.ChatMembersFilterMembers{},
|
Filter: &client.ChatMembersFilterMembers{},
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
chatIDString := strconv.FormatInt(chatID, 10)
|
|
||||||
gatewayJidSuffix := "@" + gateway.Jid.Full()
|
gatewayJidSuffix := "@" + gateway.Jid.Full()
|
||||||
|
|
||||||
myNickname := "me"
|
|
||||||
if c.me != nil {
|
|
||||||
myNickname := c.me.FirstName
|
|
||||||
if c.me.LastName != "" {
|
|
||||||
myNickname = myNickname + " " + c.me.LastName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myAffiliation := "member"
|
|
||||||
|
|
||||||
for _, member := range members.Members {
|
for _, member := range members.Members {
|
||||||
var senderId int64
|
var senderId int64
|
||||||
switch member.MemberId.MessageSenderType() {
|
switch member.MemberId.MessageSenderType() {
|
||||||
|
@ -324,7 +360,7 @@ func (c *Client) SendMUCStatuses(chatID int64) {
|
||||||
senderId = memberChat.ChatId
|
senderId = memberChat.ChatId
|
||||||
}
|
}
|
||||||
|
|
||||||
nickname := c.formatContact(senderId)
|
nickname := c.getMUCNickname(senderId)
|
||||||
affiliation := c.memberStatusToAffiliation(member.Status)
|
affiliation := c.memberStatusToAffiliation(member.Status)
|
||||||
if c.me != nil && senderId == c.me.Id {
|
if c.me != nil && senderId == c.me.Id {
|
||||||
myNickname = nickname
|
myNickname = nickname
|
||||||
|
@ -335,25 +371,29 @@ func (c *Client) SendMUCStatuses(chatID int64) {
|
||||||
gateway.SendPresence(
|
gateway.SendPresence(
|
||||||
c.xmpp,
|
c.xmpp,
|
||||||
c.jid,
|
c.jid,
|
||||||
gateway.SPFrom(chatIDString),
|
gateway.SPFrom(sChatId),
|
||||||
gateway.SPResource(nickname),
|
gateway.SPResource(nickname),
|
||||||
gateway.SPImmed(true),
|
gateway.SPImmed(true),
|
||||||
gateway.SPMUCAffiliation(affiliation),
|
gateway.SPMUCAffiliation(affiliation),
|
||||||
gateway.SPMUCJid(strconv.FormatInt(senderId, 10) + gatewayJidSuffix),
|
gateway.SPMUCJid(strconv.FormatInt(senderId, 10) + gatewayJidSuffix),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// according to the spec, own member entry should be sent the last
|
|
||||||
gateway.SendPresence(
|
|
||||||
c.xmpp,
|
|
||||||
c.jid,
|
|
||||||
gateway.SPFrom(chatIDString),
|
|
||||||
gateway.SPResource(myNickname),
|
|
||||||
gateway.SPImmed(true),
|
|
||||||
gateway.SPMUCAffiliation(myAffiliation),
|
|
||||||
gateway.SPMUCStatusCodes([]uint16{100, 110, 210}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// according to the spec, own member entry should be sent the last
|
||||||
|
gateway.SendPresence(
|
||||||
|
c.xmpp,
|
||||||
|
c.jid,
|
||||||
|
gateway.SPFrom(sChatId),
|
||||||
|
gateway.SPResource(myNickname),
|
||||||
|
gateway.SPImmed(true),
|
||||||
|
gateway.SPMUCAffiliation(myAffiliation),
|
||||||
|
gateway.SPMUCStatusCodes([]uint16{100, 110, 210}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getMUCNickname(chatID int64) string {
|
||||||
|
return c.formatContact(chatID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) formatContact(chatID int64) string {
|
func (c *Client) formatContact(chatID int64) string {
|
||||||
|
@ -917,13 +957,13 @@ func (c *Client) countCharsInLines(lines *[]string) (count int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) messageToPrefix(message *client.Message, previewString string, fileString string, replyMsg *client.Message) (string, int, int) {
|
func (c *Client) messageToPrefix(message *client.Message, previewString string, fileString string, replyMsg *client.Message) (string, int, int) {
|
||||||
isPM, err := c.IsPM(message.ChatId)
|
chatType, err := c.GetChatType(message.ChatId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Could not determine if chat is PM: %v", err)
|
log.Errorf("Could not determine chat type: %v", err)
|
||||||
}
|
}
|
||||||
isCarbonsEnabled := gateway.MessageOutgoingPermissionVersion > 0 && 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 || chatType == ChatTypePM)) || (c.Session.MUC && chatType == ChatTypeGroup)
|
||||||
|
|
||||||
var replyStart, replyEnd int
|
var replyStart, replyEnd int
|
||||||
prefix := []string{}
|
prefix := []string{}
|
||||||
|
@ -944,7 +984,7 @@ func (c *Client) messageToPrefix(message *client.Message, previewString string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isPM || !c.Session.HideIds {
|
if chatType != ChatTypePM || !c.Session.HideIds {
|
||||||
prefix = append(prefix, directionChar+strconv.FormatInt(message.Id, 10))
|
prefix = append(prefix, directionChar+strconv.FormatInt(message.Id, 10))
|
||||||
}
|
}
|
||||||
// show sender in group chats
|
// show sender in group chats
|
||||||
|
@ -999,8 +1039,20 @@ 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) {
|
func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
|
||||||
isCarbon := gateway.MessageOutgoingPermissionVersion > 0 && c.Session.Carbons && message.IsOutgoing
|
c.sendMessageToGateway(chatId, message, false, "", []string{})
|
||||||
jids := c.getCarbonFullJids(isCarbon, "")
|
}
|
||||||
|
|
||||||
|
func (c *Client) sendMessageToGateway(chatId int64, message *client.Message, delay bool, groupChatFrom string, groupChatTos []string) {
|
||||||
|
var isCarbon bool
|
||||||
|
var jids []string
|
||||||
|
var isGroupchat bool
|
||||||
|
if len(groupChatTos) == 0 {
|
||||||
|
isCarbon = gateway.MessageOutgoingPermissionVersion > 0 && c.Session.Carbons && message.IsOutgoing
|
||||||
|
jids = c.getCarbonFullJids(isCarbon, "")
|
||||||
|
} else {
|
||||||
|
isGroupchat = true
|
||||||
|
jids = groupChatTos
|
||||||
|
}
|
||||||
|
|
||||||
var text, oob, auxText string
|
var text, oob, auxText string
|
||||||
|
|
||||||
|
@ -1073,12 +1125,22 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
|
||||||
|
|
||||||
// forward message to XMPP
|
// forward message to XMPP
|
||||||
sId := strconv.FormatInt(message.Id, 10)
|
sId := strconv.FormatInt(message.Id, 10)
|
||||||
sChatId := strconv.FormatInt(chatId, 10)
|
var from string
|
||||||
|
if groupChatFrom == "" {
|
||||||
|
from = strconv.FormatInt(chatId, 10)
|
||||||
|
} else {
|
||||||
|
from = groupChatFrom
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp int64
|
||||||
|
if delay {
|
||||||
|
timestamp = int64(message.Date)
|
||||||
|
}
|
||||||
|
|
||||||
for _, jid := range jids {
|
for _, jid := range jids {
|
||||||
gateway.SendMessageWithOOB(jid, sChatId, text, sId, c.xmpp, reply, oob, isCarbon)
|
gateway.SendMessageWithOOB(jid, from, text, sId, c.xmpp, reply, timestamp, oob, isCarbon, isGroupchat)
|
||||||
if auxText != "" {
|
if auxText != "" {
|
||||||
gateway.SendMessage(jid, sChatId, auxText, sId, c.xmpp, reply, isCarbon)
|
gateway.SendMessage(jid, from, auxText, sId, c.xmpp, reply, timestamp, isCarbon, isGroupchat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1294,6 +1356,36 @@ func (c *Client) getLastMessages(id int64, query string, from int64, count int32
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) getNLastMessages(chatID int64, limit int32) ([]*client.Message, error) {
|
||||||
|
var newMessages *client.Messages
|
||||||
|
var messages []*client.Message
|
||||||
|
var err error
|
||||||
|
var fromId int64
|
||||||
|
|
||||||
|
for _ = range make([]struct{}, limit) { // safety limit
|
||||||
|
if len(messages) > 0 {
|
||||||
|
fromId = messages[len(messages)-1].Id
|
||||||
|
}
|
||||||
|
|
||||||
|
newMessages, err = c.client.GetChatHistory(&client.GetChatHistoryRequest{
|
||||||
|
ChatId: chatID,
|
||||||
|
FromMessageId: fromId,
|
||||||
|
Limit: limit,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = append(messages, newMessages.Messages...)
|
||||||
|
|
||||||
|
if len(newMessages.Messages) == 0 || len(messages) >= int(limit) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DownloadFile actually obtains a file by id given by TDlib
|
// DownloadFile actually obtains a file by id given by TDlib
|
||||||
func (c *Client) DownloadFile(id int32, priority int32, synchronous bool) (*client.File, error) {
|
func (c *Client) DownloadFile(id int32, priority int32, synchronous bool) (*client.File, error) {
|
||||||
return c.client.DownloadFile(&client.DownloadFileRequest{
|
return c.client.DownloadFile(&client.DownloadFileRequest{
|
||||||
|
@ -1652,3 +1744,39 @@ func (c *Client) memberStatusToAffiliation(memberStatus client.ChatMemberStatus)
|
||||||
}
|
}
|
||||||
return "member"
|
return "member"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, plain bool, toJid string) {
|
||||||
|
sChatId := strconv.FormatInt(chatID, 10)
|
||||||
|
var mucJid string
|
||||||
|
if toJid != "" {
|
||||||
|
mucJid = sChatId + "@" + gateway.Jid.Bare()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(messages) - 1; i >= 0; i-- {
|
||||||
|
message := messages[i]
|
||||||
|
|
||||||
|
if plain {
|
||||||
|
reply, _ := c.getMessageReply(message)
|
||||||
|
|
||||||
|
gateway.SendMessage(
|
||||||
|
c.jid,
|
||||||
|
sChatId,
|
||||||
|
c.formatMessage(0, 0, false, message),
|
||||||
|
strconv.FormatInt(message.Id, 10),
|
||||||
|
c.xmpp,
|
||||||
|
reply,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
c.sendMessageToGateway(
|
||||||
|
chatID,
|
||||||
|
message,
|
||||||
|
true,
|
||||||
|
mucJid + "/" + c.getMUCNickname(c.getSenderId(message)),
|
||||||
|
[]string{toJid},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -234,6 +234,20 @@ type PresenceXMucUserStatus struct {
|
||||||
Code uint16 `xml:"code,attr"`
|
Code uint16 `xml:"code,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MessageDelay is from XEP-0203
|
||||||
|
type MessageDelay struct {
|
||||||
|
XMLName xml.Name `xml:"urn:xmpp:delay delay"`
|
||||||
|
From string `xml:"from,attr"`
|
||||||
|
Stamp string `xml:"stamp,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageDelayLegacy is from XEP-0203
|
||||||
|
type MessageDelayLegacy struct {
|
||||||
|
XMLName xml.Name `xml:"jabber:x:delay x"`
|
||||||
|
From string `xml:"from,attr"`
|
||||||
|
Stamp string `xml:"stamp,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
// Namespace is a namespace!
|
// Namespace is a namespace!
|
||||||
func (c PresenceNickExtension) Namespace() string {
|
func (c PresenceNickExtension) Namespace() string {
|
||||||
return c.XMLName.Space
|
return c.XMLName.Space
|
||||||
|
@ -304,6 +318,16 @@ func (c PresenceXMucUserExtension) Namespace() string {
|
||||||
return c.XMLName.Space
|
return c.XMLName.Space
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Namespace is a namespace!
|
||||||
|
func (c MessageDelay) Namespace() string {
|
||||||
|
return c.XMLName.Space
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespace is a namespace!
|
||||||
|
func (c MessageDelayLegacy) Namespace() string {
|
||||||
|
return c.XMLName.Space
|
||||||
|
}
|
||||||
|
|
||||||
// Name is a packet name
|
// Name is a packet name
|
||||||
func (ClientMessage) Name() string {
|
func (ClientMessage) Name() string {
|
||||||
return "message"
|
return "message"
|
||||||
|
@ -394,4 +418,16 @@ func init() {
|
||||||
"http://jabber.org/protocol/muc#user",
|
"http://jabber.org/protocol/muc#user",
|
||||||
"x",
|
"x",
|
||||||
}, PresenceXMucUserExtension{})
|
}, PresenceXMucUserExtension{})
|
||||||
|
|
||||||
|
// message delay
|
||||||
|
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
|
||||||
|
"urn:xmpp:delay",
|
||||||
|
"delay",
|
||||||
|
}, MessageDelay{})
|
||||||
|
|
||||||
|
// legacy message delay
|
||||||
|
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
|
||||||
|
"jabber:x:delay",
|
||||||
|
"x",
|
||||||
|
}, MessageDelayLegacy{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"dev.narayana.im/narayana/telegabber/badger"
|
"dev.narayana.im/narayana/telegabber/badger"
|
||||||
"dev.narayana.im/narayana/telegabber/xmpp/extensions"
|
"dev.narayana.im/narayana/telegabber/xmpp/extensions"
|
||||||
|
@ -42,26 +43,26 @@ var DirtySessions = false
|
||||||
var MessageOutgoingPermissionVersion = 0
|
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, timestamp int64, isCarbon, isGroupchat bool) {
|
||||||
sendMessageWrapper(to, from, body, id, component, reply, "", isCarbon)
|
sendMessageWrapper(to, from, body, id, component, reply, timestamp, "", isCarbon, isGroupchat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendServiceMessage creates and sends a simple message stanza from transport
|
// SendServiceMessage creates and sends a simple message stanza from transport
|
||||||
func SendServiceMessage(to string, body string, component *xmpp.Component) {
|
func SendServiceMessage(to string, body string, component *xmpp.Component) {
|
||||||
sendMessageWrapper(to, "", body, "", component, nil, "", false)
|
sendMessageWrapper(to, "", body, "", component, nil, 0, "", false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTextMessage creates and sends a simple message stanza
|
// SendTextMessage creates and sends a simple message stanza
|
||||||
func SendTextMessage(to string, from string, body string, component *xmpp.Component) {
|
func SendTextMessage(to string, from string, body string, component *xmpp.Component) {
|
||||||
sendMessageWrapper(to, from, body, "", component, nil, "", false)
|
sendMessageWrapper(to, from, body, "", component, nil, 0, "", false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMessageWithOOB creates and sends a message stanza with OOB URL
|
// SendMessageWithOOB creates and sends a message stanza with OOB URL
|
||||||
func SendMessageWithOOB(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, oob string, isCarbon bool) {
|
func SendMessageWithOOB(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, timestamp int64, oob string, isCarbon bool, isGroupchat bool) {
|
||||||
sendMessageWrapper(to, from, body, id, component, reply, oob, isCarbon)
|
sendMessageWrapper(to, from, body, id, component, reply, timestamp, oob, isCarbon, isGroupchat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMessageWrapper(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, oob string, isCarbon bool) {
|
func sendMessageWrapper(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, timestamp int64, oob string, isCarbon bool, isGroupchat bool) {
|
||||||
toJid, err := stanza.NewJid(to)
|
toJid, err := stanza.NewJid(to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
|
@ -76,12 +77,17 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
|
||||||
var logFrom string
|
var logFrom string
|
||||||
var messageFrom string
|
var messageFrom string
|
||||||
var messageTo string
|
var messageTo string
|
||||||
if from == "" {
|
if isGroupchat {
|
||||||
logFrom = componentJid
|
|
||||||
messageFrom = componentJid
|
|
||||||
} else {
|
|
||||||
logFrom = from
|
logFrom = from
|
||||||
messageFrom = from + "@" + componentJid
|
messageFrom = from
|
||||||
|
} else {
|
||||||
|
if from == "" {
|
||||||
|
logFrom = componentJid
|
||||||
|
messageFrom = componentJid
|
||||||
|
} else {
|
||||||
|
logFrom = from
|
||||||
|
messageFrom = from + "@" + componentJid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if isCarbon {
|
if isCarbon {
|
||||||
messageTo = messageFrom
|
messageTo = messageFrom
|
||||||
|
@ -95,11 +101,18 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
|
||||||
"to": to,
|
"to": to,
|
||||||
}).Warn("Got message")
|
}).Warn("Got message")
|
||||||
|
|
||||||
|
var messageType stanza.StanzaType
|
||||||
|
if isGroupchat {
|
||||||
|
messageType = stanza.MessageTypeGroupchat
|
||||||
|
} else {
|
||||||
|
messageType = stanza.MessageTypeChat
|
||||||
|
}
|
||||||
|
|
||||||
message := stanza.Message{
|
message := stanza.Message{
|
||||||
Attrs: stanza.Attrs{
|
Attrs: stanza.Attrs{
|
||||||
From: messageFrom,
|
From: messageFrom,
|
||||||
To: messageTo,
|
To: messageTo,
|
||||||
Type: "chat",
|
Type: messageType,
|
||||||
Id: id,
|
Id: id,
|
||||||
},
|
},
|
||||||
Body: body,
|
Body: body,
|
||||||
|
@ -122,13 +135,27 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
|
||||||
if !isCarbon && toJid.Resource != "" {
|
if !isCarbon && toJid.Resource != "" {
|
||||||
message.Extensions = append(message.Extensions, stanza.HintNoCopy{})
|
message.Extensions = append(message.Extensions, stanza.HintNoCopy{})
|
||||||
}
|
}
|
||||||
|
if timestamp != 0 {
|
||||||
|
var delayFrom string
|
||||||
|
if isGroupchat {
|
||||||
|
delayFrom, _, _ = SplitJID(from)
|
||||||
|
}
|
||||||
|
message.Extensions = append(message.Extensions, extensions.MessageDelay{
|
||||||
|
From: delayFrom,
|
||||||
|
Stamp: time.Unix(timestamp, 0).UTC().Format(time.RFC3339),
|
||||||
|
})
|
||||||
|
message.Extensions = append(message.Extensions, extensions.MessageDelayLegacy{
|
||||||
|
From: delayFrom,
|
||||||
|
Stamp: time.Unix(timestamp, 0).UTC().Format("20060102T15:04:05"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if isCarbon {
|
if isCarbon {
|
||||||
carbonMessage := extensions.ClientMessage{
|
carbonMessage := extensions.ClientMessage{
|
||||||
Attrs: stanza.Attrs{
|
Attrs: stanza.Attrs{
|
||||||
From: bareTo,
|
From: bareTo,
|
||||||
To: to,
|
To: to,
|
||||||
Type: "chat",
|
Type: messageType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
carbonMessage.Extensions = append(carbonMessage.Extensions, extensions.CarbonSent{
|
carbonMessage.Extensions = append(carbonMessage.Extensions, extensions.CarbonSent{
|
||||||
|
|
|
@ -440,7 +440,7 @@ func handleMUCPresence(s xmpp.Sender, p stanza.Presence) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fromBare, _, ok := gateway.SplitJID(p.From)
|
fromBare, fromResource, ok := gateway.SplitJID(p.From)
|
||||||
if !ok {
|
if !ok {
|
||||||
presenceReplySetError(reply, 400)
|
presenceReplySetError(reply, 400)
|
||||||
return
|
return
|
||||||
|
@ -458,7 +458,7 @@ func handleMUCPresence(s xmpp.Sender, p stanza.Presence) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
session.SendMUCStatuses(chatId)
|
session.JoinMUC(chatId, fromResource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue