From 5e0782b5536d0bb7d5e63a085eed00e32538887a Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Wed, 18 Aug 2021 14:18:24 -0500 Subject: [PATCH] Ensure implicit room-members are real MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a message/event is sent to a room that's tied to a user that hasn't been formally declared (through IM_ROOM_PARTICIPANTS or IM_ROOM_PARTICIPANT_JOINED), that user won't be unconditionally kept anymore. Now, after adding an implicit user, the participant list will be requested again― upon receiving the list, all implicitly-defined users will be removed. If they really existed to begin with, they should be re-added quickly through this re-sending of IM_ROOM_PARTICIPANTS. Ghosts should be treated as ghosts, not users. --- application/Conversation.cpp | 58 ++++++++++++++++++++++++++++-------- application/Conversation.h | 6 ++-- application/Server.cpp | 23 +------------- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/application/Conversation.cpp b/application/Conversation.cpp index d7864a9..44dcef0 100644 --- a/application/Conversation.cpp +++ b/application/Conversation.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "AppPreferences.h" #include "Cardie.h" @@ -199,6 +198,28 @@ Conversation::ImMessage(BMessage* msg) _CacheRoomFlags(); break; } + case IM_ROOM_PARTICIPANTS: + { + // Get rid of implicity-defined users rq + for (int i = 0; i < fGuests.CountStrings(); i++) { + RemoveUser(UserById(fGuests.StringAt(i))); + fGuests.Remove(i); + } + + BStringList ids; + BStringList names; + msg->FindStrings("user_name", &names); + if (msg->FindStrings("user_id", &ids) != B_OK) + break; + + for (int i = 0; i < ids.CountStrings(); i++) { + BMessage user; + user.AddString("user_name", names.StringAt(i)); + user.AddString("user_id", ids.StringAt(i)); + _EnsureUser(&user, false); + } + break; + } case IM_ROOM_PARTICIPANT_JOINED: { BString user_id; @@ -206,7 +227,7 @@ Conversation::ImMessage(BMessage* msg) break; if (UserById(user_id) == NULL) { - _EnsureUser(msg); + _EnsureUser(msg, false); GetView()->MessageReceived(msg); } break; @@ -437,10 +458,12 @@ Conversation::UserById(BString id) void Conversation::AddUser(User* user) { + if (user == NULL) + return; BMessage msg; msg.AddString("user_id", user->GetId()); msg.AddString("user_name", user->GetName()); - _EnsureUser(&msg); + _EnsureUser(&msg, false); _SortConversationList(); } @@ -448,6 +471,8 @@ Conversation::AddUser(User* user) void Conversation::RemoveUser(User* user) { + if (user == NULL) + return; fUsers.RemoveItemFor(user->GetId()); user->UnregisterObserver(this); GetView()->UpdateUserList(fUsers); @@ -473,7 +498,8 @@ Conversation::SetRole(BString id, Role* role) fRoles.RemoveItemFor(id); delete oldRole; } - fRoles.AddItem(id, role); + if (role != NULL) + fRoles.AddItem(id, role); } @@ -579,7 +605,7 @@ Conversation::_EnsureCachePath() User* -Conversation::_EnsureUser(BMessage* msg) +Conversation::_EnsureUser(BMessage* msg, bool implicit) { BString id = msg->FindString("user_id"); BString name = msg->FindString("user_name"); @@ -589,19 +615,27 @@ Conversation::_EnsureUser(BMessage* msg) User* serverUser = fLooper->UserById(id); // Not here, but found in server - if (user == NULL && serverUser != NULL) { - fUsers.AddItem(id, serverUser); + if (user == NULL && serverUser != NULL) user = serverUser; - GetView()->UpdateUserList(fUsers); - _UpdateIcon(user); - NotifyInteger(INT_ROOM_MEMBERS, fUsers.CountItems()); - } // Not anywhere; create user else if (user == NULL) { user = new User(id, _GetServer()->Looper()); user->SetProtocolLooper(fLooper); - fLooper->AddUser(user); + } + + // It's been implicitly defined (rather than explicit join), shame! + if (UserById(id) == NULL && implicit == true) { + fGuests.Add(id); + // The response to this will be used to determine if this guest stays + BMessage msg(IM_MESSAGE); + msg.AddInt32("im_what", IM_GET_ROOM_PARTICIPANTS); + msg.AddString("chat_id", fID); + fLooper->MessageReceived(&msg); + } + + if (UserById(id) == NULL) { + fUsers.AddItem(id, user); fUsers.AddItem(id, user); GetView()->UpdateUserList(fUsers); _UpdateIcon(user); diff --git a/application/Conversation.h b/application/Conversation.h index a0676d1..2fd52a4 100644 --- a/application/Conversation.h +++ b/application/Conversation.h @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -83,7 +84,7 @@ private: void _LoadRoomFlags(); void _EnsureCachePath(); - User* _EnsureUser(BMessage* msg); + User* _EnsureUser(BMessage* msg, bool implicit = true); Role* _GetRole(BMessage* msg); void _UpdateIcon(User* user = NULL); @@ -113,7 +114,8 @@ private: int32 fRoomFlags; int32 fDisallowedFlags; - UserMap fUsers; + UserMap fUsers; // For defined, certain members of the room + BStringList fGuests; // IDs of implicitly-defined users RoleMap fRoles; }; diff --git a/application/Server.cpp b/application/Server.cpp index 59120bd..82e1da0 100644 --- a/application/Server.cpp +++ b/application/Server.cpp @@ -458,7 +458,6 @@ Server::ImMessage(BMessage* msg) chat->AddUser(user); chat->ShowView(false, true); } - break; } case IM_JOIN_ROOM: @@ -466,27 +465,6 @@ Server::ImMessage(BMessage* msg) SendProtocolMessage(msg); break; } - case IM_ROOM_PARTICIPANTS: - { - Conversation* chat = _EnsureConversation(msg); - BStringList ids; - BStringList name; - - msg->FindStrings("user_name", &name); - if (msg->FindStrings("user_id", &ids) != B_OK) - break; - - ProtocolLooper* protoLooper = _LooperFromMessage(msg); - - for (int i = 0; i < ids.CountStrings(); i++) { - User* user = _EnsureUser(ids.StringAt(i), protoLooper); - - if (name.CountStrings() >= i && !name.StringAt(i).IsEmpty()) - user->SetNotifyName(name.StringAt(i)); - chat->AddUser(user); - } - break; - } case IM_MESSAGE_RECEIVED: if (msg->HasString("chat_id") == false) { ProtocolLooper* looper = _LooperFromMessage(msg); @@ -499,6 +477,7 @@ Server::ImMessage(BMessage* msg) case IM_ROOM_CREATED: case IM_ROOM_METADATA: case IM_ROOM_ROLECHANGED: + case IM_ROOM_PARTICIPANTS: case IM_ROOM_PARTICIPANT_JOINED: case IM_ROOM_PARTICIPANT_LEFT: case IM_ROOM_PARTICIPANT_BANNED: