summaryrefslogtreecommitdiff
path: root/protocols/FacebookRM
diff options
context:
space:
mode:
authorRobert Pösel <robyer@seznam.cz>2016-04-17 17:06:12 +0000
committerRobert Pösel <robyer@seznam.cz>2016-04-17 17:06:12 +0000
commit9e64b26c646913d5669723269c07e6fe8277f10c (patch)
tree0702a4bf6254e49b0cf5af82f3b2d71c56721d30 /protocols/FacebookRM
parent34dd9e912952befefa30ba0d64dbd18d84201552 (diff)
Facebook: Loading names of all users in multi chat from server (not only existing Miranda contacts)
It primary iterates over Miranda's contacts list to find existing contacts (e.g. to preserve existing custom names of these contacts). Then for missing ones it does request to server to get their names. git-svn-id: http://svn.miranda-ng.org/main/trunk@16701 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/FacebookRM')
-rw-r--r--protocols/FacebookRM/src/chat.cpp12
-rw-r--r--protocols/FacebookRM/src/contacts.cpp53
-rw-r--r--protocols/FacebookRM/src/json.cpp49
-rw-r--r--protocols/FacebookRM/src/json.h1
-rw-r--r--protocols/FacebookRM/src/process.cpp10
5 files changed, 88 insertions, 37 deletions
diff --git a/protocols/FacebookRM/src/chat.cpp b/protocols/FacebookRM/src/chat.cpp
index 4fe98713f4..bcdad74310 100644
--- a/protocols/FacebookRM/src/chat.cpp
+++ b/protocols/FacebookRM/src/chat.cpp
@@ -288,22 +288,22 @@ INT_PTR FacebookProto::OnJoinChat(WPARAM hContact, LPARAM)
return 0;
facebook_chatroom *fbc;
- std::string tthread_id = threadId;
+ std::string thread_id = threadId;
- auto it = facy.chat_rooms.find(tthread_id);
+ auto it = facy.chat_rooms.find(thread_id);
if (it != facy.chat_rooms.end()) {
fbc = it->second;
}
else {
// We don't have this chat loaded in memory yet, lets load some info (name, list of users)
- fbc = new facebook_chatroom(tthread_id);
+ fbc = new facebook_chatroom(thread_id);
LoadChatInfo(fbc);
- facy.chat_rooms.insert(std::make_pair(tthread_id, fbc));
+ facy.chat_rooms.insert(std::make_pair(thread_id, fbc));
}
// RM TODO: better use check if chatroom exists/is in db/is online... no?
- // like: if (ChatIDToHContact(tthread_id) == NULL) {
- ptrA users(GetChatUsers(tthread_id.c_str()));
+ // like: if (ChatIDToHContact(thread_id) == NULL) {
+ ptrA users(GetChatUsers(thread_id.c_str()));
if (users == NULL) {
// Add chatroom
AddChat(fbc->thread_id.c_str(), fbc->chat_name.c_str());
diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp
index 0aec3fcaa0..167933f061 100644
--- a/protocols/FacebookRM/src/contacts.cpp
+++ b/protocols/FacebookRM/src/contacts.cpp
@@ -244,7 +244,10 @@ void FacebookProto::LoadContactInfo(facebook_user* fbu)
void FacebookProto::LoadParticipantsNames(facebook_chatroom *fbc)
{
- for (std::map<std::string, std::string>::iterator it = fbc->participants.begin(); it != fbc->participants.end(); ++it) {
+ std::vector<std::string> namelessIds;
+
+ // 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;
@@ -259,15 +262,51 @@ void FacebookProto::LoadParticipantsNames(facebook_chatroom *fbc)
// TODO: set correct role (friend/user) for this contact here - need rework participants map to <id, participant>
}
- // TODO: load unknown contact's names from server
if (it->second.empty())
- it->second = it->first;
-
- //if (isOffline())
- // return;
+ namelessIds.push_back(it->first);
}
}
}
+
+ // if (isOffline())
+ // return;
+
+ if (!namelessIds.empty()) {
+ // we have some contacts without name, let's load them all from the server
+
+ std::string data = "&__user=" + facy.self_.user_id;
+ data += "&__dyn=" + facy.__dyn();
+ data += "&__req=" + facy.__req();
+ data += "&fb_dtsg=" + facy.dtsg_;
+ data += "&ttstamp=" + facy.ttstamp_;
+ data += "&__rev=" + facy.__rev();
+
+ for (std::string::size_type i = 0; i < namelessIds.size() - 1; 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;
+ }
+
+ http::response resp = facy.flap(REQUEST_USER_INFO, &data); // NOTE: Request revised 11.2.2016
+
+ if (resp.code == HTTP_CODE_OK) {
+ CODE_BLOCK_TRY
+
+ // TODO: We can cache these results and next time (e.g. for different chatroom) we can use that already cached names
+
+ facebook_json_parser* p = new facebook_json_parser(this);
+ p->parse_chat_participant_names(&resp.data, &fbc->participants);
+ delete p;
+
+ debugLogA("*** Participant names processed");
+
+ CODE_BLOCK_CATCH
+
+ debugLogA("*** Error processing participant names: %s", e.what());
+
+ CODE_BLOCK_END
+ }
+ }
}
void FacebookProto::LoadChatInfo(facebook_chatroom *fbc)
@@ -341,8 +380,6 @@ void FacebookProto::LoadChatInfo(facebook_chatroom *fbc)
fbc->chat_name = std::tstring(_A2T(fbc->thread_id.c_str())); // TODO: is this needed? Isn't it showed automatically as id if there is no name?
}
- //ReceiveMessages(messages, true); // don't let it fall into infinite cycle, solve it somehow...
-
debugLogA("*** Chat thread info processed");
CODE_BLOCK_CATCH
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index ecd69d393b..d4e4c84d87 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -158,6 +158,33 @@ 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)
+{
+ std::string jsonData = data->substr(9);
+
+ JSONNode root = JSONNode::parse(jsonData.c_str());
+ if (!root)
+ return EXIT_FAILURE;
+
+ const JSONNode &profiles = root["payload"].at("profiles");
+ if (!profiles)
+ return EXIT_FAILURE;
+
+ for (auto it = profiles.begin(); it != profiles.end(); ++it) {
+ std::string userId = (*it).name();
+ std::string userName = (*it)["name"].as_string();
+
+ if (userId.empty() || userName.empty())
+ continue;
+
+ auto participant = participants->find(userId);
+ if (participant != participants->end())
+ participant->second = userName;
+ }
+
+ return EXIT_SUCCESS;
+}
+
int facebook_json_parser::parse_friends(std::string *data, std::map< std::string, facebook_user* >* friends)
{
std::string jsonData = data->substr(9);
@@ -1195,22 +1222,6 @@ int facebook_json_parser::parse_chat_info(std::string *data, facebook_chatroom*
if (!threads)
return EXIT_FAILURE;
- /*const JSONNode &roger = payload, "roger");
- if (roger) {
- for (unsigned int i = 0; i < json_size(roger); i++) {
- const JSONNode &it = json_at(roger, i);
- std::tstring id = _A2T(json_name(it));
-
- // Ignore "wrong" (duplicit) identifiers - these that doesn't begin with "id."
- if (id.substr(0, 3) == _T("id.")) {
- facebook_chatroom *room = new facebook_chatroom();
- room->thread_id = id;
-
- chatrooms->insert(std::make_pair((char*)_T2A(room->thread_id.c_str()), room));
- }
- }
- }*/
-
for (auto it = threads.begin(); it != threads.end(); ++it) {
const JSONNode &is_canonical_user_ = (*it)["is_canonical_user"];
const JSONNode &thread_id_ = (*it)["thread_id"];
@@ -1223,14 +1234,16 @@ int facebook_json_parser::parse_chat_info(std::string *data, facebook_chatroom*
std::string tid = thread_id_.as_string();
- // TODO: allow more users to parse at once
+ // TODO: allow more chats to parse at once
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...
+
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), ""));
+ fbc->participants.insert(std::make_pair(user_id.substr(5), "")); // strip "fbid:" prefix
}
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 08aca60918..c49ef65193 100644
--- a/protocols/FacebookRM/src/json.h
+++ b/protocols/FacebookRM/src/json.h
@@ -39,6 +39,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);
facebook_json_parser(FacebookProto* proto)
{
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp
index c1986f2b7d..27383e09f1 100644
--- a/protocols/FacebookRM/src/process.cpp
+++ b/protocols/FacebookRM/src/process.cpp
@@ -866,9 +866,9 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, boo
debugLogA(" < Got chat message ID: %s", messages[i]->message_id.c_str());
facebook_chatroom *fbc;
- std::string tthread_id = messages[i]->thread_id.c_str();
+ std::string thread_id = messages[i]->thread_id.c_str();
- auto it = facy.chat_rooms.find(tthread_id);
+ auto it = facy.chat_rooms.find(thread_id);
if (it != facy.chat_rooms.end()) {
fbc = it->second;
}
@@ -880,14 +880,14 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, boo
}
// We don't have this chat loaded in memory yet, lets load some info (name, list of users)
- fbc = new facebook_chatroom(tthread_id);
+ fbc = new facebook_chatroom(thread_id);
LoadChatInfo(fbc);
- facy.chat_rooms.insert(std::make_pair(tthread_id, fbc));
+ facy.chat_rooms.insert(std::make_pair(thread_id, fbc));
}
MCONTACT hChatContact = NULL;
// RM TODO: better use check if chatroom exists/is in db/is online... no?
- // like: if (ChatIDToHContact(tthread_id) == NULL) {
+ // like: if (ChatIDToHContact(thread_id) == NULL) {
ptrA users(GetChatUsers(fbc->thread_id.c_str()));
if (users == NULL) {
AddChat(fbc->thread_id.c_str(), fbc->chat_name.c_str());