From bed8dcfa17b2f9de35a145826c2a4201e6daff13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Wed, 2 Oct 2013 20:08:00 +0000 Subject: Facebook: Multi user chat improvements - Load unread messages at login - Mark received messages as read git-svn-id: http://svn.miranda-ng.org/main/trunk@6313 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/FacebookRM/src/chat.cpp | 31 +++- protocols/FacebookRM/src/entities.h | 9 +- protocols/FacebookRM/src/events.cpp | 8 + protocols/FacebookRM/src/json.cpp | 321 ++++++++++++++++++---------------- protocols/FacebookRM/src/json.h | 2 +- protocols/FacebookRM/src/messages.cpp | 2 + protocols/FacebookRM/src/process.cpp | 72 +++++--- protocols/FacebookRM/src/proto.h | 1 + 8 files changed, 272 insertions(+), 174 deletions(-) (limited to 'protocols/FacebookRM/src') diff --git a/protocols/FacebookRM/src/chat.cpp b/protocols/FacebookRM/src/chat.cpp index e0414ae9c7..ea635c4a53 100644 --- a/protocols/FacebookRM/src/chat.cpp +++ b/protocols/FacebookRM/src/chat.cpp @@ -40,7 +40,8 @@ void FacebookProto::UpdateChat(const char *chat_id, const char *id, const char * gce.time = timestamp ? timestamp : ::time(NULL); gce.dwFlags = GC_TCHAR; gcd.iType = GC_EVENT_MESSAGE; - gce.bIsMe = !strcmp(id,facy.self_.user_id.c_str()); + if (id != NULL) + gce.bIsMe = !strcmp(id,facy.self_.user_id.c_str()); gce.dwFlags |= GCEF_ADDTOLOG; gce.ptszNick = tnick; @@ -55,6 +56,23 @@ void FacebookProto::UpdateChat(const char *chat_id, const char *id, const char * CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)hChatContact, (LPARAM)mir_a2u("Unseen")); } +void FacebookProto::RenameChat(const char *chat_id, const char *name) +{ + ptrT tchat_id( mir_a2t(chat_id)); + ptrT tname( mir_a2t_cp(name, CP_UTF8)); + + GCDEST gcd = { m_szModuleName }; + gcd.ptszID = tchat_id; + + GCEVENT gce = {sizeof(gce)}; + gce.pDest = &gcd; + gce.ptszText = tname; + gce.dwFlags = GC_TCHAR; + gcd.iType = GC_EVENT_CHANGESESSIONAME; + + CallService(MS_GC_EVENT, 0, reinterpret_cast(&gce)); +} + int FacebookProto::OnGCEvent(WPARAM wParam,LPARAM lParam) { GCHOOK *hook = reinterpret_cast(lParam); @@ -281,8 +299,17 @@ void FacebookProto::AddChat(const char *id, const char *name) } */ -INT_PTR FacebookProto::OnJoinChat(WPARAM,LPARAM suppress) +INT_PTR FacebookProto::OnJoinChat(WPARAM wParam,LPARAM suppress) { + HANDLE hContact = (HANDLE)wParam; + + // TODO: load info from server + old history,... + + ptrA id( getStringA(hContact, "ChatRoomID")); + ptrA name( getStringA(hContact, "Nick")); + + AddChat(id, name); + /* GCSESSION gcw = {sizeof(gcw)}; // Create the group chat session diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h index d18a939e7b..4eb4405f83 100644 --- a/protocols/FacebookRM/src/entities.h +++ b/protocols/FacebookRM/src/entities.h @@ -64,6 +64,7 @@ struct facebook_chatroom HANDLE handle; std::string chat_name; + std::string thread_id; std::map participants; std::string message_readers; @@ -74,9 +75,10 @@ struct facebook_chatroom struct facebook_message { std::string user_id; - std::string message_text; std::string sender_name; + std::string message_text; std::string message_id; + std::string thread_id; DWORD time; bool isIncoming; bool isUnread; @@ -84,7 +86,7 @@ struct facebook_message facebook_message() { - this->user_id = this->message_text = this->sender_name = this->message_id = ""; + this->user_id = this->message_text = this->sender_name = this->message_id = this->thread_id = ""; this->time = 0; this->isUnread = this->isIncoming = true; this->isChat = false; @@ -93,9 +95,10 @@ struct facebook_message facebook_message(const facebook_message& msg) { this->user_id = msg.user_id; - this->message_text = msg.message_text; this->sender_name = msg.sender_name; + this->message_text = msg.message_text; this->message_id = msg.message_id; + this->message_id = msg.thread_id; this->time = msg.time; this->isIncoming = msg.isIncoming; this->isUnread = msg.isUnread; diff --git a/protocols/FacebookRM/src/events.cpp b/protocols/FacebookRM/src/events.cpp index 826a0a55ef..68f6a1f547 100644 --- a/protocols/FacebookRM/src/events.cpp +++ b/protocols/FacebookRM/src/events.cpp @@ -83,6 +83,14 @@ void FacebookProto::NotifyEvent(TCHAR* title, TCHAR* info, HANDLE contact, DWORD if (!getByte(FACEBOOK_KEY_SYSTRAY_NOTIFY,DEFAULT_SYSTRAY_NOTIFY)) { if (ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { + + // TODO: if popup with particular ID is already showed, just update his content + // ... but f***ed up Popup Classes won't allow it now - they need to return hPopupWindow somehow + /* if (popup exists) { + if (PUChangeTextT(hWndPopup, info) > 0) // success + return; + }*/ + POPUPDATACLASS pd = { sizeof(pd) }; pd.ptszTitle = title; pd.ptszText = info; diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index df43cf9466..ee79210ed4 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -342,66 +342,7 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa continue; std::string t = json_as_pstring(type); - if (t == "msg" || t == "offline_msg") { - // we use this only for outgoing messages - - // TODO: load recipient id here, but use data from "messaging" section, problem is that "messaging" is usually before this - - JSONNODE *msg = json_get(it, "msg"); - if (msg == NULL) - continue; - - JSONNODE *from = json_get(it, "from"); - JSONNODE *from_name = json_get(it, "from_name"); - JSONNODE *text = json_get(msg, "text"); - JSONNODE *messageId = json_get(msg, "messageId"); - JSONNODE *time = json_get(msg, "time"); - // JSONNODE *tab_type = json_get(it, "tab_type"); // e.g. "friend" - - if (from == NULL || from_name == NULL || text == NULL || messageId == NULL || time == NULL) - continue; - - std::string from_id = json_as_pstring(from); - - // ignore incomming messages - if (from_id != proto->facy.self_.user_id) - continue; - - std::string message_id = json_as_pstring(messageId); - std::string message_text = json_as_pstring(text); - - message_text = utils::text::trim(utils::text::special_expressions_decode(utils::text::slashu_to_utf8(message_text)), true); - if (message_text.empty()) - continue; - - JSONNODE *truncated = json_get(msg, "truncated"); - if (truncated != NULL && json_as_int(truncated) == 1) { - std::string msg = "????? We got truncated message\n"; - msg += utils::text::special_expressions_decode(utils::text::slashu_to_utf8(message_text)); - proto->Log(msg.c_str()); - } - - // ignore duplicits or messages sent from miranda - if (ignore_duplicits(proto, message_id, message_text)) - continue; - - // Outgoing message - JSONNODE *to = json_get(it, "to"); - if (to == NULL) - continue; - - JSONNODE *to_name = json_get(it, "to_name"); - - facebook_message* message = new facebook_message(); - message->message_text = message_text; - message->sender_name = utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_pstring(to_name))); - message->time = utils::time::fix_timestamp(json_as_float(time)); - message->user_id = json_as_pstring(to); // TODO: Check if we have contact with this ID in friendlist and otherwise do something different? - message->message_id = message_id; - message->isIncoming = false; - - messages->push_back(message); - } else if (t == "messaging") { + if (t == "messaging") { // we use this only for incomming messages (and getting seen info) JSONNODE *type = json_get(it, "event"); @@ -420,8 +361,8 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa JSONNODE *threadid = json_get(it, "tid"); if (threadid != NULL) { // multi user chat - const char *tid = json_as_string(threadid); - const char *reader_id = json_as_string(reader); + std::string tid = json_as_pstring(threadid); + std::string reader_id = json_as_pstring(reader); std::map::iterator chatroom = proto->facy.chat_rooms.find(tid); if (chatroom != proto->facy.chat_rooms.end()) { @@ -447,7 +388,7 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa name = name.substr(0, pos); } - proto->AddChatContact(tid, reader_id, name.c_str()); + proto->AddChatContact(tid.c_str(), reader_id.c_str(), name.c_str()); } } @@ -512,50 +453,83 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa // Multi-user JSONNODE *gthreadinfo = json_get(msg, "group_thread_info"); - if (gthreadinfo != NULL) { - JSONNODE *thread_name = json_get(gthreadinfo, "name"); - const char* thread_id = json_as_string(tid); + if (gthreadinfo != NULL) { + std::string thread_id = json_as_pstring(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::string name = json_as_pstring(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 += ", "; + + name += json_as_pstring(nameItr); + } + JSONNODE *count_ = json_get(gthreadinfo, "participant_total_count"); + unsigned int count = json_as_int(count_); + + if (count > namesCount) { + char more[200]; + mir_snprintf(more, SIZEOF(more), Translate("%s and more (%d)"), name.c_str(), count - namesCount); + name = more; + } + } + + HANDLE hChatContact; // 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) == NULL) { + if (proto->GetChatUsers(thread_id.c_str()) == NULL) { // Set thread id (TID) for later. - proto->AddChat(thread_id, json_as_string(thread_name)); - db_set_s(proto->ChatIDToHContact(thread_id), proto->m_szModuleName, FACEBOOK_KEY_TID, thread_id); + proto->AddChat(thread_id.c_str(), name.c_str()); + hChatContact = proto->ChatIDToHContact(thread_id); + proto->setString(hChatContact, FACEBOOK_KEY_TID, thread_id.c_str()); } - // 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"); + if (!hChatContact) + hChatContact = proto->ChatIDToHContact(thread_id.c_str()); + for (unsigned int n = 0; n < json_size(participants_ids); n++) { JSONNODE *idItr = json_at(participants_ids, n); - const char* pId = json_as_string(idItr); + std::string pId = json_as_pstring(idItr); JSONNODE *nameItr = json_at(participants_names, n); - const char* pName = json_as_string(nameItr); + std::string pName = json_as_pstring(nameItr); - if (!proto->IsChatContact(thread_id, pId)) { - proto->AddChatContact(thread_id, pId, pName); + 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_string(sender_name); + 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 (Incase was not in the participants) - Is this even needed? - if (!proto->IsChatContact(thread_id, id.c_str())) { - proto->AddChatContact(thread_id, id.c_str(), senderName.c_str()); + 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. - proto->UpdateChat(thread_id, id.c_str(), senderName.c_str(), message_text.c_str(), utils::time::fix_timestamp(json_as_float(timestamp))); + 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->message_text = message_text; - message->sender_name = utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_string(sender_name))); + 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->message_id = message_id; @@ -563,50 +537,6 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa messages->push_back(message); } } - } else if (t == "thread_msg") { - // multiuser message - - JSONNODE *from_name = json_get(it, "from_name"); - JSONNODE *to_name_ = json_get(it, "to_name"); - if (to_name_ == NULL) - continue; - JSONNODE *to_name = json_get(to_name_, "__html"); - JSONNODE *to_id = json_get(it, "to"); - JSONNODE *from_id = json_get(it, "from"); - - JSONNODE *msg = json_get(it, "msg"); - JSONNODE *text = json_get(msg, "text"); - JSONNODE *messageId = json_get(msg, "messageId"); - - if (from_id == NULL || text == NULL || messageId == NULL) - continue; - - std::string id = json_as_pstring(from_id); - std::string message_id = json_as_pstring(messageId); - std::string message_text = json_as_pstring(text); - - // Ignore messages from myself - if (id == proto->facy.self_.user_id) - continue; - - // Ignore duplicits or messages sent from miranda - if (ignore_duplicits(proto, message_id, message_text)) - continue; - - message_text = utils::text::trim(utils::text::special_expressions_decode(utils::text::slashu_to_utf8(message_text)), true); - if (message_text.empty()) - continue; - - std::string title = utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_pstring(to_name))); - std::string url = "/?action=read&sk=inbox&page&query&tid=" + id; - std::string popup_text = utils::text::special_expressions_decode(utils::text::slashu_to_utf8(json_as_pstring(from_name))); - popup_text += ": " + message_text; - - proto->Log(" Got multichat message"); - - ptrT szTitle( mir_utf8decodeT(title.c_str())); - ptrT szText( mir_utf8decodeT(popup_text.c_str())); - proto->NotifyEvent(szTitle, szText, NULL, FACEBOOK_EVENT_OTHER, &url); } else if (t == "notification_json") { // event notification @@ -617,8 +547,8 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa for (unsigned int j = 0; j < json_size(nodes); j++) { JSONNODE *itNodes = json_at(nodes, j); - //JSONNODE *text = json_get(itNodes, "title/text"); - JSONNODE *text_ = json_get(itNodes, "unaggregatedTitle"); + //JSONNODE *text = json_get(itNodes, "title/text"); // use this when popups will be ready to allow changes of their content + JSONNODE *text_ = json_get(itNodes, "unaggregatedTitle"); // notifications one by one, not grouped if (text_ == NULL) continue; JSONNODE *text = json_get(text_, "text"); @@ -687,8 +617,71 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa proto->Log(" Requested chat switch to %s", isVisible ? "Online" : "Offline"); proto->SetStatus(isVisible ? ID_STATUS_ONLINE : ID_STATUS_INVISIBLE); } - } - else + } else if (t == "buddylist_overlay") { + // we opened/closed chat window - pretty useless info for us + continue; + } else if (t == "ticker_update:home") { + JSONNODE *actor_ = json_get(it, "actor"); + JSONNODE *time_ = json_get(it, "actor"); + JSONNODE *story_ = json_get(it, "story_xhp"); + + std::string id = json_as_pstring(actor_); + time_t time = json_as_float(time_); + std::string text = json_as_pstring(story_); + text = utils::text::slashu_to_utf8(text); + + text = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::source_get_value(&text, 3, "", ""))); + + // TODO: notify ticker updates + /* if (!text.empty()) { + proto->NotifyEvent() + }*/ + } else if (t == "inbox") { + // count of unread/unseen messages - pretty useless info for us + /* JSONNODE *unread_ = json_get(it, "unread"); + JSONNODE *unseen_ = json_get(it, "unseen"); + JSONNODE *other_unread_ = json_get(it, "other_unread"); + JSONNODE *other_unseen_ = json_get(it, "other_unseen"); + JSONNODE *seen_timestamp_ = json_get(it, "seen_timestamp"); */ + continue; + } else if (t == "mercury") { + // rename multi user chat, ... + + JSONNODE *actions_ = json_get(it, "actions"); + if (actions_ == NULL) + continue; + + for (unsigned int i = 0; i < json_size(actions_); i++) { + JSONNODE *action_ = json_at(actions_, i); + + JSONNODE *thread_id_ = json_get(action_, "thread_id"); + JSONNODE *log_body_ = json_get(action_, "log_message_body"); + JSONNODE *log_data_ = json_get(action_, "log_message_data"); + if (!log_data_ || !thread_id_) + continue; + + JSONNODE *name_ = json_get(log_data_, "name"); + std::string name = json_as_pstring(name_); + std::string thread_id = json_as_pstring(thread_id_); + std::string message = json_as_pstring(log_body_); + + // proto->RenameChat(thread_id.c_str(), name.c_str()); // this don't work, why? + proto->setStringUtf(proto->ChatIDToHContact(thread_id), FACEBOOK_KEY_NICK, name.c_str()); + + proto->UpdateChat(thread_id.c_str(), NULL, NULL, message.c_str()); + } + } else if (t == "notifications_read") { + // TODO: close popups with these IDs + JSONNODE *alert_ids = json_get(it, "alert_ids"); + for (unsigned int n = 0; n < json_size(alert_ids); n++) { + JSONNODE *idItr = json_at(alert_ids, n); + std::string alert_id = json_as_pstring(idItr); + + // PUDeletePopup(hWndPopup); + } + } else continue; } @@ -740,7 +733,7 @@ int facebook_json_parser::parse_unread_threads(void* data, std::vector< std::str return EXIT_SUCCESS; } -int facebook_json_parser::parse_thread_messages(void* data, std::vector< facebook_message* >* messages, bool unreadOnly, int limit) +int facebook_json_parser::parse_thread_messages(void* data, std::vector< facebook_message* >* messages, std::map< std::string, facebook_chatroom* >* chatrooms, bool unreadOnly, int limit) { std::string jsonData = static_cast< std::string* >(data)->substr(9); @@ -761,13 +754,37 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo return EXIT_FAILURE; } + JSONNODE *roger = json_get(payload, "roger"); + if (roger != NULL) { + for (unsigned int i = 0; i < json_size(roger); i++) { + JSONNODE *it = json_at(roger, i); + + facebook_chatroom *room = new facebook_chatroom(); + room->thread_id = json_name(it); + + for (unsigned int j = 0; j < json_size(it); j++) { + JSONNODE *jt = json_at(it, j); + std::string user_id = json_name(jt); + room->participants.insert(std::make_pair(user_id, user_id)); // TODO: get name somehow + } + + chatrooms->insert(std::make_pair(room->thread_id, room)); + } + } + 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 *name = json_get(it, "name"); JSONNODE *unread_count = json_get(it, "unread_count"); // TODO: use it to check against number of loaded messages... but how? + std::map::iterator iter = chatrooms->find(json_as_pstring(thread_id)); + if (iter != chatrooms->end()) { + iter->second->chat_name = json_as_pstring(name); // TODO: create name from users if there is no name... + } + if (canonical == NULL || thread_id == NULL) continue; @@ -790,23 +807,13 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo JSONNODE *timestamp = json_get(it, "timestamp"); if (author == NULL || body == NULL || mid == NULL || tid == NULL || timestamp == NULL) - continue; - - // Ignore read messages if we want only unread messages - JSONNODE *is_unread = json_get(it, "is_unread"); - if (unreadOnly && (is_unread == NULL || !json_as_bool(is_unread))) - continue; - - // Try to get user id from "threads" array (and simultaneously ignore multi user threads) - std::map::iterator iter = thread_ids.find(json_as_pstring(tid)); - if (iter == thread_ids.end()) - continue; // not found or ignored multi user thread + continue; - std::string user_id = iter->second; - std::string message_id = json_as_pstring(mid); + std::string thread_id = json_as_pstring(tid); + std::string message_id = json_as_pstring(mid); std::string message_text = json_as_pstring(body); std::string author_id = json_as_pstring(author); - std::string::size_type pos = author_id.find(":"); + std::string::size_type pos = author_id.find(":"); if (pos != std::string::npos) author_id = author_id.substr(pos+1); @@ -817,15 +824,37 @@ int facebook_json_parser::parse_thread_messages(void* data, std::vector< faceboo if (message_text.empty()) continue; - facebook_message* message = new facebook_message(); + facebook_message* message = new facebook_message(); message->message_text = message_text; if (author_email != NULL) message->sender_name = json_as_pstring(author_email); message->time = utils::time::fix_timestamp(json_as_float(timestamp)); - message->user_id = user_id; // TODO: Check if we have contact with this ID in friendlist and otherwise do something different? message->message_id = message_id; message->isIncoming = (author_id != proto->facy.self_.user_id); + std::map::iterator iter = chatrooms->find(thread_id); + if (iter != chatrooms->end()) { + // this is chatroom message + message->isChat = true; + message->user_id = author_id; + message->thread_id = thread_id; + } else { + // this is standard message + + // Ignore read messages if we want only unread messages + JSONNODE *is_unread = json_get(it, "is_unread"); + if (unreadOnly && (is_unread == NULL || !json_as_bool(is_unread))) + continue; + + message->isChat = false; + std::map::iterator iter = thread_ids.find(thread_id); + if (iter != thread_ids.end()) { + message->user_id = iter->second; // TODO: Check if we have contact with this ID in friendlist and otherwise do something different? + } else { + continue; + } + } + messages->push_back(message); } diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h index 8294c2ec2e..9e06e8b042 100644 --- a/protocols/FacebookRM/src/json.h +++ b/protocols/FacebookRM/src/json.h @@ -35,7 +35,7 @@ public: int parse_notifications(void*, std::vector< facebook_notification* >*); 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* >*, bool unreadOnly, int limit); + int parse_thread_messages(void*, std::vector< facebook_message* >*, std::map< std::string, facebook_chatroom* >*, bool unreadOnly, int limit); facebook_json_parser(FacebookProto* proto) { diff --git a/protocols/FacebookRM/src/messages.cpp b/protocols/FacebookRM/src/messages.cpp index 8ca7a8c2c1..f64addb82a 100644 --- a/protocols/FacebookRM/src/messages.cpp +++ b/protocols/FacebookRM/src/messages.cpp @@ -99,6 +99,8 @@ void FacebookProto::SendChatMsgWorker(void *p) if (!tid.empty()) { if (facy.send_message(tid, data->msg, &err_message, MESSAGE_TID)) UpdateChat(data->chat_id.c_str(), facy.self_.user_id.c_str(), facy.self_.real_name.c_str(), data->msg.c_str()); + else + UpdateChat(data->chat_id.c_str(), NULL, NULL, err_message.c_str()); } } diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index af9726db2f..97ca204e9e 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -348,13 +348,45 @@ void FacebookProto::ProcessUnreadMessage(void *p) CODE_BLOCK_TRY std::vector messages; + std::map chatrooms; facebook_json_parser* p = new facebook_json_parser(this); - p->parse_thread_messages(&resp.data, &messages, true, limit); + p->parse_thread_messages(&resp.data, &messages, &chatrooms, true, limit); delete p; - for(std::vector::size_type i = 0; i < messages.size(); i++) { - if (messages[i]->user_id != facy.self_.user_id) { + for (std::map::iterator it = chatrooms.begin(); it != chatrooms.end(); ) { + + 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); + setString(hChatContact, FACEBOOK_KEY_TID, room->thread_id.c_str()); + + for (std::map::iterator jt = room->participants.begin(); jt != room->participants.end(); ) { + AddChatContact(room->thread_id.c_str(), jt->first.c_str(), jt->second.c_str()); + jt++; + } + } + + if (!hChatContact) + hChatContact = ChatIDToHContact(room->thread_id); + + setString(hChatContact, FACEBOOK_KEY_MESSAGE_ID, room->thread_id.c_str()); + ForkThread(&FacebookProto::ReadMessageWorker, hChatContact); + + delete it->second; + it = chatrooms.erase(it); + } + chatrooms.clear(); + + + for (std::vector::size_type i = 0; i < messages.size(); i++) { + if (messages[i]->isChat) { + LOG(" Got chat message: %s", messages[i]->message_text.c_str()); + UpdateChat(messages[i]->thread_id.c_str(), messages[i]->user_id.c_str(), messages[i]->sender_name.c_str(), messages[i]->message_text.c_str(), local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time); + } else if (messages[i]->user_id != facy.self_.user_id) { LOG(" Got message: %s", messages[i]->message_text.c_str()); facebook_user fbu; fbu.user_id = messages[i]->user_id; @@ -369,26 +401,22 @@ void FacebookProto::ProcessUnreadMessage(void *p) ParseSmileys(messages[i]->message_text, hContact); - if (messages[i]->isChat) { - + 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 { - 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); - } + 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 d3cc040fb2..1c934f0a72 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -195,6 +195,7 @@ public: // Chats handling void AddChat(const char *id, const char *name); void UpdateChat(const char *chat_id, const char *id, const char *name, const char *message, DWORD timestamp = 0); + 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 RemoveChatContact(const char *chat_id, const char *id); -- cgit v1.2.3