From a915fe3a7ff1f0512d91c1d4e2fe603b08458e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Fri, 13 Dec 2013 09:27:00 +0000 Subject: Facebook: Fixed loading sent messages (from other connected devices) git-svn-id: http://svn.miranda-ng.org/main/trunk@7170 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/FacebookRM/src/contacts.cpp | 44 +++++++++++++++++++++ protocols/FacebookRM/src/json.cpp | 61 ++++++++++++++++++++++++----- protocols/FacebookRM/src/json.h | 1 + protocols/FacebookRM/src/process.cpp | 73 +++++++++++++++++++---------------- protocols/FacebookRM/src/proto.h | 1 + 5 files changed, 137 insertions(+), 43 deletions(-) (limited to 'protocols') diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp index c7487cd71d..f225c5b8c7 100644 --- a/protocols/FacebookRM/src/contacts.cpp +++ b/protocols/FacebookRM/src/contacts.cpp @@ -94,6 +94,50 @@ HANDLE FacebookProto::ContactIDToHContact(std::string user_id) return 0; } +std::string FacebookProto::ThreadIDToContactID(std::string thread_id) +{ + std::string user_id; + + for (HANDLE hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { + if (!IsMyContact(hContact)) + continue; + + ptrA tid(getStringA(hContact, FACEBOOK_KEY_TID)); + if (tid && !strcmp(tid, thread_id.c_str())) { + user_id = ptrA( getStringA(hContact, FACEBOOK_KEY_ID)); + return user_id; + } + } + + // We don't have any contact with thish thread_id cached, we must ask server + + std::string data = "client=mercury"; + data += "&__user=" + facy.self_.user_id; + data += "&fb_dtsg=" + (facy.dtsg_.length() ? facy.dtsg_ : "0"); + data += "&__a=1&__dyn=&__req=&ttstamp=0"; + data += "&threads[thread_ids][0]=" + utils::url::encode(thread_id); + + http::response resp = facy.flap(REQUEST_THREAD_INFO, &data); + + if (resp.code == HTTP_CODE_OK) { + CODE_BLOCK_TRY + + facebook_json_parser* p = new facebook_json_parser(this); + p->parse_thread_info(&resp.data, &user_id); + delete p; + + debugLogA("***** Thread info processed"); + + CODE_BLOCK_CATCH + + debugLogA("***** Error processing thread info: %s", e.what()); + + CODE_BLOCK_END + } + + return user_id; +} + HANDLE FacebookProto::AddToContactList(facebook_user* fbu, ContactType type, bool dont_check) { HANDLE hContact; diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index cbb18c66e1..9abb95c088 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -372,7 +372,7 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa std::string t = json_as_pstring(type); if (t == "messaging") { - // we use this only for incomming messages (and getting seen info) + // various messaging stuff (received and sent messages, getting seen info) JSONNODE *type = json_get(it, "event"); if (type == NULL) @@ -470,10 +470,6 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa // Process attachements and stickers parseAttachments(proto, &message_text, msg); - // Ignore messages from myself, as there is no id of recipient - if (id == proto->facy.self_.user_id) - continue; - // Ignore duplicits or messages sent from miranda if (body == NULL || ignore_duplicits(proto, message_id, message_text)) continue; @@ -524,9 +520,9 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa // RM TODO: better use check if chatroom exists/is in db/is online... no? /// e.g. HANDLE hChatContact = proto->ChatIDToHContact(thread_id); ? if (proto->GetChatUsers(thread_id.c_str()) == NULL) { - // Set thread id (TID) for later. proto->AddChat(thread_id.c_str(), name.c_str()); hChatContact = proto->ChatIDToHContact(thread_id); + // Set thread id (TID) for later proto->setTString(hChatContact, FACEBOOK_KEY_TID, thread_id.c_str()); } @@ -551,21 +547,25 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa senderName = senderName.substr(0, pos); }*/ - // Last fall-back for adding this sender (Incase was not in the participants) - Is this even needed? + // Last fall-back for adding this sender (in case he was not in the participants) - is this even needed? if (!proto->IsChatContact(thread_id.c_str(), id.c_str())) { proto->AddChatContact(thread_id.c_str(), id.c_str(), senderName.c_str()); } - // Update chat with message. + // Update chat with message + // TODO: support also system messages (rename chat, user quit, etc.)! (here? or it is somewhere else?) proto->UpdateChat(thread_id.c_str(), id.c_str(), senderName.c_str(), message_text.c_str(), utils::time::fix_timestamp(json_as_float(timestamp))); proto->setString(hChatContact, FACEBOOK_KEY_MESSAGE_ID, message_id.c_str()); proto->ForkThread(&FacebookProto::ReadMessageWorker, hChatContact); } else { facebook_message* message = new facebook_message(); + + message->isIncoming = (id != proto->facy.self_.user_id); message->message_text = message_text; message->sender_name = utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_pstring(sender_name))); message->time = utils::time::fix_timestamp(json_as_float(timestamp)); - message->user_id = id; // TODO: Check if we have contact with this ID in friendlist and otherwise do something different? + message->thread_id = json_as_pstring(tid); + message->user_id = message->isIncoming ? id : proto->ThreadIDToContactID(message->thread_id); // TODO: Check if we have contact with this user_id in friendlist and otherwise do something different? message->message_id = message_id; messages->push_back(message); @@ -867,6 +867,7 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo if (author_email != NULL) message->sender_name = json_as_pstring(author_email); message->time = utils::time::fix_timestamp(json_as_float(timestamp)); + message->thread_id = thread_id; message->message_id = message_id; message->isIncoming = (author_id != proto->facy.self_.user_id); @@ -875,7 +876,6 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo // this is chatroom message message->isChat = true; message->user_id = author_id; - message->thread_id = thread_id; } else { // this is standard message @@ -899,3 +899,44 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo json_delete(root); return EXIT_SUCCESS; } + +int facebook_json_parser::parse_thread_info(void* data, std::string* user_id) +{ + std::string jsonData = static_cast< std::string* >(data)->substr(9); + + JSONNODE *root = json_parse(jsonData.c_str()); + if (root == NULL) + return EXIT_FAILURE; + + JSONNODE *payload = json_get(root, "payload"); + if (payload == NULL) { + json_delete(root); + return EXIT_FAILURE; + } + + JSONNODE *threads = json_get(payload, "threads"); + if (threads == NULL) { + json_delete(root); + return EXIT_FAILURE; + } + + std::map thread_ids; + for (unsigned int i = 0; i < json_size(threads); i++) { + JSONNODE *it = json_at(threads, i); + JSONNODE *canonical = json_get(it, "canonical_fbid"); + JSONNODE *thread_id = json_get(it, "thread_id"); + JSONNODE *message_count = json_get(it, "message_count"); // TODO: this could be useful for loading history from server + + if (canonical == NULL || thread_id == NULL) + continue; + + std::string id = json_as_pstring(canonical); + if (id == "null") + continue; + + *user_id = id; + } + + json_delete(root); + return EXIT_SUCCESS; +} diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h index 9e06e8b042..d506f0f50c 100644 --- a/protocols/FacebookRM/src/json.h +++ b/protocols/FacebookRM/src/json.h @@ -36,6 +36,7 @@ public: int parse_messages(void*, std::vector< facebook_message* >*, std::vector< facebook_notification* >*); int parse_unread_threads(void*, std::vector< std::string >*); int parse_thread_messages(void*, std::vector< facebook_message* >*, std::map< std::string, facebook_chatroom* >*, bool unreadOnly, int limit); + int parse_thread_info(void* data, std::string* user_id); facebook_json_parser(FacebookProto* proto) { diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index 584d1bebcb..866bc8cf00 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -359,9 +359,9 @@ void FacebookProto::ProcessUnreadMessage(void *p) facebook_chatroom *room = it->second; HANDLE hChatContact; if (GetChatUsers(room->thread_id.c_str()) == NULL) { - // Set thread id (TID) for later. AddChat(room->thread_id.c_str(), room->chat_name.c_str()); hChatContact = ChatIDToHContact(room->thread_id); + // Set thread id (TID) for later setTString(hChatContact, FACEBOOK_KEY_TID, room->thread_id.c_str()); for (std::map::iterator jt = room->participants.begin(); jt != room->participants.end(); ) { @@ -395,6 +395,11 @@ void FacebookProto::ProcessUnreadMessage(void *p) // TODO: optimize this? HANDLE hContact = AddToContactList(&fbu, CONTACT_NONE); setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str()); + + // Save TID if not exists already + ptrA tid( getStringA(hContact, FACEBOOK_KEY_TID)); + if (!tid || strcmp(tid, messages[i]->thread_id.c_str())) + setString(hContact, FACEBOOK_KEY_TID, messages[i]->thread_id.c_str()); // TODO: if contact is newly added, get his user info // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages? @@ -469,38 +474,40 @@ void FacebookProto::ProcessMessages(void* data) for(std::vector::size_type i=0; iuser_id != facy.self_.user_id) - { - debugLogA(" Got message: %s", messages[i]->message_text.c_str()); - facebook_user fbu; - fbu.user_id = messages[i]->user_id; - fbu.real_name = messages[i]->sender_name; - - HANDLE hContact = AddToContactList(&fbu, CONTACT_NONE); - setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str()); - - // TODO: if contact is newly added, get his user info - // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages? - - ParseSmileys(messages[i]->message_text, hContact); - - if (messages[i]->isIncoming) { - PROTORECVEVENT recv = {0}; - recv.flags = PREF_UTF; - recv.szMessage = const_cast(messages[i]->message_text.c_str()); - recv.timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; - ProtoChainRecvMsg(hContact, &recv); - } else { - DBEVENTINFO dbei = {0}; - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.flags = DBEF_SENT | DBEF_UTF; - dbei.szModule = m_szModuleName; - dbei.timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; - dbei.cbBlob = (DWORD)messages[i]->message_text.length() + 1; - dbei.pBlob = (PBYTE)messages[i]->message_text.c_str(); - db_event_add(hContact, &dbei); - } + debugLogA(" Got message: %s", messages[i]->message_text.c_str()); + facebook_user fbu; + fbu.user_id = messages[i]->user_id; + fbu.real_name = messages[i]->sender_name; + + HANDLE hContact = AddToContactList(&fbu, CONTACT_NONE); + setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str()); + + // Save TID if not exists already + ptrA tid(getStringA(hContact, FACEBOOK_KEY_TID)); + if (!tid || strcmp(tid, messages[i]->thread_id.c_str())) + setString(hContact, FACEBOOK_KEY_TID, messages[i]->thread_id.c_str()); + + // TODO: if contact is newly added, get his user info + // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages? + + ParseSmileys(messages[i]->message_text, hContact); + + if (messages[i]->isIncoming) { + PROTORECVEVENT recv = {0}; + recv.flags = PREF_UTF; + recv.szMessage = const_cast(messages[i]->message_text.c_str()); + recv.timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; + ProtoChainRecvMsg(hContact, &recv); + } else { + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT | DBEF_UTF; + dbei.szModule = m_szModuleName; + dbei.timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; + dbei.cbBlob = (DWORD)messages[i]->message_text.length() + 1; + dbei.pBlob = (PBYTE)messages[i]->message_text.c_str(); + db_event_add(hContact, &dbei); } delete messages[i]; } diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h index 000afba6ec..3d056a92c4 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -188,6 +188,7 @@ public: bool IsMyContact(HANDLE, bool include_chat = false); HANDLE ContactIDToHContact(std::string); HANDLE ChatIDToHContact(std::tstring); + std::string ThreadIDToContactID(std::string thread_id); HANDLE AddToContactList(facebook_user*, ContactType type, bool dont_check = false); void SetAllContactStatuses(int status); HANDLE HContactFromAuthEvent(HANDLE hEvent); -- cgit v1.2.3