From 5a3503225b9f0b864e901067867e481905f8f2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Mon, 14 Apr 2014 10:03:02 +0000 Subject: Facebook: Refactor receiving multi-chat messages - This will broke loading list of 5 users in room - Instead of name it will use id everytime -> but this will be fixed in the future in some better way than it was git-svn-id: http://svn.miranda-ng.org/main/trunk@8971 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/FacebookRM/src/json.cpp | 154 ++++++++++++++++++----------------- protocols/FacebookRM/src/process.cpp | 48 +++++++---- 2 files changed, 109 insertions(+), 93 deletions(-) diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index 65e2658dd7..9c85ebc08d 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -3,7 +3,7 @@ Facebook plugin for Miranda Instant Messenger _____________________________________________ -Copyright © 2009-11 Michal Zelinka, 2011-13 Robert Pösel +Copyright � 2009-11 Michal Zelinka, 2011-13 Robert P�sel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -521,85 +521,29 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa if (message_text.empty()) continue; - // Multi-user JSONNODE *gthreadinfo = json_get(msg, "group_thread_info"); if (gthreadinfo != NULL) { - std::tstring thread_id = json_as_string(tid); - - // This is a recent 5 person listing of participants. - JSONNODE *participants_ids = json_get(gthreadinfo, "participant_ids"); - JSONNODE *participants_names = json_get(gthreadinfo, "participant_names"); - - JSONNODE *thread_name_ = json_get(gthreadinfo, "name"); - std::tstring name = json_as_string(thread_name_); - - // if there is no name for this room, set own name - if (name.empty()) { - unsigned int namesCount = 3; // how many names should be in room name; max. 5 - - for (unsigned int n = 0; n < json_size(participants_names) && n < namesCount; n++) { - JSONNODE *nameItr = json_at(participants_names, n); - - if (!name.empty()) - name += _T(", "); - - name += json_as_string(nameItr); - } - JSONNODE *count_ = json_get(gthreadinfo, "participant_total_count"); - unsigned int count = json_as_int(count_); - - if (count > namesCount) { - TCHAR more[200]; - mir_sntprintf(more, SIZEOF(more), TranslateT("%s and more (%d)"), name.c_str(), count - namesCount); - name = more; - } - } - - MCONTACT hChatContact = NULL; - - // 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) { - 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()); - } - - if (!hChatContact) - hChatContact = proto->ChatIDToHContact(thread_id); - - for (unsigned int n = 0; n < json_size(participants_ids); n++) { - JSONNODE *idItr = json_at(participants_ids, n); - std::string pId = json_as_pstring(idItr); - - JSONNODE *nameItr = json_at(participants_names, n); - std::string pName = json_as_pstring(nameItr); - - if (!proto->IsChatContact(thread_id.c_str(), pId.c_str())) { - proto->AddChatContact(thread_id.c_str(), pId.c_str(), pName.c_str()); - } - } - - std::string senderName = json_as_pstring(sender_name); - /*std::string::size_type pos; - if ((pos = senderName.find(" ")) != std::string::npos) { - senderName = senderName.substr(0, pos); - }*/ + // Multi-user message + facebook_message* message = new facebook_message(); - // 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()); - } + message->isChat = true; + message->isUnread = true; + 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))); // TODO: or if not incomming use my own name from facy.self_ ? + message->time = utils::time::fix_timestamp(json_as_float(timestamp)); + message->thread_id = json_as_pstring(tid); // TODO: or if not incomming use my own id from facy.self_ ? + message->user_id = id; + message->message_id = message_id; - // 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, (void*)hChatContact); - } else { + messages->push_back(message); + } + else { + // Standard message facebook_message* message = new facebook_message(); - + + message->isChat = false; + message->isUnread = true; message->isIncoming = (id != proto->facy.self_.user_id); message->message_text = message_text; message->sender_name = message->isIncoming ? utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_pstring(sender_name))) : ""; @@ -846,6 +790,7 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo JSONNODE *canonical = json_get(it, "canonical_fbid"); JSONNODE *thread_id = json_get(it, "thread_id"); JSONNODE *name = json_get(it, "name"); + //JSONNODE *message_count = json_get(it, "message_count"); JSONNODE *unread_count = json_get(it, "unread_count"); // TODO: use it to check against number of loaded messages... but how? JSONNODE *folder = json_get(it, "folder"); @@ -1025,3 +970,62 @@ int facebook_json_parser::parse_user_info(void* data, facebook_user* fbu) json_delete(root); return EXIT_SUCCESS; } + +/* TODO: implement this somehow +int facebook_json_parser::parse_chat_info(void* data, facebook_chat* fbu) { + // This is a recent 5 person listing of participants. + JSONNODE *participants_ids = json_get(gthreadinfo, "participant_ids"); + JSONNODE *participants_names = json_get(gthreadinfo, "participant_names"); + + JSONNODE *thread_name_ = json_get(gthreadinfo, "name"); + std::tstring name = json_as_string(thread_name_); + + // if there is no name for this room, set own name + if (name.empty()) { + unsigned int namesCount = 3; // how many names should be in room name; max. 5 + + for (unsigned int n = 0; n < json_size(participants_names) && n < namesCount; n++) { + JSONNODE *nameItr = json_at(participants_names, n); + + if (!name.empty()) + name += _T(", "); + + name += json_as_string(nameItr); + } + JSONNODE *count_ = json_get(gthreadinfo, "participant_total_count"); + unsigned int count = json_as_int(count_); + + if (count > namesCount) { + TCHAR more[200]; + mir_sntprintf(more, SIZEOF(more), TranslateT("%s and more (%d)"), name.c_str(), count - namesCount); + name = more; + } + } + + if (name.empty()) + name = thread_id; + + for (unsigned int n = 0; n < json_size(participants_ids); n++) { + JSONNODE *idItr = json_at(participants_ids, n); + std::string pId = json_as_pstring(idItr); + + JSONNODE *nameItr = json_at(participants_names, n); + std::string pName = json_as_pstring(nameItr); + + if (!proto->IsChatContact(thread_id.c_str(), pId.c_str())) { + proto->AddChatContact(thread_id.c_str(), pId.c_str(), pName.c_str()); + } + } + + std::string senderName = json_as_pstring(sender_name); + std::string::size_type pos; + if ((pos = senderName.find(" ")) != std::string::npos) { + senderName = senderName.substr(0, pos); + } + + // 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()); + } +} +*/ \ No newline at end of file diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index 2d6802bfe8..d0dc4085d6 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -411,20 +411,16 @@ void FacebookProto::ReceiveMessages(std::vector messages, boo bool naseemsSpamMode = getBool(FACEBOOK_KEY_NASEEMS_SPAM_MODE, false); for(std::vector::size_type i = 0; i < messages.size(); i++) { + DWORD timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; + if (messages[i]->isChat) { + // Multi-user message debugLogA(" Got chat message: %s", messages[i]->message_text.c_str()); std::tstring tthread_id = _A2T(messages[i]->thread_id.c_str()); - std::string user_id = messages[i]->user_id; - std::string user_name = messages[i]->sender_name; - std::string message_text = messages[i]->message_text; - std::string message_id = messages[i]->message_id; - DWORD timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time; - - MCONTACT hChatContact = ChatIDToHContact(tthread_id); // RM TODO: better use check if chatroom exists/is in db/is online... no? - /// e.g. HANDLE hChatContact = proto->ChatIDToHContact(thread_id); ? + // like: if (ChatIDToHContact(tthread_id) == NULL) { if (GetChatUsers(tthread_id.c_str()) == NULL) { // In Naseem's spam mode we ignore outgoing messages sent from other instances if (naseemsSpamMode && !messages[i]->isIncoming) { @@ -432,20 +428,35 @@ void FacebookProto::ReceiveMessages(std::vector messages, boo continue; } - AddChat(tthread_id.c_str(), tthread_id.c_str()); // TODO: use correct name for chat, not thread_id - hChatContact = ChatIDToHContact(tthread_id); - // Set thread id (TID) for later - setTString(hChatContact, FACEBOOK_KEY_TID, tthread_id.c_str()); + // TODO: We don't have this chat, lets load info about it (name, list of users, last messages, etc.) + //LoadChatInfo(&fbu); // In this method use json's parse_chat_info + std::tstring tthread_name = tthread_id; // TODO: use correct name for chat, not thread_id + + AddChat(tthread_id.c_str(), tthread_name.c_str()); } - if (!hChatContact) - hChatContact = ChatIDToHContact(tthread_id); + MCONTACT hChatContact = ChatIDToHContact(tthread_id); + + // Save last (this) message ID + setString(hChatContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str()); - UpdateChat(tthread_id.c_str(), user_id.c_str(), user_name.c_str(), message_text.c_str(), timestamp); - setString(hChatContact, FACEBOOK_KEY_MESSAGE_ID, message_id.c_str()); + // Save TID if not exists already + ptrA tid(getStringA(hChatContact, FACEBOOK_KEY_TID)); + if (!tid || strcmp(tid, messages[i]->thread_id.c_str())) + setString(hChatContact, FACEBOOK_KEY_TID, messages[i]->thread_id.c_str()); + + ParseSmileys(messages[i]->message_text, hChatContact); + + // TODO: support also system messages (rename chat, user quit, etc.)! (here? or it is somewhere else? + // ... we must add some new "type" field into facebook_message structure and use it also for Pokes and similar) + UpdateChat(tthread_id.c_str(), messages[i]->user_id.c_str(), messages[i]->sender_name.c_str(), messages[i]->message_text.c_str(), timestamp); + + // Automatically mark message as read because chatroom doesn't support onRead event (yet) ForkThread(&FacebookProto::ReadMessageWorker, (void*)hChatContact); } else { + // Single-user message 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; @@ -464,6 +475,7 @@ void FacebookProto::ReceiveMessages(std::vector messages, boo hContact = AddToContactList(&fbu, CONTACT_NONE); } + // Save last (this) message ID setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str()); // Save TID if not exists already @@ -477,7 +489,7 @@ void FacebookProto::ReceiveMessages(std::vector messages, boo 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; + recv.timestamp = timestamp; ProtoChainRecvMsg(hContact, &recv); } else { DBEVENTINFO dbei = { 0 }; @@ -485,7 +497,7 @@ void FacebookProto::ReceiveMessages(std::vector messages, boo 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.timestamp = timestamp; dbei.cbBlob = (DWORD)messages[i]->message_text.length() + 1; dbei.pBlob = (PBYTE)messages[i]->message_text.c_str(); db_event_add(hContact, &dbei); -- cgit v1.2.3