public virtual Tuple <List <UserId>, List <ITextChatMessage> > JoinRoom(UserId userId, RoomId roomId) { var user = ChatModel.GetUser(userId); // If the room is private and the user has nothing to do here, EXPLODE! if (roomId.IsPrivate() && !UserIdsInPrivateRoom(roomId).Contains(userId)) { throw new LogReadyException(LogTag.PrivateRoomIntrusionAttempt, new { userId, roomId }); } if (!ChatModel.IsInRoom(roomId, user.Id)) { ChatModel.AddUserToRoom(userId, roomId); OnUserJoinedRoom?.Invoke(roomId, user.Id); if (roomId.IsPublic()) { OnCountOfUsersUpdated?.Invoke(roomId, ChatModel.UsersCountOf(roomId)); } } var withVisibilities = new List <MessageVisibility> { MessageVisibility.Everyone, MessageVisibility.Sender, MessageVisibility.Ephemeral, MessageVisibility.News }; var customMessageHistory = ChatModel.LatestMessagesIn(roomId, HistoryLength * 2, withVisibilities) .Where(a => (a.Visibility != MessageVisibility.Sender && a.Visibility != MessageVisibility.Ephemeral) || a.UserId == userId) .Reverse().Take(HistoryLength).Reverse() .ToList(); // If in a private room and the partner doesn't want private chat, Signal it with a service message if (roomId.IsGroup()) { goto Skip; } var partnerId = PartnerInPrivateRoom(roomId, userId); if (!ChatModel.IsInChat(partnerId)) { goto Skip; } var partner = ChatModel.GetUser(partnerId); if (partner.IsNoPrivateChat) { customMessageHistory.Add(new TextChatMessage { RoomId = roomId, Text = JsonConvert.SerializeObject(new { noPrivateChat = ChatModel.GetPublicRoomsFor(partner.Id) }, Formatting.None, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }), Visibility = MessageVisibility.System }); } Skip: return(new Tuple <List <UserId>, List <ITextChatMessage> >( ChatModel.UsersInRoom(roomId, user.Id), customMessageHistory )); }
public static async Task <Result <bool> > JoinRoom(User user, RoomId roomId) { var result = Result <bool> .True; if (!roomId.IsPrivate()) { return(result); } int userIdEf = user.Id; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. int partnerId = ChatModel.PartnerIdFrom(roomId, user.Id); using (var db = new HellolingoEntities()) { var userTracker = db.TextChatTrackers.Find(userIdEf, roomIdEf); var partnerTracker = db.TextChatTrackers.Find(partnerId, roomIdEf); // Handle people directly joining by the url from outside the chat if (userTracker == null || partnerTracker == null) { await RequestPrivateChat(user, roomId, partnerId); result.Reports.AddReport(LogTag.ChatRequestAddedFromJoinRoom, new { userId = user.Id, roomId }); return(result); } // Set new statuses according to current status if ((userTracker.Status == TrackerStatus.Invited || userTracker.Status == TrackerStatus.IgnoredInvite) && partnerTracker.Status == TrackerStatus.Inviting) { userTracker.Status = TrackerStatus.AcceptedInvite; partnerTracker.Status = TrackerStatus.InviteAccepted; userTracker.StatusAt = partnerTracker.StatusAt = DateTime.Now; result.Reports = new LogReports(LogTag.ChatRequestAccepted); } else if (userTracker.Status == TrackerStatus.InviteAccepted) { userTracker.Status = TrackerStatus.SeenInviteResponse; userTracker.StatusAt = DateTime.Now; } await db.SaveChangesAsync(); } return(result); }