summaryrefslogtreecommitdiff
path: root/protocols/FacebookRM
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/FacebookRM')
-rw-r--r--protocols/FacebookRM/src/client.h2
-rw-r--r--protocols/FacebookRM/src/contacts.cpp8
-rw-r--r--protocols/FacebookRM/src/json.cpp347
-rw-r--r--protocols/FacebookRM/src/json.h49
-rw-r--r--protocols/FacebookRM/src/process.cpp20
-rw-r--r--protocols/FacebookRM/src/proto.h20
-rw-r--r--protocols/FacebookRM/src/requests/contacts.h8
-rw-r--r--protocols/FacebookRM/src/requests/history.h66
-rw-r--r--protocols/FacebookRM/src/stdafx.h1
-rw-r--r--protocols/FacebookRM/src/version.h6
10 files changed, 243 insertions, 284 deletions
diff --git a/protocols/FacebookRM/src/client.h b/protocols/FacebookRM/src/client.h
index 4d7fe6ef1e..8d80ea72ef 100644
--- a/protocols/FacebookRM/src/client.h
+++ b/protocols/FacebookRM/src/client.h
@@ -161,7 +161,7 @@ public:
}
__inline const char *__rev() {
- return "2828561"; // FIXME: Some version of communication protocol? This version is from 12.2.2017
+ return "3496859"; // FIXME: Some version of communication protocol? This version is from 3.12.2017
}
////////////////////////////////////////////////////////////
diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp
index 104877514a..5a3f14ac93 100644
--- a/protocols/FacebookRM/src/contacts.cpp
+++ b/protocols/FacebookRM/src/contacts.cpp
@@ -177,7 +177,7 @@ std::string FacebookProto::ThreadIDToContactID(const std::string &thread_id)
if (resp.code == HTTP_CODE_OK) {
try {
- facebook_json_parser(this).parse_thread_info(&resp.data, &user_id);
+ ParseThreadInfo(&resp.data, &user_id);
if (!user_id.empty())
facy.thread_id_to_user_id.insert(std::make_pair(thread_id, user_id));
@@ -208,7 +208,7 @@ void FacebookProto::LoadContactInfo(facebook_user* fbu)
if (resp.code == HTTP_CODE_OK) {
try {
- facebook_json_parser(this).parse_user_info(&resp.data, fbu);
+ ParseUserInfo(&resp.data, fbu);
debugLogA("*** Contact thread info processed");
}
catch (const std::exception &e) {
@@ -276,7 +276,7 @@ void FacebookProto::LoadParticipantsNames(facebook_chatroom *fbc)
if (resp.code == HTTP_CODE_OK) {
try {
// TODO: We can cache these results and next time (e.g. for different chatroom) we can use that already cached names
- facebook_json_parser(this).parse_chat_participant_names(&resp.data, &fbc->participants);
+ ParseChatParticipants(&resp.data, &fbc->participants);
debugLogA("*** Participant names processed");
}
catch (const std::exception &e) {
@@ -315,7 +315,7 @@ void FacebookProto::LoadChatInfo(facebook_chatroom *fbc)
}
try {
- facebook_json_parser(this).parse_chat_info(&resp.data, fbc);
+ ParseChatInfo(&resp.data, fbc);
// Load missing participants names
LoadParticipantsNames(fbc);
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index 2deb45172f..369e2fdafd 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -73,7 +73,7 @@ void parseUser(const JSONNode &it, facebook_user *fbu)
}
}
-void parseMessageType(FacebookProto *proto, facebook_message &message, const JSONNode &log_type_, const JSONNode &log_body_, const JSONNode &log_data_) {
+void FacebookProto::ParseMessageType(facebook_message &message, const JSONNode &log_type_, const JSONNode &log_body_, const JSONNode &log_data_) {
if (!log_type_ || !log_body_ || !log_data_)
return;
@@ -118,11 +118,11 @@ void parseMessageType(FacebookProto *proto, facebook_message &message, const JSO
message.type = THREAD_IMAGE;
}
else {
- proto->debugLogA("!!! Unknown log type - %s", logType.c_str());
+ debugLogA("!!! Unknown log type - %s", logType.c_str());
}
}
-int facebook_json_parser::parse_chat_participant_names(std::string *data, std::map<std::string, chatroom_participant>* participants)
+int FacebookProto::ParseChatParticipants(std::string *data, std::map<std::string, chatroom_participant>* participants)
{
std::string jsonData = data->substr(9);
@@ -154,7 +154,7 @@ int facebook_json_parser::parse_chat_participant_names(std::string *data, std::m
else if (type == "page") {
user.role = ROLE_NONE;
// Use prefix for "page" users
- user.nick = proto->m_pagePrefix + " " + userName;
+ user.nick = m_pagePrefix + " " + userName;
}
user.loaded = true;
@@ -164,7 +164,7 @@ int facebook_json_parser::parse_chat_participant_names(std::string *data, std::m
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_friends(std::string *data, std::map< std::string, facebook_user* >* friends, bool loadAllContacts)
+int FacebookProto::ParseFriends(std::string *data, std::map< std::string, facebook_user* >* friends, bool loadAllContacts)
{
std::string jsonData = data->substr(9);
@@ -193,7 +193,7 @@ int facebook_json_parser::parse_friends(std::string *data, std::map< std::string
}
-int facebook_json_parser::parse_notifications(std::string *data, std::map< std::string, facebook_notification* > *notifications)
+int FacebookProto::ParseNotifications(std::string *data, std::map< std::string, facebook_notification* > *notifications)
{
std::string jsonData = data->substr(9);
@@ -206,7 +206,7 @@ int facebook_json_parser::parse_notifications(std::string *data, std::map< std::
return EXIT_FAILURE;
// Create notifications chatroom (if it doesn't exists), because we will be writing to it new notifications here
- proto->PrepareNotificationsChatRoom();
+ PrepareNotificationsChatRoom();
for (auto it = list.begin(); it != list.end(); ++it) {
const JSONNode &id_ = (*it)["alert_id"];
@@ -235,7 +235,7 @@ int facebook_json_parser::parse_notifications(std::string *data, std::map< std::
notification->setIcon(icon_.as_string());
// Write notification to chatroom
- proto->UpdateNotificationsChatRoom(notification);
+ UpdateNotificationsChatRoom(notification);
// If it's unseen, remember it, otherwise forget it
if (notifications->find(notification->id) == notifications->end())
@@ -247,19 +247,19 @@ int facebook_json_parser::parse_notifications(std::string *data, std::map< std::
return EXIT_SUCCESS;
}
-bool ignore_duplicits(FacebookProto *proto, const std::string &mid)
+bool FacebookProto::IgnoreDuplicates(const std::string &mid)
{
- ScopedLock s(proto->facy.send_message_lock_);
+ ScopedLock s(facy.send_message_lock_);
- std::map<std::string, int>::iterator it = proto->facy.messages_ignore.find(mid);
- if (it != proto->facy.messages_ignore.end()) {
- proto->debugLogA("??? Ignoring duplicit/sent message ID: %s", mid.c_str());
+ std::map<std::string, int>::iterator it = facy.messages_ignore.find(mid);
+ if (it != facy.messages_ignore.end()) {
+ debugLogA("??? Ignoring duplicit/sent message ID: %s", mid.c_str());
it->second++; // increase counter (for deleting it later)
return true;
}
// remember this id to ignore duplicits
- proto->facy.messages_ignore.insert(std::make_pair(mid, 1));
+ facy.messages_ignore.insert(std::make_pair(mid, 1));
return false;
}
@@ -270,10 +270,10 @@ std::string absolutizeUrl(std::string &url) {
return url;
}
-void parseAttachments(FacebookProto *proto, std::string *message_text, const JSONNode &delta_, std::string other_user_fbid, bool legacy)
+void FacebookProto::ParseAttachments(std::string &message_text, const JSONNode &delta_, std::string other_user_fbid, bool legacy)
{
std::string attachments_text;
- std::string type;
+ std::wstring newText;
const JSONNode &attachments_ = delta_["attachments"];
if (!attachments_ || attachments_.empty())
@@ -282,36 +282,60 @@ void parseAttachments(FacebookProto *proto, std::string *message_text, const JSO
for (auto itAttachment = attachments_.begin(); itAttachment != attachments_.end(); ++itAttachment) {
const JSONNode &attach_ = legacy ? (*itAttachment) : (*itAttachment)["mercury"];
- type = attach_["attach_type"].as_string(); // "sticker", "photo", "file", "share", "animated_image", "video"
-
- if (type == "photo") {
- std::string filename = attach_["name"].as_string();
- std::string link = attach_["hires_url"].as_string();
- if (link.empty()) {
- link = attach_["large_preview_url"].as_string();
+ if (const JSONNode sticker_ = attach_["sticker_attachment"]) {
+ newText = TranslateT("a sticker");
+ attachments_text += "\n";
+
+ std::string link = sticker_["url"].as_string();
+ if (!link.empty())
+ attachments_text += absolutizeUrl(link) + "\n";
+
+ std::string label = sticker_["label"].as_string();
+ if (!label.empty())
+ attachments_text += label + "\n";
+
+ const JSONNode &stickerId_ = sticker_["id"];
+ if (stickerId_) {
+ // Stickers as smileys
+ if (getByte(FACEBOOK_KEY_CUSTOM_SMILEYS, DEFAULT_CUSTOM_SMILEYS) && !facy.loading_history) {
+ // FIXME: rewrite smileyadd to use custom smileys per protocol and not per contact and then remove this ugliness
+ if (!other_user_fbid.empty()) {
+ std::string sticker = "[[sticker:" + stickerId_.as_string() + "]]";
+ StickerAsSmiley(sticker, link, ContactIDToHContact(other_user_fbid));
+ }
+ }
}
- if (link.empty()) {
- link = attach_["preview_url"].as_string();
+ }
+ else if (const JSONNode blob_ = attach_["blob_attachment"]) {
+ std::string type = blob_["__typename"].as_string();
+ if (type == "MessageAnimatedImage") { // a GIF
+ newText = TranslateT("a GIF");
+
+ std::string link = blob_["animated_image"]["uri"].as_string();
+ if (!link.empty())
+ attachments_text += "\n" + absolutizeUrl(link) + "\n";
}
+ else {
+ newText = (attachments_.size() > 1) ? TranslateT("files") : TranslateT("a file");
- if (!link.empty()) {
- attachments_text += "\n" + (!filename.empty() ? "<" + filename + "> " : "") + absolutizeUrl(link) + "\n";
- }
- }
- else if (type == "file" || type == "video") {
- std::string filename = attach_["name"].as_string();
- std::string link = attach_["url"].as_string();
+ std::string filename = blob_["filename"].as_string();
+ std::string filesize = attach_["fileSize"].as_string();
+ if (!filesize.empty())
+ filename += ", " + filesize + " bytes";
- if (!link.empty()) {
- attachments_text += "\n" + (!filename.empty() ? "<" + filename + "> " : "") + absolutizeUrl(link) + "\n";
+ std::string link = blob_["url"].as_string();
+ if (!link.empty())
+ attachments_text += "\n" + (!filename.empty() ? "<" + filename + "> " : "") + absolutizeUrl(link) + "\n";
}
}
- else if (type == "share") {
- const JSONNode &share = attach_["share"];
- if (share) {
- std::string title = share["title"] ? share["title"].as_string() : "";
- std::string description = share["description"] ? share["description"].as_string() : "";
- std::string link = share["uri"].as_string();
+ else if (const JSONNode story_ = attach_["extensible_attachment"]["story_attachment"]) {
+ std::string type = story_["target"]["__typename"].as_string();
+ if (type == "ExternalUrl") {
+ newText = TranslateT("a link");
+
+ std::string title = story_["title_with_entities"]["text"].as_string();
+ std::string description = story_["description"]["text"].as_string();
+ std::string link = story_["url"].as_string();
// shorten long descriptions
description = utils::text::truncate_utf8(description, MAX_LINK_DESCRIPTION_LEN);
@@ -330,83 +354,29 @@ void parseAttachments(FacebookProto *proto, std::string *message_text, const JSO
attachments_text += absolutizeUrl(link) + "\n";
}
}
+ else debugLogA("json::parseAttachments (%s) - Unknown extensible attachment type %s", legacy ? "legacy" : "not legacy", type.c_str());
}
- else if (type == "sticker") {
- std::string link = attach_["url"].as_string();
- if (!link.empty()) {
- attachments_text += "\n" + absolutizeUrl(link) + "\n";
- }
-
- const JSONNode &metadata = attach_["metadata"];
- if (metadata) {
- const JSONNode &stickerId_ = metadata["stickerID"];
- if (stickerId_) {
- std::string sticker = "[[sticker:" + stickerId_.as_string() + "]]\n";
- attachments_text += sticker;
-
- // Stickers as smileys
- if (proto->getByte(FACEBOOK_KEY_CUSTOM_SMILEYS, DEFAULT_CUSTOM_SMILEYS) && !proto->facy.loading_history) {
- // FIXME: rewrite smileyadd to use custom smileys per protocol and not per contact and then remove this ugliness
- if (!other_user_fbid.empty()) {
- MCONTACT hContact = proto->ContactIDToHContact(other_user_fbid);
- proto->StickerAsSmiley(sticker, link, hContact);
- }
- }
- }
- }
- }
- else if (type == "animated_image") {
- std::string link = attach_["hires_url"].as_string();
- if (link.empty()) {
- link = attach_["large_preview_url"].as_string();
- }
- if (link.empty()) {
- link = attach_["preview_url"].as_string();
- }
-
- if (!link.empty()) {
- attachments_text += "\n" + absolutizeUrl(link) + "\n";
- }
- }
- else {
- proto->debugLogA("json::parseAttachments (%s) - Unknown attachment type '%s'", legacy ? "legacy" : "not legacy", type.c_str());
- }
+ else debugLogA("json::parseAttachments (%s) - Unknown attachment type", legacy ? "legacy" : "not legacy");
}
// TODO: have this as extra event, not replace or append message content
- if (!message_text->empty())
- *message_text += "\n\n";
+ if (!message_text.empty())
+ message_text += "\n\n";
if (!attachments_text.empty()) {
- std::wstring newText;
- if (type == "sticker")
- newText = TranslateT("a sticker");
- else if (type == "share")
- newText = TranslateT("a link");
- else if (type == "file")
- newText = (attachments_.size() > 1) ? TranslateT("files") : TranslateT("a file");
- else if (type == "photo")
- newText = (attachments_.size() > 1) ? TranslateT("photos") : TranslateT("a photo");
- else if (type == "video")
- newText = TranslateT("a video");
- else if (type == "animated_image")
- newText = TranslateT("a GIF");
- else
- newText = _A2T(type.c_str());
-
wchar_t title[200];
mir_snwprintf(title, TranslateT("User sent %s:"), newText.c_str());
- *message_text += T2Utf(title);
- *message_text += attachments_text;
+ message_text += T2Utf(title);
+ message_text += attachments_text;
}
else {
- *message_text += T2Utf(TranslateT("User sent an unsupported attachment. Open your browser to see it."));
- proto->debugLogA("json::parseAttachments (%s) - Unsupported attachment:\n%s", legacy ? "legacy" : "not legacy", attachments_.as_string().c_str());
+ message_text += T2Utf(TranslateT("User sent an unsupported attachment. Open your browser to see it."));
+ debugLogA("json::parseAttachments (%s) - Unsupported attachment:\n%s", legacy ? "legacy" : "not legacy", attachments_.as_string().c_str());
}
}
-bool parseMessageMetadata(FacebookProto *proto, facebook_message &message, const JSONNode &meta_)
+bool FacebookProto::ParseMessageMetadata(facebook_message &message, const JSONNode &meta_)
{
if (!meta_)
return false;
@@ -426,7 +396,7 @@ bool parseMessageMetadata(FacebookProto *proto, facebook_message &message, const
std::string threadFbId = (!otherUserFbId_ && threadFbId_ ? "id." + threadFbId_.as_string() : ""); // NOTE: we must add "id." prefix as this is threadFbId and we want threadId (but only for multi chats)
message.isChat = otherUserFbId.empty();
- message.isIncoming = (actorFbId_.as_string() != proto->facy.self_.user_id);
+ message.isIncoming = (actorFbId_.as_string() != facy.self_.user_id);
message.isUnread = message.isIncoming;
message.message_text = (adminText_ ? adminText_.as_string() : "");
message.time = utils::time::from_string(timestamp_.as_string());
@@ -436,20 +406,20 @@ bool parseMessageMetadata(FacebookProto *proto, facebook_message &message, const
return true;
}
-bool processSpecialMessage(FacebookProto *proto, std::vector<facebook_message>* messages, const JSONNode &meta_, MessageType messageType, const std::string &messageData = "")
+bool FacebookProto::ProcessSpecialMessage(std::vector<facebook_message>* messages, const JSONNode &meta_, MessageType messageType, const std::string &messageData)
{
facebook_message message;
message.type = messageType;
message.data = messageData;
// Parse message metadata
- if (!parseMessageMetadata(proto, message, meta_)) {
- proto->debugLogA("json::processSpecialMessage - given empty messageMetadata");
+ if (!ParseMessageMetadata(message, meta_)) {
+ debugLogA("json::ProcessSpecialMessage - given empty messageMetadata");
return false;
}
// Ignore duplicits or messages sent from miranda
- if (ignore_duplicits(proto, message.message_id)) {
+ if (IgnoreDuplicates(message.message_id)) {
return false;
}
@@ -458,12 +428,12 @@ bool processSpecialMessage(FacebookProto *proto, std::vector<facebook_message>*
}
-int facebook_json_parser::parse_messages(std::string *pData, std::vector<facebook_message>* messages, std::map< std::string, facebook_notification* >* notifications)
+int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_message>* messages, std::map< std::string, facebook_notification* >* notifications)
{
// remove old received messages from map
- for (std::map<std::string, int>::iterator it = proto->facy.messages_ignore.begin(); it != proto->facy.messages_ignore.end();) {
+ for (std::map<std::string, int>::iterator it = facy.messages_ignore.begin(); it != facy.messages_ignore.end();) {
if (it->second > FACEBOOK_IGNORE_COUNTER_LIMIT) {
- it = proto->facy.messages_ignore.erase(it);
+ it = facy.messages_ignore.erase(it);
}
else {
it->second++; // increase counter on each request
@@ -499,20 +469,20 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
// Parse message metadata
const JSONNode &meta_ = delta_["messageMetadata"];
- if (!parseMessageMetadata(proto, message, meta_)) {
- proto->debugLogA("json::parse_messages - No messageMetadata element");
+ if (!ParseMessageMetadata(message, meta_)) {
+ debugLogA("json::ParseMessages - No messageMetadata element");
continue;
}
// Ignore duplicits or messages sent from miranda
- if (ignore_duplicits(proto, message.message_id))
+ if (IgnoreDuplicates(message.message_id))
continue;
const JSONNode &body_ = delta_["body"];
std::string messageText = body_.as_string();
// Process attachements and stickers
- parseAttachments(proto, &messageText, delta_, (message.isChat ? "" : message.user_id), false);
+ ParseAttachments(messageText, delta_, (message.isChat ? "" : message.user_id), false);
message.message_text = utils::text::trim(messageText, true);
messages->push_back(message);
@@ -544,21 +514,21 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
// multi chat
// ignore if disabled
- if (!proto->m_enableChat)
+ if (!m_enableChat)
continue;
std::string readerId = actor_.as_string();
std::string tid = "id." + thread_.as_string(); // NOTE: threadFbId means just numeric id of thread, without "id." prefix. We add it here to have it consistent with other methods (where threadId is used)
- MCONTACT hContact = proto->ChatIDToHContact(tid);
- proto->facy.insert_reader(hContact, timestamp, readerId);
+ MCONTACT hContact = ChatIDToHContact(tid);
+ facy.insert_reader(hContact, timestamp, readerId);
}
else if (reader_) {
// single chat
std::string userId = reader_.as_string();
- MCONTACT hContact = proto->ContactIDToHContact(userId);
- proto->facy.insert_reader(hContact, timestamp);
+ MCONTACT hContact = ContactIDToHContact(userId);
+ facy.insert_reader(hContact, timestamp);
}
}
else if (cls == "MarkRead") { // revised 5.3.2017
@@ -601,10 +571,10 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
//const JSONNode &thread_icon_ = untyped_["thread_icon"]; // emoji symbol
}
else {
- proto->debugLogA("json::parse_messages - Unknown AdminTextMessage type '%s'", deltaType.c_str());
+ debugLogA("json::ParseMessages - Unknown AdminTextMessage type '%s'", deltaType.c_str());
}
- if (!processSpecialMessage(proto, messages, meta_, messageType)) {
+ if (!ProcessSpecialMessage(messages, meta_, messageType)) {
// Message wasn't added - either it is duplicate or there was some error
continue;
}
@@ -619,17 +589,14 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &eventType_ = delta_["eventType"]; // e.g. "VOICE_EVENT", "VIDEO_EVENT"
std::string eventType = eventType_.as_string();
- if (eventType == "VOICE_EVENT") {
+ if (eventType == "VOICE_EVENT")
messageType = PHONE_CALL;
- }
- else if (eventType == "VIDEO_EVENT") {
+ else if (eventType == "VIDEO_EVENT")
messageType = VIDEO_CALL;
- }
- else {
- proto->debugLogA("json::parse_messages - Unknown RTCEventLog type '%s'", eventType.c_str());
- }
+ else
+ debugLogA("json::ParseMessages - Unknown RTCEventLog type '%s'", eventType.c_str());
- if (!processSpecialMessage(proto, messages, meta_, messageType)) {
+ if (!ProcessSpecialMessage(messages, meta_, messageType)) {
// Message wasn't added - either it is duplicate or there was some error
continue;
}
@@ -641,7 +608,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &name_ = delta_["name"]; // new name of the chat (could be empty)
std::string data = (name_ ? name_.as_string() : "");
- processSpecialMessage(proto, messages, meta_, THREAD_NAME, data);
+ ProcessSpecialMessage(messages, meta_, THREAD_NAME, data);
}
else if (cls == "ThreadMuteSettings") {
//const JSONNode &expireTime_ = delta_["expireTime"]; // timestamp until which this thread will be muted; could be 0 = unmuted
@@ -654,7 +621,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &leftParticipantFbId_ = delta_["leftParticipantFbId"];
std::string data = (leftParticipantFbId_ ? leftParticipantFbId_.as_string() : "");
- processSpecialMessage(proto, messages, meta_, UNSUBSCRIBE, data);
+ ProcessSpecialMessage(messages, meta_, UNSUBSCRIBE, data);
}
else if (cls == "ParticipantsAddedToGroupThread") {
// user was added to multi user chat
@@ -676,11 +643,11 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
}
}
- processSpecialMessage(proto, messages, meta_, SUBSCRIBE, data);
+ ProcessSpecialMessage(messages, meta_, SUBSCRIBE, data);
}
else {
// DeliveryReceipt, MarkRead, ThreadDelete
- proto->debugLogA("json::parse_messages - Unknown delta class '%s'", cls.c_str());
+ debugLogA("json::ParseMessages - Unknown delta class '%s'", cls.c_str());
}
}
else if (t == "notification_json") {
@@ -688,7 +655,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &nodes = (*it)["nodes"];
// Create notifications chatroom (if it doesn't exists), because we will be writing to it new notifications here
- proto->PrepareNotificationsChatRoom();
+ PrepareNotificationsChatRoom();
for (auto itNodes = nodes.begin(); itNodes != nodes.end(); ++itNodes) {
const JSONNode &text_ = (*itNodes)["unaggregatedTitle"]; // notifications one by one, not grouped
@@ -708,9 +675,9 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
continue;
time_t timestamp = utils::time::from_string(time.as_string());
- if (timestamp > proto->facy.last_notification_time_) {
+ if (timestamp > facy.last_notification_time_) {
// Only new notifications
- proto->facy.last_notification_time_ = timestamp;
+ facy.last_notification_time_ = timestamp;
facebook_notification* notification = new facebook_notification();
notification->text = utils::text::slashu_to_utf8(text.as_string());
@@ -725,7 +692,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
notification->id = notification->id.substr(pos + 1);
// Write notification to chatroom
- proto->UpdateNotificationsChatRoom(notification);
+ UpdateNotificationsChatRoom(notification);
// If it's unseen, remember it, otherwise forget it (here it will always be unseen)
if (notifications->find(notification->id) == notifications->end() && !notification->seen)
@@ -761,14 +728,14 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
std::string alert_id = alertId_.as_string();
// Notify it, if user wants to be notified
- if (proto->getByte(FACEBOOK_KEY_EVENT_FRIENDSHIP_ENABLE, DEFAULT_EVENT_FRIENDSHIP_ENABLE)) {
- proto->NotifyEvent(proto->m_tszUserName, ptrW(mir_utf8decodeW(text.c_str())), NULL, EVENT_FRIENDSHIP, &url, alert_id.empty() ? nullptr : &alert_id);
+ if (getByte(FACEBOOK_KEY_EVENT_FRIENDSHIP_ENABLE, DEFAULT_EVENT_FRIENDSHIP_ENABLE)) {
+ NotifyEvent(m_tszUserName, ptrW(mir_utf8decodeW(text.c_str())), NULL, EVENT_FRIENDSHIP, &url, alert_id.empty() ? nullptr : &alert_id);
}
}
}
else if (t == "jewel_requests_add") {
// New friendship request, load them all with real names (because there is only user_id in "from" field)
- proto->ForkThread(&FacebookProto::ProcessFriendRequests, nullptr);
+ ForkThread(&FacebookProto::ProcessFriendRequests, nullptr);
}
/*else if (t == "jewel_requests_handled") { // revised 5.3.2017
// When some request is approved (or perhaps even ignored/removed)
@@ -789,22 +756,22 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &st_ = (*it)["st"]; // typing status - 1 = started typing, 0 = stopped typing
// Ignore wrong (without "from") typing notifications or that are not meant for us (but e.g. for our page)
- if (!from_ || to_.as_string() != proto->facy.self_.user_id)
+ if (!from_ || to_.as_string() != facy.self_.user_id)
continue;
facebook_user fbu;
fbu.user_id = from_.as_string();
fbu.type = CONTACT_FRIEND; // only friends are able to send typing notifications
- MCONTACT hContact = proto->AddToContactList(&fbu);
+ MCONTACT hContact = AddToContactList(&fbu);
if (st_.as_int() == 1)
- proto->StartTyping(hContact);
+ StartTyping(hContact);
else
- proto->StopTyping(hContact);
+ StopTyping(hContact);
}
else if (t == "ttyp") {
// multi chat typing notification
- if (!proto->m_enableChat)
+ if (!m_enableChat)
continue;
const JSONNode &from_ = (*it)["from"];
@@ -816,8 +783,8 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
std::string tid = thread_.as_string();
std::string from_id = from_.as_string();
- auto itRoom = proto->facy.chat_rooms.find(thread_.as_string());
- if (itRoom != proto->facy.chat_rooms.end()) {
+ auto itRoom = facy.chat_rooms.find(thread_.as_string());
+ if (itRoom != facy.chat_rooms.end()) {
facebook_chatroom *chatroom = itRoom->second;
std::map<std::string, chatroom_participant> participants = chatroom->participants;
@@ -827,12 +794,12 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
chatroom_participant new_participant;
new_participant.user_id = from_id;
new_participant.nick = from_id;
- proto->AddChatContact(tid.c_str(), new_participant, true);
+ AddChatContact(tid.c_str(), new_participant, true);
}
participant = participants.find(from_id);
if (participant != participants.end()) {
- MCONTACT hChatContact = proto->ChatIDToHContact(tid);
+ MCONTACT hChatContact = ChatIDToHContact(tid);
ptrW name(mir_utf8decodeW(participant->second.nick.c_str()));
if (st_.as_int() == 1)
@@ -858,11 +825,11 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
const JSONNode &visibility = event_data["visibility"];
bool isVisible = visibility && visibility.as_bool();
- proto->debugLogA(" Requested chat switch to %s", isVisible ? "Online" : "Offline");
+ debugLogA(" Requested chat switch to %s", isVisible ? "Online" : "Offline");
// If actual status is not what server says, change it (handle also local away status, which means online)
- if (isVisible != (proto->m_iStatus != ID_STATUS_INVISIBLE))
- proto->SetStatus(isVisible ? ID_STATUS_ONLINE : ID_STATUS_INVISIBLE);
+ if (isVisible != (m_iStatus != ID_STATUS_INVISIBLE))
+ SetStatus(isVisible ? ID_STATUS_ONLINE : ID_STATUS_INVISIBLE);
}
}
else if (t == "chatproxy-presence") {
@@ -875,7 +842,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
for (auto itNodes = buddyList.begin(); itNodes != buddyList.end(); ++itNodes) {
std::string id = (*itNodes).name();
- MCONTACT hContact = proto->ContactIDToHContact(id);
+ MCONTACT hContact = ContactIDToHContact(id);
if (!hContact) {
// Facebook now sends info also about some nonfriends, so we just ignore status change of contacts we don't have in list
continue;
@@ -898,7 +865,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
else if (p == 2)
status = ID_STATUS_ONLINE;
- proto->setWord(hContact, "Status", status);
+ setWord(hContact, "Status", status);
}
// Last active time
@@ -906,13 +873,13 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
time_t last_active = utils::time::from_string(lat_.as_string());
if (last_active > 0)
- proto->setDword(hContact, "LastActiveTS", last_active);
+ setDword(hContact, "LastActiveTS", last_active);
else
- proto->delSetting(hContact, "LastActiveTS");
+ delSetting(hContact, "LastActiveTS");
// Set users inactive for too long as offline
if (last_active > 0 && last_active < offlineThreshold) {
- proto->setWord(hContact, "Status", ID_STATUS_OFFLINE);
+ setWord(hContact, "Status", ID_STATUS_OFFLINE);
}
}
@@ -933,7 +900,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
else {
client = FACEBOOK_CLIENT_OTHER;
}
- proto->setWString(hContact, "MirVer", client);
+ setWString(hContact, "MirVer", client);
}
}
}
@@ -949,7 +916,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
for (auto itNodes = overlay_.begin(); itNodes != overlay_.end(); ++itNodes) {
std::string id = (*itNodes).name();
- MCONTACT hContact = proto->ContactIDToHContact(id);
+ MCONTACT hContact = ContactIDToHContact(id);
if (!hContact) {
// Facebook now sends info also about some nonfriends, so we just ignore status change of contacts we don't have in list
continue;
@@ -987,17 +954,17 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
time_t last_active = utils::time::from_string(la_.as_string());
// we should set IdleTS only when contact is IDLE, or OFFLINE
- //if (proto->getDword(hContact, "IdleTS", 0) != last_active) {
+ //if (getDword(hContact, "IdleTS", 0) != last_active) {
// if (/*(fbu->idle || status == ID_STATUS_OFFLINE) &&*/ last_active > 0)
- // proto->setDword(hContact, "IdleTS", last_active);
+ // setDword(hContact, "IdleTS", last_active);
// else
- // proto->delSetting(hContact, "IdleTS");
+ // delSetting(hContact, "IdleTS");
//}
/*if (last_active > 0)
- proto->setDword(hContact, "LastActiveTS", last_active);
+ setDword(hContact, "LastActiveTS", last_active);
else
- proto->delSetting(hContact, "LastActiveTS");
+ delSetting(hContact, "LastActiveTS");
*/
// Set users inactive for too long as offline
@@ -1005,10 +972,10 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
status = ID_STATUS_OFFLINE;
}
else {
- proto->delSetting(hContact, "IdleTS");
+ delSetting(hContact, "IdleTS");
}
- proto->setWord(hContact, "Status", status);
+ setWord(hContact, "Status", status);
if (s_) {
// what to do with this?
@@ -1032,11 +999,11 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
client = FACEBOOK_CLIENT_OTHER;
}*/
- proto->setWString(hContact, "MirVer", client);
+ setWString(hContact, "MirVer", client);
}
}
} else if (t == "ticker_update:home") {
- if (!proto->getByte(FACEBOOK_KEY_EVENT_TICKER_ENABLE, DEFAULT_EVENT_TICKER_ENABLE))
+ if (!getByte(FACEBOOK_KEY_EVENT_TICKER_ENABLE, DEFAULT_EVENT_TICKER_ENABLE))
continue;
const JSONNode &actor_ = (*it)["actor"];
@@ -1053,15 +1020,15 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
std::string userId = actor_.as_string();
- MCONTACT hContact = proto->ContactIDToHContact(userId);
+ MCONTACT hContact = ContactIDToHContact(userId);
- proto->debugLogA("+++ Got ticker type='%s' class='%s'", story_type.c_str(), story_class.c_str());
+ debugLogA("+++ Got ticker type='%s' class='%s'", story_type.c_str(), story_class.c_str());
if (!text.empty())
- proto->NotifyEvent(proto->m_tszUserName, ptrW(mir_utf8decodeW(text.c_str())), hContact, EVENT_TICKER, &url);
+ NotifyEvent(m_tszUserName, ptrW(mir_utf8decodeW(text.c_str())), hContact, EVENT_TICKER, &url);
}
else if (t == "notifications_read" || t == "notifications_seen") { // revised 5.3.2017
- ScopedLock s(proto->facy.notifications_lock_);
+ ScopedLock s(facy.notifications_lock_);
const JSONNode &alerts = (*it)["alert_ids"];
@@ -1117,7 +1084,7 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_unread_threads(std::string *data, std::vector< std::string >* threads)
+int FacebookProto::ParseUnreadThreads(std::string *data, std::vector< std::string >* threads)
{
std::string jsonData = data->substr(9);
@@ -1144,7 +1111,7 @@ int facebook_json_parser::parse_unread_threads(std::string *data, std::vector< s
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_thread_messages(std::string *data, std::vector< facebook_message >* messages, bool unreadOnly)
+int FacebookProto::ParseThreadMessages(std::string *data, std::vector< facebook_message >* messages, bool unreadOnly)
{
std::string jsonData = data->substr(9);
@@ -1178,7 +1145,7 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector<
const JSONNode &log_data_ = (*it)["log_message_data"]; // additional data for this log message
if (!author_ || (!body_ && !log_body_) || !mid_ || (!thread_fbid_ && !thread_id_) || !timestamp_) {
- proto->debugLogA("parse_thread_messages: ignoring message (%s) - missing attribute", mid_.as_string().c_str());
+ debugLogA("ParseThreadMessages: ignoring message (%s) - missing attribute", mid_.as_string().c_str());
continue;
}
@@ -1193,14 +1160,14 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector<
author_id = author_id.substr(pos + 1);
// Process attachements and stickers
- parseAttachments(proto, &message_text, *it, other_user_fbid, true);
+ ParseAttachments(message_text, *it, other_user_fbid, true);
if (filtered_.as_bool() && message_text.empty())
message_text = Translate("This message is no longer available, because it was marked as abusive or spam.");
message_text = utils::text::trim(utils::text::slashu_to_utf8(message_text), true);
if (message_text.empty()) {
- proto->debugLogA("parse_thread_messages: ignoring message (%s) - empty message text", mid_.as_string().c_str());
+ debugLogA("ParseThreadMessages: ignoring message (%s) - empty message text", mid_.as_string().c_str());
continue;
}
@@ -1214,7 +1181,7 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector<
message.message_text = message_text;
message.time = utils::time::from_string(timestamp_.as_string());
message.message_id = message_id;
- message.isIncoming = (author_id != proto->facy.self_.user_id);
+ message.isIncoming = (author_id != facy.self_.user_id);
message.isUnread = isUnread;
message.isChat = other_user_fbid.empty();
@@ -1227,7 +1194,7 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector<
message.thread_id = thread_id;
}
- parseMessageType(proto, message, log_type_, log_body_, log_data_);
+ ParseMessageType(message, log_type_, log_body_, log_data_);
messages->push_back(message);
}
@@ -1235,7 +1202,7 @@ int facebook_json_parser::parse_thread_messages(std::string *data, std::vector<
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_history(std::string *data, std::vector< facebook_message >* messages, std::string *firstTimestamp)
+int FacebookProto::ParseHistory(std::string *data, std::vector< facebook_message >* messages, std::string *firstTimestamp)
{
std::string jsonData = data->substr(9);
@@ -1269,7 +1236,7 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook
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());
+ debugLogA("ParseHistory: ignoring message (%s) - missing attribute", mid.as_string().c_str());
continue;
}
@@ -1288,14 +1255,14 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook
author_id = author_id.substr(pos + 1);
// Process attachements and stickers
- parseAttachments(proto, &message_text, *it, other_user_id, true);
+ ParseAttachments(message_text, *it, other_user_id, true);
if (filtered.as_bool() && message_text.empty())
message_text = Translate("This message is no longer available, because it was marked as abusive or spam.");
message_text = utils::text::trim(utils::text::slashu_to_utf8(message_text), true);
if (message_text.empty()) {
- proto->debugLogA("parse_history: ignoring message (%s) - empty message text", mid.as_string().c_str());
+ debugLogA("ParseHistory: ignoring message (%s) - empty message text", mid.as_string().c_str());
continue;
}
@@ -1304,12 +1271,12 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook
message.time = utils::time::from_string(timestamp.as_string());
message.thread_id = thread_id;
message.message_id = message_id;
- message.isIncoming = (author_id != proto->facy.self_.user_id);
+ message.isIncoming = (author_id != facy.self_.user_id);
message.isUnread = is_unread.as_bool();
message.isChat = false;
message.user_id = other_user_id;
- parseMessageType(proto, message, log_type_, log_body_, log_data_);
+ ParseMessageType(message, log_type_, log_body_, log_data_);
messages->push_back(message);
}
@@ -1317,7 +1284,7 @@ int facebook_json_parser::parse_history(std::string *data, std::vector< facebook
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_thread_info(std::string *data, std::string* user_id)
+int FacebookProto::ParseThreadInfo(std::string *data, std::string* user_id)
{
std::string jsonData = data->substr(9);
@@ -1348,7 +1315,7 @@ int facebook_json_parser::parse_thread_info(std::string *data, std::string* user
}
-int facebook_json_parser::parse_user_info(std::string *data, facebook_user* fbu)
+int FacebookProto::ParseUserInfo(std::string *data, facebook_user* fbu)
{
std::string jsonData = data->substr(9);
@@ -1374,7 +1341,7 @@ int facebook_json_parser::parse_user_info(std::string *data, facebook_user* fbu)
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_chat_info(std::string *data, facebook_chatroom* fbc)
+int FacebookProto::ParseChatInfo(std::string *data, facebook_chatroom* fbc)
{
std::string jsonData = data->substr(9);
@@ -1432,7 +1399,7 @@ int facebook_json_parser::parse_chat_info(std::string *data, facebook_chatroom*
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_messages_count(std::string *data, int *messagesCount, int *unreadCount)
+int FacebookProto::ParseMessagesCount(std::string *data, int *messagesCount, int *unreadCount)
{
std::string jsonData = data->substr(9);
diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h
deleted file mode 100644
index d62666a66d..0000000000
--- a/protocols/FacebookRM/src/json.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-
-Facebook plugin for Miranda Instant Messenger
-_____________________________________________
-
-Copyright © 2009-11 Michal Zelinka, 2011-17 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
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#pragma once
-
-// Parser front-end
-
-#define lltoa _i64toa
-
-class facebook_json_parser
-{
-public:
- FacebookProto* proto;
- int parse_friends(std::string*, std::map< std::string, facebook_user* >*, bool);
- int parse_notifications(std::string*, std::map< std::string, facebook_notification* >*);
- int parse_messages(std::string*, std::vector< facebook_message >*, std::map< std::string, facebook_notification* >*);
- int parse_unread_threads(std::string*, std::vector< std::string >*);
- int parse_thread_messages(std::string*, std::vector< facebook_message >*, bool unreadOnly);
- int parse_history(std::string*, std::vector< facebook_message >*, std::string *);
- int parse_thread_info(std::string* data, std::string* user_id);
- int parse_user_info(std::string* data, facebook_user* fbu);
- int parse_chat_info(std::string* data, facebook_chatroom* fbc);
- int parse_chat_participant_names(std::string *data, std::map<std::string, chatroom_participant>* participants);
- int parse_messages_count(std::string *data, int *messagesCount, int *unreadCount);
-
- facebook_json_parser(FacebookProto* proto)
- {
- this->proto = proto;
- }
-};
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp
index fb02f5c868..eb856d06f3 100644
--- a/protocols/FacebookRM/src/process.cpp
+++ b/protocols/FacebookRM/src/process.cpp
@@ -62,7 +62,7 @@ void FacebookProto::ProcessFriendList(void*)
bool loadAllContacts = getBool(FACEBOOK_KEY_LOAD_ALL_CONTACTS, DEFAULT_LOAD_ALL_CONTACTS);
bool pagesAlwaysOnline = getBool(FACEBOOK_KEY_PAGES_ALWAYS_ONLINE, DEFAULT_PAGES_ALWAYS_ONLINE);
- facebook_json_parser(this).parse_friends(&resp.data, &friends, loadAllContacts);
+ ParseFriends(&resp.data, &friends, loadAllContacts);
// Check and update old contacts
for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
@@ -193,7 +193,7 @@ void FacebookProto::ProcessUnreadMessages(void*)
try {
std::vector<std::string> threads;
- facebook_json_parser(this).parse_unread_threads(&resp.data, &threads);
+ ParseUnreadThreads(&resp.data, &threads);
ForkThread(&FacebookProto::ProcessUnreadMessage, new std::vector<std::string>(threads));
@@ -243,7 +243,7 @@ void FacebookProto::ProcessUnreadMessage(void *pParam)
if (resp.code == HTTP_CODE_OK) {
try {
std::vector<facebook_message> messages;
- facebook_json_parser(this).parse_thread_messages(&resp.data, &messages, false);
+ ParseThreadMessages(&resp.data, &messages, false);
ReceiveMessages(messages, true);
debugLogA("*** Unread messages processed");
@@ -308,7 +308,7 @@ void FacebookProto::LoadLastMessages(void *pParam)
try {
std::vector<facebook_message> messages;
- facebook_json_parser(this).parse_thread_messages(&resp.data, &messages, false);
+ ParseThreadMessages(&resp.data, &messages, false);
ReceiveMessages(messages, true);
debugLogA("*** Thread messages processed");
@@ -365,9 +365,7 @@ void FacebookProto::LoadHistory(void *pParam)
int messagesCount = -1;
int unreadCount = -1;
- facebook_json_parser* p = new facebook_json_parser(this);
- if (p->parse_messages_count(&resp.data, &messagesCount, &unreadCount) == EXIT_FAILURE) {
- delete p;
+ if (ParseMessagesCount(&resp.data, &messagesCount, &unreadCount) == EXIT_FAILURE) {
facy.handle_error("LoadHistory");
return;
}
@@ -411,7 +409,7 @@ void FacebookProto::LoadHistory(void *pParam)
try {
messages.clear();
- p->parse_history(&resp.data, &messages, &firstTimestamp);
+ ParseHistory(&resp.data, &messages, &firstTimestamp);
// Receive messages
std::string previousFirstMessageId = firstMessageId;
@@ -484,8 +482,6 @@ void FacebookProto::LoadHistory(void *pParam)
}
}
- delete p;
-
facy.handle_success("LoadHistory");
// Enable marking messages as read for this contact
@@ -972,7 +968,7 @@ void FacebookProto::ProcessMessages(void* data)
try {
std::vector<facebook_message> messages;
- facebook_json_parser(this).parse_messages(resp, &messages, &facy.notifications);
+ ParseMessages(resp, &messages, &facy.notifications);
ReceiveMessages(messages);
@@ -1031,7 +1027,7 @@ void FacebookProto::ProcessNotifications(void *p)
try {
size_t numNotifications = facy.notifications.size();
- facebook_json_parser(this).parse_notifications(&resp.data, &facy.notifications);
+ ParseNotifications(&resp.data, &facy.notifications);
if (manuallyTriggered) {
numNotifications = facy.notifications.size() - numNotifications;
diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h
index dff762bfaa..f31981a500 100644
--- a/protocols/FacebookRM/src/proto.h
+++ b/protocols/FacebookRM/src/proto.h
@@ -26,6 +26,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
class FacebookProto : public PROTO<FacebookProto>
{
+ bool IgnoreDuplicates(const std::string &mid);
+ bool ProcessSpecialMessage(std::vector<facebook_message>* messages, const JSONNode &meta_, MessageType messageType, const std::string &messageData = "");
+
+ void ParseAttachments(std::string &message_text, const JSONNode &delta_, std::string other_user_fbid, bool legacy);
+ void ParseMessageType(facebook_message &message, const JSONNode &log_type_, const JSONNode &log_body_, const JSONNode &log_data_);
+ bool ParseMessageMetadata(facebook_message &message, const JSONNode &meta_);
+
+ int ParseChatInfo(std::string* data, facebook_chatroom* fbc);
+ int ParseChatParticipants(std::string *data, std::map<std::string, chatroom_participant>* participants);
+ int ParseFriends(std::string*, std::map< std::string, facebook_user* >*, bool);
+ int ParseHistory(std::string*, std::vector< facebook_message >*, std::string *);
+ int ParseMessages(std::string*, std::vector< facebook_message >*, std::map< std::string, facebook_notification* >*);
+ int ParseMessagesCount(std::string *data, int *messagesCount, int *unreadCount);
+ int ParseNotifications(std::string*, std::map< std::string, facebook_notification* >*);
+ int ParseThreadInfo(std::string* data, std::string* user_id);
+ int ParseThreadMessages(std::string*, std::vector< facebook_message >*, bool unreadOnly);
+ int ParseUnreadThreads(std::string*, std::vector< std::string >*);
+ int ParseUserInfo(std::string* data, facebook_user* fbu);
+
public:
FacebookProto(const char *proto_name, const wchar_t *username);
~FacebookProto();
@@ -48,7 +67,6 @@ public:
inline bool isInvisible()
{
return m_invisible;
- //return (m_iStatus == ID_STATUS_INVISIBLE);
}
inline int IdleSeconds()
diff --git a/protocols/FacebookRM/src/requests/contacts.h b/protocols/FacebookRM/src/requests/contacts.h
index 8fa60fced8..960fb269b3 100644
--- a/protocols/FacebookRM/src/requests/contacts.h
+++ b/protocols/FacebookRM/src/requests/contacts.h
@@ -36,7 +36,7 @@ public:
// getting info about particular friend
-// revised 17.8.2016
+// revised 3.12.2017
class UserInfoRequest : public HttpRequest
{
public:
@@ -60,7 +60,11 @@ public:
<< CHAR_VALUE("__rev", fc->__rev())
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
- << "__be=-1";
+ << "__be=1"
+ << "jazoest="
+ << "__spin_r="
+ << "__spin_b="
+ << "__spin_t=";
}
};
diff --git a/protocols/FacebookRM/src/requests/history.h b/protocols/FacebookRM/src/requests/history.h
index 9ac3d52168..b7cf3f42c1 100644
--- a/protocols/FacebookRM/src/requests/history.h
+++ b/protocols/FacebookRM/src/requests/history.h
@@ -24,20 +24,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define _FACEBOOK_REQUEST_HISTORY_H_
// getting thread info and messages
-// revised 17.8.2016
+// revised 3.12.2017
class ThreadInfoRequest : public HttpRequest
{
public:
// Request only messages history
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id, int offset, const char *timestamp, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
{
- Url
- << "dpr=1";
-
setCommonBody(fc);
- const char *type = isChat ? "thread_fbids" : "user_ids";
+ // FIXME: FB removed /ajax/mercury/thread_info requests and now all messaging stuff does through /api/graphqlbatch/ - all loading of threads, (unread) messages, list of contacts in groupchat, etc.
+ // All these request must be rewritten to the new request. Preparation is below but unfinished.
+
+ //const char *type = isChat ? "thread_fbids" : "user_ids";
std::string id_ = id; // FIXME: Rewrite this without std::string...
if (isChat) {
// NOTE: Remove "id." prefix as here we need to give threadFbId and not threadId
@@ -46,6 +46,34 @@ public:
}
ptrA idEncoded(mir_urlEncode(id_.c_str()));
+
+ JSONNode root, o0, query_params;
+
+ int before = -1;
+
+ query_params
+ << CHAR_PARAM("id", id_.c_str()) // TODO: Do I have to encode the id? And remove that first "id." at the begin as we do above?
+ << INT_PARAM("message_limit", limit)
+ << INT_PARAM("load_messages", 1)
+ << BOOL_PARAM("load_read_receipts", false);
+
+ if (before != -1)
+ query_params << INT_PARAM("before", before);
+ else
+ query_params << NULL_PARAM("before");
+
+ o0 << CHAR_PARAM("doc_id", id) << JSON_PARAM("query_params", query_params);
+
+ root << JSON_PARAM("o0", o0);
+
+ Body
+ << "batch_name=MessengerGraphQLThreadFetcherRe"
+ << CHAR_VALUE("queries", root.write().c_str());
+
+ // example request data we need to send: { "o0":{"doc_id":"456789456123","query_params" : {"id":"123456789","message_limit" : 20,"load_messages" : 1,"load_read_receipts" : false,"before" : null}} }
+
+
+ /*
//if (loadMessages) {
// Grrr, offset doesn't work at all, we need to use timestamps to get back in history...
// And we don't know, what's timestamp of first message, so we need to get from latest to oldest
@@ -55,7 +83,7 @@ public:
<< CMStringA(::FORMAT, "%s[offset]=%i", begin.c_str(), offset).c_str()
<< CMStringA(::FORMAT, "%s[timestamp]=%s", begin.c_str(), timestamp).c_str()
<< CMStringA(::FORMAT, "%s[limit]=%i", begin.c_str(), limit).c_str();
- //}
+ //}*/
/*if (loadThreadInfo) {
data += "&threads[" + type + "][0]=" + idEncoded;
@@ -64,11 +92,8 @@ public:
// Request only thread info // TODO: Make it array of ids
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
{
- Url
- << "dpr=1";
-
setCommonBody(fc);
const char *type = isChat ? "thread_fbids" : "user_ids";
@@ -86,11 +111,8 @@ public:
// Request both thread info and messages for single contact/chat
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
{
- Url
- << "dpr=1";
-
setCommonBody(fc);
const char *type = isChat ? "thread_fbids" : "user_ids";
@@ -116,11 +138,8 @@ public:
// Request both thread info and messages for more threads
ThreadInfoRequest(facebook_client *fc, const LIST<char> &ids, int offset, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
{
- Url
- << "dpr=1";
-
setCommonBody(fc);
for (int i = 0; i < ids.getCount(); i++) {
@@ -146,7 +165,6 @@ private:
void setCommonBody(facebook_client *fc)
{
Body
- << "client=mercury"
<< CHAR_VALUE("__user", fc->self_.user_id.c_str())
<< CHAR_VALUE("__dyn", fc->__dyn())
<< CHAR_VALUE("__req", fc->__req())
@@ -155,7 +173,11 @@ private:
<< CHAR_VALUE("ttstamp", fc->ttstamp_.c_str())
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
- << "__be=-1";
+ << "__be=1"
+ << "jazoest="
+ << "__spin_r="
+ << "__spin_b="
+ << "__spin_t=";
}
};
@@ -183,6 +205,8 @@ public:
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
<< "__be=-1";
+
+ //queries={"o0":{"doc_id":"2003371749678240","query_params":{"limit":99,"before":null,"tags":["PENDING","unread"],"includeDeliveryReceipts":true,"includeSeqID":false}}}
}
};
diff --git a/protocols/FacebookRM/src/stdafx.h b/protocols/FacebookRM/src/stdafx.h
index 0e466e9715..007711c0c4 100644
--- a/protocols/FacebookRM/src/stdafx.h
+++ b/protocols/FacebookRM/src/stdafx.h
@@ -74,7 +74,6 @@ class FacebookProto;
#include "list.hpp"
#include "client.h"
#include "proto.h"
-#include "json.h"
#include "db.h"
#include "dialogs.h"
#include "theme.h"
diff --git a/protocols/FacebookRM/src/version.h b/protocols/FacebookRM/src/version.h
index 08b34f8856..943d643eb5 100644
--- a/protocols/FacebookRM/src/version.h
+++ b/protocols/FacebookRM/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
-#define __MINOR_VERSION 3
-#define __RELEASE_NUM 3
-#define __BUILD_NUM 2
+#define __MINOR_VERSION 4
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
#include <stdver.h>