diff --git a/docs/API.md b/docs/API.md index df93bff0..e54aa054 100644 --- a/docs/API.md +++ b/docs/API.md @@ -881,10 +881,8 @@ The following values are currently defined for the `head` field: * `attachments`: an array of paths indicating media attached to this message `["/v0/file/s/sJOD_tZDPz0.jpg"]`. * `auto`: `true` when the message was sent automatically, i.e. by a chatbot or an auto-responder. * `forwarded`: an indicator that the message is a forwarded message, a unique ID of the original message, `"grp1XUtEhjv6HND:123"`. - * `hashtags`: an array of hashtags in the message without the leading `#` symbol: `["onehash", "twohash"]`. * `mentions`: an array of user IDs mentioned (`@alice`) in the message: `["usr1XUtEhjv6HND", "usr2il9suCbuko"]`. * `mime`: MIME-type of the message content, `"text/x-drafty"`; a `null` or a missing value is interpreted as `"text/plain"`. - * `priority`: message display priority: hint for the client that the message should be displayed more prominently for a set period of time; only `"high"` is currently defined; `{"level": "high", "expires": "2019-10-06T18:07:30.038Z"}`; `priority` can be set by the topic owner or administrator (`A` permission) only. The `"expires"` qualifier is optional. * `replace`: an indicator that the message is a correction/replacement for another message, a topic-unique ID of the message being updated/replaced, `":123"` * `reply`: an indicator that the message is a reply to another message, a unique ID of the original message, `"grp1XUtEhjv6HND:123"`. * `sender`: a user ID of the sender added by the server when the message is sent on behalf of another user, `"usr1XUtEhjv6HND"`. diff --git a/server/calls.go b/server/calls.go index 5c7010fc..63876ec6 100644 --- a/server/calls.go +++ b/server/calls.go @@ -171,13 +171,20 @@ func initVideoCalls(jsconfig json.RawMessage) error { return nil } -func (call *videoCall) messageHead(newState string, duration int) map[string]interface{} { - head := map[string]interface{}{ - "replace": ":" + strconv.Itoa(call.seq), - "webrtc": newState, +// Add webRTC-related headers to message Head. The original Head may already contain some entries, +// like 'sender', preserve them. +func (call *videoCall) messageHead(head map[string]interface{}, newState string, duration int) map[string]interface{} { + if head == nil { + head = map[string]interface{}{} } + + head["replace"] = ":" + strconv.Itoa(call.seq) + head["webrtc"] = newState + if duration > 0 { head["webrtc-duration"] = duration + } else { + delete(head, "webrtc-duration") } if call.contentMime != nil { head["mime"] = call.contentMime @@ -281,10 +288,10 @@ func (t *Topic) handleCallEvent(msg *ClientComMessage) { if call.Event == constCallEventAccept { // The call has been accepted. // Send a replacement {data} message to the topic. - replaceWith := constCallMsgAccepted - head := t.currentCall.messageHead(replaceWith, 0) msgCopy := *msg msgCopy.AsUser = originatorUid.UserId() + replaceWith := constCallMsgAccepted + head := t.currentCall.messageHead(msgCopy.Pub.Head, replaceWith, 0) if err := t.saveAndBroadcastMessage(&msgCopy, originatorUid, false, nil, head, t.currentCall.content); err != nil { return @@ -397,9 +404,9 @@ func (t *Topic) maybeEndCallInProgress(from string, msg *ClientComMessage, callD } // Send a message indicating the call has ended. - head := t.currentCall.messageHead(replaceWith, int(callDuration)) msgCopy := *msg msgCopy.AsUser = originatorUid.UserId() + head := t.currentCall.messageHead(msgCopy.Pub.Head, replaceWith, int(callDuration)) if err := t.saveAndBroadcastMessage(&msgCopy, originatorUid, false, nil, head, t.currentCall.content); err != nil { logs.Err.Printf("topic[%s]: failed to write finalizing message for call seq id %d - '%s'", t.name, t.currentCall.seq, err) } diff --git a/server/topic.go b/server/topic.go index b2741f4d..9ca33688 100644 --- a/server/topic.go +++ b/server/topic.go @@ -964,6 +964,17 @@ func (t *Topic) saveAndBroadcastMessage(msg *ClientComMessage, asUid types.Uid, } } + if msg.sess != nil && msg.sess.uid != asUid { + // The "sender" header contains ID of the user who sent the message on behalf of asUid. + if head == nil { + head = map[string]interface{}{} + } + head["sender"] = msg.sess.uid.UserId() + } else if head != nil { + // Make sure the received Head does not include a fake "sender" header. + delete(head, "sender") + } + markedReadBySender := false if err, unreadUpdated := store.Messages.Save( &types.Message{