summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Pösel <robyer@seznam.cz>2016-08-31 10:11:32 +0000
committerRobert Pösel <robyer@seznam.cz>2016-08-31 10:11:32 +0000
commit8a904bdef0e8237dee49c1b704d4ebbc2b28a958 (patch)
treec07494e752a8a00c237afdbcc25162391d66957c
parentfc8bb06ec24197d50e695e5de657e7904d6ce597 (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.cpp6
-rw-r--r--protocols/FacebookRM/src/constants.h12
-rw-r--r--protocols/FacebookRM/src/entities.h3
-rw-r--r--protocols/FacebookRM/src/json.cpp102
-rw-r--r--protocols/FacebookRM/src/process.cpp47
-rw-r--r--protocols/FacebookRM/src/proto.h2
-rw-r--r--protocols/FacebookRM/src/theme.cpp5
-rw-r--r--protocols/FacebookRM/src/version.h2
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>