private void OnMessageProcessed(Message msg, bool isSent)
        {
            msg.IsSent = isSent;
            _processedMessagesQueue.Enqueue(msg);
            if (isSent)
            {
                //TODO: remove this line later
                _deliveryStatusEventManager.DeliverEventToDevice(new DeliveryNotification {
                    MessageToken = msg.MessageToken, ReceiverDeviceId = msg.SenderDeviceId
                });

                foreach (var senderDeviceId in _devicesRepository.GetDevices(msg.SenderId))
                {
                    if (senderDeviceId != msg.SenderDeviceId)
                    {
                        _deliveryStatusEventManager.DeliverEventToDevice(new DeliveryNotification {
                            MessageToken = msg.MessageToken, ReceiverDeviceId = senderDeviceId
                        });
                    }
                }
            }
        }
 public MarkMessageAsSeenResponse MarkMessageAsSeen(ISession session, MarkMessageAsSeenRequest request)
 {
     foreach (var messageId in request.MessagesSeen)
     {
         Logger.Debug("MarkMessageAsSeen msgToken={0}  from={1}  to={2}", messageId.ToString().Cut(), session.DeviceId.Cut(), request.MessagesAuthor);
         foreach (var deviceId in _devicesRepository.GetDevices(request.MessagesAuthor))
         {
             _seenStatusEventManager.DeliverEventToDevice(new SeenNotification {
                 MessageToken = messageId, ReceiverDeviceId = deviceId
             });
         }
     }
     return(request.CreateResponse <MarkMessageAsSeenResponse>());
 }
        public CreateGroupChatResponse CreateGroupChat(ISession session, CreateGroupChatRequest request)
        {
            var response = request.CreateResponse <CreateGroupChatResponse>();

            GroupChat group = new GroupChat {
                GroupId = Guid.NewGuid(), CreatedAt = DateTime.UtcNow, OwnerId = session.UserId
            };

            group.Participants = new List <GroupChatParticipant> {
                new GroupChatParticipant {
                    UserId = session.UserId
                }
            };
            group.Participants.AddRange(request.Participants.Select(i => new GroupChatParticipant {
                UserId = i
            }));

            foreach (var participant in group.Participants)
            {
                _groupChatsRepository.AddGroupToUser(participant.UserId, group.GroupId);
                participant.Devices = _devicesRepository.GetDevices(participant.UserId);
            }

            foreach (var device in group.Participants.SelectMany(p => p.Devices))
            {
                if (device != session.DeviceId)
                {
                    _groupChangedEventManager.DeliverEventToDevice(new GroupChangedEvent
                    {
                        ReceiverDeviceId = device,
                        ChangesAuthorId  = session.UserId,
                        GroupId          = group.GroupId,
                        Participants     = group.Participants,
                        Type             = GroupChangedEvent.ChangesType.ParticipantsAdded
                    });
                }
            }

            _groupChatsRepository.UpdateOrCreateGroup(group);

            response.GroupId = group.GroupId;
            return(response);
        }
        public SendMessageResponse SendMessage(ISession session, SendMessageRequest request)
        {
            var response = request.CreateResponse <SendMessageResponse>();

            Logger.Info("SendMessage from Id={0} (Device={1}) to Id={2} ({3} devices)",
                        session.UserId, session.DeviceId.Cut(), request.ReceiverUserId, request.Keys != null ? request.Keys.Count : -1);

            Dictionary <string, long>   actualMessageReceiversDevices = null;
            Dictionary <string, byte[]> keys = request.Keys;

            if (request.GroupId != Guid.Empty)// group conversation
            {
                var groupChat = _groupChatsRepository.GetChat(request.GroupId);

                //sender is in the group?
                if (groupChat.Participants.All(i => i.UserId != session.UserId))
                {
                    response.Success = false;
                    response.Error   = Errors.YouAreNotParticipantOfThatGroup;
                    return(response);
                }

                if (keys == null) //means not encrypted
                {
                    keys = groupChat.Participants
                           .SelectMany(p => p.Devices)
                           .Where(p => p != session.DeviceId)
                           .Distinct()
                           .ToDictionary <string, string, byte[]>(k => k, v => null); //null value means unencrypted
                }
                else
                {
                    //it means we will check all provided devices below (see if (actualMessageReceiversDevices != null)) -- just to avoid copy-paste

                    actualMessageReceiversDevices = new Dictionary <string, long>();
                    foreach (var groupChatParticipant in groupChat.Participants)
                    {
                        foreach (var device in groupChatParticipant.Devices)
                        {
                            actualMessageReceiversDevices[device] = groupChatParticipant.UserId;
                        }
                    }
                }
            }
            else // private conversation
            {
                if (request.ReceiverUserId == session.UserId)
                {
                    response.Success = false;
                    response.Error   = Errors.SendMessage_ReceiverAndSenderAreSame;
                    return(response);
                }

                if (keys == null)//means not encrypted
                {
                    keys = _devicesRepository.GetDevices(request.ReceiverUserId).ToDictionary <string, string, byte[]>(k => k, v => null);
                }
                else
                {
                    //it means we will check all provided devices below (see if (actualMessageReceiversDevices != null)) -- just to avoid copy-paste
                    actualMessageReceiversDevices = _devicesRepository.GetDevices(request.ReceiverUserId).ToDictionary(k => k, v => request.ReceiverUserId);
                }
            }

            if (actualMessageReceiversDevices != null) //TODO: uncoment later
            {
                var providedDevices = keys.Select(i => i.Key);

                List <string> union;
                List <string> notProvidedDevices; //conversation has more devices than user provided as targets
                List <string> wrongDevices;       //some of the devices user provided are not members of that conversation
                actualMessageReceiversDevices.Select(i => i.Key)
                .FindIntersectionAndDifference(providedDevices, out union, out notProvidedDevices, out wrongDevices);

                if (notProvidedDevices.Any())
                {
                    response.Success = false;
                    response.Error   = Errors.SendMessage_ProvideKeysForTheseDevices;
                    //we will help the user - provide public keys as well
                    response.MissedDevicesWithPublicKeysToReEncrypt = notProvidedDevices
                                                                      .Where(d => session.DeviceId != d)
                                                                      .Select(d => new PublicKeyInfo
                    {
                        DeviceId  = d,
                        PublicKey = _devicesRepository.GetPublicKeyForDevice(d),
                        UserId    = actualMessageReceiversDevices[d]
                    })
                                                                      .ToList();
                    return(response);
                }

                //cut receivers not in the conversation
                //TODO: uncomment it later

                /*foreach (var key in wrongDevices)
                 * {
                 *  keys.Remove(key);
                 * }*/
            }

            keys.Remove(session.DeviceId);

            if (keys.Count < 1)
            {
                response.Success = false;
                response.Error   = Errors.SendMessage_ReceiversNotFound;
                return(response);
            }

            foreach (var key in keys)
            {
                var innerMsg = new Message
                {
                    SenderAccessToken = session.AccessToken,
                    Text             = request.Message,
                    GroupId          = request.GroupId,
                    SenderId         = session.UserId,
                    SenderDeviceId   = session.DeviceId,
                    SenderName       = request.SenderName,
                    ReceiverId       = request.ReceiverUserId,
                    MessageTypeId    = (int)request.MessageType,
                    Thumbnail        = request.Thumbnail,
                    ReceiverDeviceId = key.Key,
                    EncryptionKey    = key.Value,
                    MessageToken     = request.MessageToken,
                };
                _messageEventManager.DeliverEventToDevice(innerMsg);
            }
            return(response);
        }