diff options
author | Robert Pösel <robyer@seznam.cz> | 2016-08-31 10:11:32 +0000 |
---|---|---|
committer | Robert Pösel <robyer@seznam.cz> | 2016-08-31 10:11:32 +0000 |
commit | 8a904bdef0e8237dee49c1b704d4ebbc2b28a958 (patch) | |
tree | c07494e752a8a00c237afdbcc25162391d66957c | |
parent | fc8bb06ec24197d50e695e5de657e7904d6ce597 (diff) |
Facebook: Basic support for handling more chat events; version bump
Events like user join/leave, change emoji, etc. are now printed, but that's all. Still missing specific behavior for them, but that require more changes in events parsing and on other places.
git-svn-id: http://svn.miranda-ng.org/main/trunk@17222 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r-- | protocols/FacebookRM/src/chat.cpp | 6 | ||||
-rw-r--r-- | protocols/FacebookRM/src/constants.h | 12 | ||||
-rw-r--r-- | protocols/FacebookRM/src/entities.h | 3 | ||||
-rw-r--r-- | protocols/FacebookRM/src/json.cpp | 102 | ||||
-rw-r--r-- | protocols/FacebookRM/src/process.cpp | 47 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.h | 2 | ||||
-rw-r--r-- | protocols/FacebookRM/src/theme.cpp | 5 | ||||
-rw-r--r-- | protocols/FacebookRM/src/version.h | 2 |
8 files changed, 134 insertions, 45 deletions
diff --git a/protocols/FacebookRM/src/chat.cpp b/protocols/FacebookRM/src/chat.cpp index 9720dc06b3..78df418b38 100644 --- a/protocols/FacebookRM/src/chat.cpp +++ b/protocols/FacebookRM/src/chat.cpp @@ -163,7 +163,7 @@ int FacebookProto::OnGCEvent(WPARAM, LPARAM lParam) return 0; } -void FacebookProto::AddChatContact(const char *chat_id, const chatroom_participant &user) +void FacebookProto::AddChatContact(const char *chat_id, const chatroom_participant &user, bool addToLog) { // Don't add user if it's already there if (IsChatContact(chat_id, user.user_id.c_str())) @@ -176,7 +176,7 @@ void FacebookProto::AddChatContact(const char *chat_id, const chatroom_participa GCDEST gcd = { m_szModuleName, tchat_id, GC_EVENT_JOIN }; GCEVENT gce = { sizeof(gce), &gcd }; gce.pDest = &gcd; - gce.dwFlags = GCEF_ADDTOLOG; + gce.dwFlags = addToLog ? GCEF_ADDTOLOG : 0; gce.ptszNick = tnick; gce.ptszUID = tid; gce.time = ::time(NULL); @@ -325,7 +325,7 @@ INT_PTR FacebookProto::OnJoinChat(WPARAM hContact, LPARAM) // Add chat contacts 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); + AddChatContact(fbc->thread_id.c_str(), jt->second, false); } // Load last messages diff --git a/protocols/FacebookRM/src/constants.h b/protocols/FacebookRM/src/constants.h index bc90d50636..7d07a010d6 100644 --- a/protocols/FacebookRM/src/constants.h +++ b/protocols/FacebookRM/src/constants.h @@ -183,9 +183,17 @@ enum ClientType { CLIENT_MOBILE = 5 // Facebook on unknown mobile client (can't be determined for offline contacts)
};
+// TODO: Rework to "Events" and add also typing, seen, contact status, chat switch, etc. then have JSON parser only for parsing and a single place for processing updates
+// Each type then could have also separate class representing it. And when giving it in some list, make it map of arrays with key=thread_id to group it by contact/chat, to have it more effective
+// Use also for Poke and such events...
enum MessageType {
- MESSAGE = 1, // Classic message
- CALL = 2, // Video call
+ MESSAGE = 1, // Classic message
+ CALL = 2, // Video call
+ ADMIN_TEXT = 3,
+ SUBSCRIBE = 4,
+ UNSUBSCRIBE = 5,
+ THREAD_NAME = 6,
+ THREAD_IMAGE = 7,
};
enum ParticipantRole {
diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h index 6644f26e90..b997137043 100644 --- a/protocols/FacebookRM/src/entities.h +++ b/protocols/FacebookRM/src/entities.h @@ -3,7 +3,7 @@ Facebook plugin for Miranda Instant Messenger _____________________________________________ -Copyright © 2009-11 Michal Zelinka, 2011-16 Robert Pösel +Copyright � 2009-11 Michal Zelinka, 2011-16 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 @@ -103,6 +103,7 @@ struct facebook_message std::string message_text; std::string message_id; std::string thread_id; + std::string data; time_t time; bool isIncoming; bool isUnread; diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index f8cfb701d8..2c97a56b4a 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -665,7 +665,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo if (participant == participants.end()) { // TODO: load name of this participant participant->second.user_id = from_id; - proto->AddChatContact(tid.c_str(), participant->second); + proto->AddChatContact(tid.c_str(), participant->second, true); } participant = participants.find(from_id); @@ -934,47 +934,60 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo for (unsigned int i = 0; i < actions_.size(); i++) { const JSONNode &action_ = actions_[i]; + const JSONNode &author = action_["author"]; const JSONNode &thread_id_ = action_["thread_id"]; const JSONNode &log_body_ = action_["log_message_body"]; const JSONNode &log_data_ = action_["log_message_data"]; const JSONNode &log_type_ = action_["log_message_type"]; - if (!log_data_ || !log_body_ || !thread_id_ || !log_type_) + if (!author || !log_data_ || !log_body_ || !thread_id_ || !log_type_) continue; std::string thread_id = thread_id_.as_string(); std::string logType = log_type_.as_string(); std::string message_text = log_body_.as_string(); + std::string other_user_id = action_["other_user_fbid"].as_string(); + std::string message_id = action_["message_id"].as_string(); + + std::string author_id = author.as_string(); + std::string::size_type pos = author_id.find(":"); // strip "fbid:" prefix + if (pos != std::string::npos) + author_id = author_id.substr(pos + 1); + + facebook_message message; + message.isChat = other_user_id.empty(); // FIXME: Determine whether this is chat or contact event + message.isUnread = true; + message.isIncoming = (author_id != proto->facy.self_.user_id); + message.message_text = message_text; + message.time = utils::time::from_string(action_["timestamp"].as_string()); + message.user_id = message.isChat ? author_id : other_user_id; + message.message_id = message_id; + message.thread_id = thread_id; + if (logType == "log:video-call") { - std::string id = action_["other_user_fbid"].as_string(); - std::string message_id = action_["message_id"].as_string(); - - facebook_message message; - message.isChat = false; - message.isUnread = true; - message.isIncoming = (id != proto->facy.self_.user_id); - message.message_text = message_text; - message.time = utils::time::from_string(action_["timestamp"].as_string()); - message.user_id = id; - message.message_id = message_id; - message.thread_id = thread_id; message.type = CALL; - messages->push_back(message); + } + else if (logType == "log:generic-admin-text") { + message.type = ADMIN_TEXT; + } + else if (logType == "log:subscribe") { + message.type = SUBSCRIBE; + } + else if (logType == "log:unsubscribe") { + message.type = UNSUBSCRIBE; + } + else if (logType == "log:thread-name") { + message.type = THREAD_NAME; + message.data = log_data_["name"].as_string(); + } + else if (logType == "log:thread-image") { + message.type = THREAD_IMAGE; } else { proto->debugLogA("!!! Unknown log type - %s", logType.c_str()); - - // TODO: check for other types, now we expect this is rename chat - if (!proto->m_enableChat) - continue; - - std::string name = log_data_["name"].as_string(); - - // 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_text.c_str()); } + + messages->push_back(message); } } else if (t == "notifications_read" || t == "notifications_seen") { @@ -1112,8 +1125,7 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector< // Either there is "body" (for classic messages), or "log_message_type" and "log_message_body" (for log messages) const JSONNode &log_type_ = (*it)["log_message_type"]; const JSONNode &log_body_ = (*it)["log_message_body"]; - // const JSONNode &log_data_ = (*it)["log_message_data"]; // additional data for this log message - // e.g., for missed video calls - {"answered":false,"caller":"fbid:1234567890","callee":"fbid:123456789012345"} + const JSONNode &log_data_ = (*it)["log_message_data"]; // additional data for this log message if (!author || (!body && !log_body_) || !mid || !tid || !timestamp) { proto->debugLogA("parse_thread_messages: ignoring message (%s) - missing attribute", mid.as_string().c_str()); @@ -1177,6 +1189,22 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector< if (log_type == "log:video-call") { message.type = CALL; } + else if (log_type == "log:generic-admin-text") { + message.type = ADMIN_TEXT; + } + else if (log_type == "log:subscribe") { + message.type = SUBSCRIBE; + } + else if (log_type == "log:unsubscribe") { + message.type = UNSUBSCRIBE; + } + else if (log_type == "log:thread-name") { + message.type = THREAD_NAME; + message.data = log_data_["name"].as_string(); + } + else if (log_type == "log:thread-image") { + message.type = THREAD_IMAGE; + } else { proto->debugLogA("parse_thread_messages: unknown message log type (%s) - %s", mid.as_string().c_str(), log_type.c_str()); } @@ -1219,7 +1247,7 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook // Either there is "body" (for classic messages), or "log_message_type" and "log_message_body" (for log messages) const JSONNode &log_type_ = (*it)["log_message_type"]; const JSONNode &log_body_ = (*it)["log_message_body"]; - // const JSONNode &log_data_ = (*it)["log_message_data"]; + const JSONNode &log_data_ = (*it)["log_message_data"]; if (!author || (!body && !log_body_) || !mid || !tid || !timestamp) { proto->debugLogA("parse_history: ignoring message (%s) - missing attribute", mid.as_string().c_str()); @@ -1267,6 +1295,22 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook if (log_type == "log:video-call") { message.type = CALL; } + else if (log_type == "log:generic-admin-text") { + message.type = ADMIN_TEXT; + } + else if (log_type == "log:subscribe") { + message.type = SUBSCRIBE; + } + else if (log_type == "log:unsubscribe") { + message.type = UNSUBSCRIBE; + } + else if (log_type == "log:thread-name") { + message.type = THREAD_NAME; + message.data = log_data_["name"].as_string(); + } + else if (log_type == "log:thread-image") { + message.type = THREAD_IMAGE; + } else { proto->debugLogA("parse_history: unknown message log type (%s) - %s", mid.as_string().c_str(), log_type.c_str()); } diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index a3db0d8812..bc90683341 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -950,7 +950,7 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message> &messages, boo setString(hChatContact, FACEBOOK_KEY_TID, fbc->thread_id.c_str()); for (auto jt = fbc->participants.begin(); jt != fbc->participants.end(); ++jt) { - AddChatContact(fbc->thread_id.c_str(), jt->second); + AddChatContact(fbc->thread_id.c_str(), jt->second, false); } } @@ -979,10 +979,43 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message> &messages, boo if (jt != fbc->participants.end()) { name = jt->second.nick; } + else { + // TODO: Load info about this participant from server, and add it manually to participants list (maybe only if this is SUBSCRIBE type) + } - // 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(fbc->thread_id.c_str(), msg.user_id.c_str(), name.c_str(), msg.message_text.c_str(), msg.time); + switch (msg.type) { + default: + case MESSAGE: + UpdateChat(fbc->thread_id.c_str(), msg.user_id.c_str(), name.c_str(), msg.message_text.c_str(), msg.time); + break; + case ADMIN_TEXT: + UpdateChat(thread_id.c_str(), NULL, NULL, msg.message_text.c_str()); + break; + case SUBSCRIBE: + // TODO: We must get data with list of added users (their ids) from json to work properly, so for now we just print it as admin message + UpdateChat(thread_id.c_str(), NULL, NULL, msg.message_text.c_str()); + /*if (jt == fbc->participants.end()) { + // We don't have this user there yet, so load info about him and then add him + chatroom_participant participant; + participant.is_former = false; + participant.loaded = false; + participant.nick = msg.data; + participant.user_id = msg.data; + AddChatContact(thread_id.c_str(), participant, msg.isUnread); + }*/ + break; + case UNSUBSCRIBE: + RemoveChatContact(thread_id.c_str(), msg.user_id.c_str(), name.c_str()); + break; + case THREAD_NAME: + // proto->RenameChat(thread_id.c_str(), msg.data.c_str()); // this don't work, why? + setStringUtf(hChatContact, FACEBOOK_KEY_NICK, msg.data.c_str()); + UpdateChat(thread_id.c_str(), NULL, NULL, msg.message_text.c_str()); + break; + case THREAD_IMAGE: + UpdateChat(thread_id.c_str(), NULL, NULL, msg.message_text.c_str()); + break; + } // Automatically mark message as read because chatroom doesn't support onRead event (yet) hChatContacts->insert(hChatContact); // std::set checks duplicates at insert automatically @@ -1030,10 +1063,12 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message> &messages, boo DBEVENTINFO dbei = { 0 }; dbei.cbSize = sizeof(dbei); - if (msg.type == CALL) + if (msg.type == MESSAGE) + dbei.eventType = EVENTTYPE_MESSAGE; + else if (msg.type == CALL) dbei.eventType = FACEBOOK_EVENTTYPE_CALL; else - dbei.eventType = EVENTTYPE_MESSAGE; + dbei.eventType = EVENTTYPE_URL; // FIXME: Use better and specific type for our other event types. dbei.flags = DBEF_UTF; diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h index eb1b81f63e..585b3e93d4 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -213,7 +213,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 chatroom_participant &user); + void AddChatContact(const char *chat_id, const chatroom_participant &user, bool addToLog); 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); diff --git a/protocols/FacebookRM/src/theme.cpp b/protocols/FacebookRM/src/theme.cpp index 8e7ae32cf7..a1e83aca21 100644 --- a/protocols/FacebookRM/src/theme.cpp +++ b/protocols/FacebookRM/src/theme.cpp @@ -3,7 +3,7 @@ Facebook plugin for Miranda Instant Messenger
_____________________________________________
-Copyright © 2009-11 Michal Zelinka, 2011-16 Robert Pösel
+Copyright � 2009-11 Michal Zelinka, 2011-16 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
@@ -213,11 +213,12 @@ int FacebookProto::OnPrebuildContactMenu(WPARAM wParam, LPARAM) BYTE type = getByte(hContact, FACEBOOK_KEY_CONTACT_TYPE, 0);
bool bIsChatroom = isChatRoom(hContact);
+ bool bIsSpecialChatroom = IsSpecialChatRoom(hContact);
bool bIsPage = (type == CONTACT_PAGE);
Menu_ShowItem(g_hContactMenuVisitProfile, !bIsChatroom);
Menu_ShowItem(g_hContactMenuVisitFriendship, !bIsChatroom && !bIsPage);
- Menu_ShowItem(g_hContactMenuVisitConversation, true);
+ Menu_ShowItem(g_hContactMenuVisitConversation, !bIsSpecialChatroom);
Menu_ShowItem(g_hContactMenuPostStatus, !bIsChatroom);
Menu_ShowItem(g_hContactMenuLoadHistory, !bIsChatroom);
diff --git a/protocols/FacebookRM/src/version.h b/protocols/FacebookRM/src/version.h index 8823f24fa8..5f9b67272b 100644 --- a/protocols/FacebookRM/src/version.h +++ b/protocols/FacebookRM/src/version.h @@ -1,6 +1,6 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 2 -#define __RELEASE_NUM 15 +#define __RELEASE_NUM 16 #define __BUILD_NUM 0 #include <stdver.h> |