コード例 #1
0
        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;
        }