diff options
-rw-r--r-- | protocols/FacebookRM/src/chat.cpp | 43 | ||||
-rw-r--r-- | protocols/FacebookRM/src/communication.cpp | 10 | ||||
-rw-r--r-- | protocols/FacebookRM/src/constants.h | 6 | ||||
-rw-r--r-- | protocols/FacebookRM/src/contacts.cpp | 35 | ||||
-rw-r--r-- | protocols/FacebookRM/src/entities.h | 17 | ||||
-rw-r--r-- | protocols/FacebookRM/src/json.cpp | 59 | ||||
-rw-r--r-- | protocols/FacebookRM/src/json.h | 2 | ||||
-rw-r--r-- | protocols/FacebookRM/src/process.cpp | 6 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.h | 2 |
9 files changed, 129 insertions, 51 deletions
diff --git a/protocols/FacebookRM/src/chat.cpp b/protocols/FacebookRM/src/chat.cpp index 79d9874e93..49e694c332 100644 --- a/protocols/FacebookRM/src/chat.cpp +++ b/protocols/FacebookRM/src/chat.cpp @@ -163,14 +163,15 @@ int FacebookProto::OnGCEvent(WPARAM, LPARAM lParam) return 0; } -void FacebookProto::AddChatContact(const char *chat_id, const char *id, const char *name) +void FacebookProto::AddChatContact(const char *chat_id, const chatroom_participant &user) { - if (IsChatContact(chat_id, id)) + // Don't add user if it's already there + if (IsChatContact(chat_id, user.user_id.c_str())) return; ptrT tchat_id(mir_a2t(chat_id)); - ptrT tnick(mir_a2t_cp(name, CP_UTF8)); - ptrT tid(mir_a2t(id)); + ptrT tnick(mir_a2t_cp(user.nick.c_str(), CP_UTF8)); + ptrT tid(mir_a2t(user.user_id.c_str())); GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_JOIN }; GCEVENT gce = { sizeof(gce), &gcd }; @@ -179,17 +180,22 @@ void FacebookProto::AddChatContact(const char *chat_id, const char *id, const ch gce.ptszNick = tnick; gce.ptszUID = tid; gce.time = ::time(NULL); - gce.bIsMe = !mir_strcmp(id, facy.self_.user_id.c_str()); + gce.bIsMe = (user.role == ROLE_ME); - if (gce.bIsMe) { - gce.ptszStatus = TranslateT("Myself"); + if (user.is_former) { + gce.ptszStatus = TranslateT("Former"); } else { - MCONTACT hContact = ContactIDToHContact(id); - if (hContact == NULL || getByte(hContact, FACEBOOK_KEY_CONTACT_TYPE, CONTACT_NONE) != CONTACT_FRIEND) - gce.ptszStatus = TranslateT("User"); - else { + switch (user.role) { + case ROLE_ME: + gce.ptszStatus = TranslateT("Myself"); + break; + case ROLE_FRIEND: gce.ptszStatus = TranslateT("Friend"); + break; + case ROLE_NONE: + gce.ptszStatus = TranslateT("User"); + break; } } @@ -261,6 +267,8 @@ void FacebookProto::AddChat(const char *id, const TCHAR *tname) CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); gce.ptszStatus = TranslateT("User"); CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); + gce.ptszStatus = TranslateT("Former"); + CallServiceSync(MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce)); // Finish initialization gcd.iType = GC_EVENT_CONTROL; @@ -269,8 +277,15 @@ void FacebookProto::AddChat(const char *id, const TCHAR *tname) bool hideChats = getBool(FACEBOOK_KEY_HIDE_CHATS, DEFAULT_HIDE_CHATS); + /*chatroom_participant myself; + myself.user_id = facy.self_.user_id; + myself.nick = facy.self_.real_name; + myself.role = ROLE_ME; + myself.is_former = false; + myself.loaded = true; + // Add self contact - AddChatContact(id, facy.self_.user_id.c_str(), facy.self_.real_name.c_str()); + AddChatContact(id, myself);*/ CallServiceSync(MS_GC_EVENT, (hideChats ? WINDOW_HIDDEN : SESSION_INITDONE), reinterpret_cast<LPARAM>(&gce)); CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce)); } @@ -309,8 +324,8 @@ INT_PTR FacebookProto::OnJoinChat(WPARAM hContact, LPARAM) AddChat(fbc->thread_id.c_str(), fbc->chat_name.c_str()); // Add chat contacts - for (std::map<std::string, std::string>::iterator jt = fbc->participants.begin(); jt != fbc->participants.end(); ++jt) { - AddChatContact(fbc->thread_id.c_str(), jt->first.c_str(), jt->second.c_str()); + for (std::map<std::string, chatroom_participant>::iterator jt = fbc->participants.begin(); jt != fbc->participants.end(); ++jt) { + AddChatContact(fbc->thread_id.c_str(), jt->second); } // Load last messages diff --git a/protocols/FacebookRM/src/communication.cpp b/protocols/FacebookRM/src/communication.cpp index 21ff44d15d..486bc08696 100644 --- a/protocols/FacebookRM/src/communication.cpp +++ b/protocols/FacebookRM/src/communication.cpp @@ -714,18 +714,12 @@ void facebook_client::insert_reader(MCONTACT hContact, time_t timestamp, const s auto itRoom = chat_rooms.find(tid); if (itRoom != chat_rooms.end()) { facebook_chatroom *chatroom = itRoom->second; - std::map<std::string, std::string> participants = chatroom->participants; + std::map<std::string, chatroom_participant> participants = chatroom->participants; // try to get name of this participant auto participant = participants.find(readerId); if (participant != participants.end()) { - name = participant->second; - } - else { - // FIXME: This probably shouldn't be here, but chatroom should have all it's participants loaded itself already - // add this missing participant, just in case - participants.insert(std::make_pair(readerId, name)); - parent->AddChatContact(tid.c_str(), readerId.c_str(), name.c_str()); + name = participant->second.nick; } } diff --git a/protocols/FacebookRM/src/constants.h b/protocols/FacebookRM/src/constants.h index 389f4eec65..c3dfbc9cc3 100644 --- a/protocols/FacebookRM/src/constants.h +++ b/protocols/FacebookRM/src/constants.h @@ -189,6 +189,12 @@ enum MessageType { CALL = 2, // Video call
};
+enum ParticipantRole {
+ ROLE_ME = 0,
+ ROLE_FRIEND = 1,
+ ROLE_NONE = 2
+};
+
typedef struct {
const char *name;
const char *id;
diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp index 95e4307ad0..00da4ecd81 100644 --- a/protocols/FacebookRM/src/contacts.cpp +++ b/protocols/FacebookRM/src/contacts.cpp @@ -259,22 +259,35 @@ void FacebookProto::LoadParticipantsNames(facebook_chatroom *fbc) // TODO: We could load all names from server at once by skipping this for cycle and using namelessIds as all in participants list, but we would lost our local names of our contacts. But maybe that's not a problem? for (auto it = fbc->participants.begin(); it != fbc->participants.end(); ++it) { - if (it->second.empty()) { - if (!mir_strcmp(it->first.c_str(), facy.self_.user_id.c_str())) - it->second = facy.self_.real_name; + const char *id = it->first.c_str(); + chatroom_participant &user = it->second; + + if (!user.loaded) { + if (!mir_strcmp(id, facy.self_.user_id.c_str())) { + user.nick = facy.self_.real_name; + user.role = ROLE_ME; + user.loaded = true; + } else { - MCONTACT hContact = ContactIDToHContact(it->first.c_str()); + MCONTACT hContact = ContactIDToHContact(id); if (hContact != NULL) { DBVARIANT dbv; if (!getStringUtf(hContact, FACEBOOK_KEY_NICK, &dbv)) { - it->second = dbv.pszVal; + user.nick = dbv.pszVal; db_free(&dbv); } - // TODO: set correct role (friend/user) for this contact here - need rework participants map to <id, participant> + if (user.role == ROLE_NONE) { + int type = getByte(hContact, FACEBOOK_KEY_CONTACT_TYPE); + if (type == CONTACT_FRIEND) + user.role = ROLE_FRIEND; + else + user.role = ROLE_NONE; + } + user.loaded = true; } - if (it->second.empty()) - namelessIds.push_back(it->first); + if (!user.loaded) + namelessIds.push_back(id); } } } @@ -292,7 +305,7 @@ void FacebookProto::LoadParticipantsNames(facebook_chatroom *fbc) data += "&ttstamp=" + facy.ttstamp_; data += "&__rev=" + facy.__rev(); - for (std::string::size_type i = 0; i < namelessIds.size() - 1; i++) { + for (std::string::size_type i = 0; i < namelessIds.size(); i++) { std::string pos = utils::conversion::to_string(&i, UTILS_CONV_UNSIGNED_NUMBER); std::string id = utils::url::encode(namelessIds.at(i)); data += "&ids[" + pos + "]=" + id; @@ -363,8 +376,8 @@ void FacebookProto::LoadChatInfo(facebook_chatroom *fbc) if (fbc->chat_name.empty()) { unsigned int namesUsed = 0; - for (std::map<std::string, std::string>::iterator it = fbc->participants.begin(); it != fbc->participants.end(); ++it) { - std::string participant = it->second; + for (auto it = fbc->participants.begin(); it != fbc->participants.end(); ++it) { + std::string participant = it->second.nick; // Ignore empty and numeric only participant names if (participant.empty() || participant.find_first_not_of("0123456789") == std::string::npos) diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h index e289a176eb..a70757e1c3 100644 --- a/protocols/FacebookRM/src/entities.h +++ b/protocols/FacebookRM/src/entities.h @@ -73,11 +73,26 @@ struct facebook_user } }; +struct chatroom_participant +{ + std::string user_id; + std::string nick; + ParticipantRole role; + bool is_former; + bool loaded; + + chatroom_participant() : loaded(false), is_former(false), role(ROLE_NONE) {} +}; + struct facebook_chatroom { std::string thread_id; std::tstring chat_name; - std::map<std::string, std::string> participants; + std::map<std::string, chatroom_participant> participants; + bool can_reply; + bool is_archived; + bool is_subscribed; + bool read_only; facebook_chatroom(std::string thread_id) : thread_id(thread_id) {} }; diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index 4cfa53c3fe..9be06826d7 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -72,7 +72,7 @@ void parseUser(const JSONNode &it, facebook_user *fbu) } } -int facebook_json_parser::parse_chat_participant_names(std::string *data, std::map<std::string, std::string>* participants) +int facebook_json_parser::parse_chat_participant_names(std::string *data, std::map<std::string, chatroom_participant>* participants) { std::string jsonData = data->substr(9); @@ -87,13 +87,28 @@ int facebook_json_parser::parse_chat_participant_names(std::string *data, std::m for (auto it = profiles.begin(); it != profiles.end(); ++it) { std::string userId = (*it).name(); std::string userName = (*it)["name"].as_string(); + std::string type = (*it)["type"].as_string(); if (userId.empty() || userName.empty()) continue; auto participant = participants->find(userId); - if (participant != participants->end()) - participant->second = userName; + if (participant != participants->end()) { + chatroom_participant &user = participant->second; + user.nick = userName; + + if (type == "friend") + user.role = ROLE_FRIEND; + else if (type == "user") + user.role = ROLE_NONE; + else if (type == "page") { + user.role = ROLE_NONE; + // Use prefix for "page" users + user.nick = proto->m_pagePrefix + " " + userName; + } + + user.loaded = true; + } } return EXIT_SUCCESS; @@ -644,19 +659,19 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo auto itRoom = proto->facy.chat_rooms.find(thread_.as_string()); if (itRoom != proto->facy.chat_rooms.end()) { facebook_chatroom *chatroom = itRoom->second; - std::map<std::string, std::string> participants = chatroom->participants; + std::map<std::string, chatroom_participant> participants = chatroom->participants; auto participant = participants.find(from_id); if (participant == participants.end()) { // TODO: load name of this participant - std::string name = from_id; - proto->AddChatContact(tid.c_str(), from_id.c_str(), name.c_str()); + participant->second.user_id = from_id; + proto->AddChatContact(tid.c_str(), participant->second); } participant = participants.find(from_id); if (participant != participants.end()) { MCONTACT hChatContact = proto->ChatIDToHContact(tid); - ptrT name(mir_utf8decodeT(participant->second.c_str())); + ptrT name(mir_utf8decodeT(participant->second.nick.c_str())); if (st_.as_int() == 1) { StatusTextData st = { 0 }; @@ -1062,8 +1077,12 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector< const JSONNode &participants = (*it)["participants"]; for (auto jt = participants.begin(); jt != participants.end(); ++jt) { - std::string user_id = (*jt).name(); - iter->second->participants.insert(std::make_pair(user_id, user_id)); // TODO: get name somehow + chatroom_participant user; + user.user_id = (*jt).name(); + // user.nick = (*jt).name(); // TODO: get name somehow + /// user. ... + + iter->second->participants.insert(std::make_pair(user.user_id, user)); } } } @@ -1232,14 +1251,30 @@ int facebook_json_parser::parse_chat_info(std::string *data, facebook_chatroom* if (fbc->thread_id != tid) continue; - // const JSONNode &former_participants = (*it)["former_participants"]; // TODO: Do we want to list also former participants? We can show them with different role or something like that... + chatroom_participant user; + user.is_former = true; + const JSONNode &former_participants = (*it)["former_participants"]; + for (auto jt = former_participants.begin(); jt != former_participants.end(); ++jt) { + user.role = (*jt)["is_friend"].as_bool() ? ROLE_FRIEND : ROLE_NONE; + user.user_id = (*jt)["id"].as_string().substr(5); // strip "fbid:" prefix + fbc->participants.insert(std::make_pair(user.user_id, user)); + } + + user.is_former = false; + user.role = ROLE_NONE; const JSONNode &participants = (*it)["participants"]; for (auto jt = participants.begin(); jt != participants.end(); ++jt) { - std::string user_id = (*jt).as_string(); - fbc->participants.insert(std::make_pair(user_id.substr(5), "")); // strip "fbid:" prefix + user.user_id = (*jt).as_string().substr(5); // strip "fbid:" prefix + fbc->participants.insert(std::make_pair(user.user_id, user)); } + // TODO: don't automatically join unsubscribed or archived chatrooms + + fbc->can_reply = (*it)["can_reply"].as_bool(); + fbc->is_archived = (*it)["is_archived"].as_bool(); + fbc->is_subscribed = (*it)["is_subscribed"].as_bool(); + fbc->read_only = (*it)["read_only"].as_bool(); fbc->chat_name = std::tstring(ptrT(mir_utf8decodeT(name_.as_string().c_str()))); } diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h index b392fb247e..666968385c 100644 --- a/protocols/FacebookRM/src/json.h +++ b/protocols/FacebookRM/src/json.h @@ -38,7 +38,7 @@ public: int parse_thread_info(std::string* data, std::string* user_id);
int parse_user_info(std::string* data, facebook_user* fbu);
int parse_chat_info(std::string* data, facebook_chatroom* fbc);
- int parse_chat_participant_names(std::string *data, std::map<std::string, std::string>* participants);
+ int parse_chat_participant_names(std::string *data, std::map<std::string, chatroom_participant>* participants);
facebook_json_parser(FacebookProto* proto)
{
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index 80cd20e3d7..5428a4f5ec 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -795,8 +795,8 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message> &messages, boo // Set thread id (TID) for later setString(hChatContact, FACEBOOK_KEY_TID, fbc->thread_id.c_str()); - for (std::map<std::string, std::string>::iterator jt = fbc->participants.begin(); jt != fbc->participants.end(); ++jt) { - AddChatContact(fbc->thread_id.c_str(), jt->first.c_str(), jt->second.c_str()); + for (auto jt = fbc->participants.begin(); jt != fbc->participants.end(); ++jt) { + AddChatContact(fbc->thread_id.c_str(), jt->second); } } @@ -823,7 +823,7 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message> &messages, boo auto jt = fbc->participants.find(msg.user_id); if (jt != fbc->participants.end()) { - name = jt->second; + name = jt->second.nick; } // TODO: support also system messages (rename chat, user quit, etc.)! (here? or it is somewhere else? diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h index c9d931ed3d..4e9603e731 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -212,7 +212,7 @@ public: void UpdateChat(const char *chat_id, const char *id, const char *name, const char *message, DWORD timestamp = 0, bool is_old = false); void RenameChat(const char *chat_id, const char *name); bool IsChatContact(const char *chat_id, const char *id); - void AddChatContact(const char *chat_id, const char *id, const char *name); + void AddChatContact(const char *chat_id, const chatroom_participant &user); void RemoveChatContact(const char *chat_id, const char *id, const char *name); char *GetChatUsers(const char *chat_id); void ReceiveMessages(std::vector<facebook_message> &messages, bool check_duplicates = false); |