summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/FacebookRM/src/communication.cpp22
-rw-r--r--protocols/FacebookRM/src/constants.h1
-rw-r--r--protocols/FacebookRM/src/entities.h5
-rw-r--r--protocols/FacebookRM/src/json.cpp255
-rw-r--r--protocols/FacebookRM/src/json.h2
-rw-r--r--protocols/FacebookRM/src/process.cpp233
6 files changed, 337 insertions, 181 deletions
diff --git a/protocols/FacebookRM/src/communication.cpp b/protocols/FacebookRM/src/communication.cpp
index ab54ee1f9d..ae677ed30e 100644
--- a/protocols/FacebookRM/src/communication.cpp
+++ b/protocols/FacebookRM/src/communication.cpp
@@ -250,7 +250,6 @@ DWORD facebook_client::choose_security_level(RequestType request_type)
// case REQUEST_MARK_READ:
// case REQUEST_NOTIFICATIONS_READ:
// case REQUEST_UNREAD_THREADS:
-// case REQUEST_UNREAD_MESSAGES:
// case REQUEST_TYPING_SEND:
default:
return (DWORD)0;
@@ -282,6 +281,7 @@ int facebook_client::choose_method(RequestType request_type)
case REQUEST_REQUEST_FRIEND:
case REQUEST_APPROVE_FRIEND:
case REQUEST_CANCEL_REQUEST:
+ case REQUEST_UNREAD_THREADS:
return REQUEST_POST;
// case REQUEST_HOME:
@@ -295,8 +295,6 @@ int facebook_client::choose_method(RequestType request_type)
// case REQUEST_USER_INFO:
// case REQUEST_LOAD_REQUESTS:
// case REQUEST_SEARCH:
-// case REQUEST_UNREAD_THREADS:
-// case REQUEST_UNREAD_MESSAGES:
default:
return REQUEST_GET;
}
@@ -330,8 +328,6 @@ std::string facebook_client::choose_server(RequestType request_type, std::string
case REQUEST_APPROVE_FRIEND:
case REQUEST_LOAD_REQUESTS:
case REQUEST_SEARCH:
- case REQUEST_UNREAD_THREADS:
- case REQUEST_UNREAD_MESSAGES:
case REQUEST_USER_INFO:
return FACEBOOK_SERVER_MOBILE;
@@ -359,6 +355,7 @@ std::string facebook_client::choose_server(RequestType request_type, std::string
// case REQUEST_DELETE_FRIEND:
// case REQUEST_REQUEST_FRIEND:
// case REQUEST_CANCEL_REQUEST:
+// case REQUEST_UNREAD_THREADS:
default:
return FACEBOOK_SERVER_REGULAR;
}
@@ -418,20 +415,7 @@ std::string facebook_client::choose_action(RequestType request_type, std::string
case REQUEST_UNREAD_THREADS:
{
- std::string action = "/messages/?folder=unread";
- if (get_data != NULL) {
- action += *get_data;
- }
- return action;
- }
-
- case REQUEST_UNREAD_MESSAGES:
- {
- std::string action = "/messages/read/?";
- if (get_data != NULL) {
- action += *get_data;
- }
- return action;
+ return "/ajax/mercury/unread_threads.php?__a=1";
}
case REQUEST_DELETE_FRIEND:
diff --git a/protocols/FacebookRM/src/constants.h b/protocols/FacebookRM/src/constants.h
index 7334ddf262..628e5e6895 100644
--- a/protocols/FacebookRM/src/constants.h
+++ b/protocols/FacebookRM/src/constants.h
@@ -117,7 +117,6 @@ enum RequestType {
REQUEST_THREAD_INFO, // getting thread info
REQUEST_UNREAD_THREADS, // getting unread threads
- REQUEST_UNREAD_MESSAGES, // getting unread messages
REQUEST_ASYNC, // marking messages read and getting other things
REQUEST_MARK_READ, // marking messages read (new)
};
diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h
index b80a75da1b..d1f1a48dcc 100644
--- a/protocols/FacebookRM/src/entities.h
+++ b/protocols/FacebookRM/src/entities.h
@@ -66,11 +66,14 @@ struct facebook_message
std::string sender_name;
std::string message_id;
DWORD time;
+ bool isIncoming;
+ bool isUnread;
facebook_message()
{
this->user_id = this->message_text = this->sender_name = this->message_id = "";
this->time = 0;
+ this->isUnread = this->isIncoming = true;
}
facebook_message(const facebook_message& msg)
@@ -80,6 +83,8 @@ struct facebook_message
this->sender_name = msg.sender_name;
this->message_id = msg.message_id;
this->time = msg.time;
+ this->isIncoming = msg.isIncoming;
+ this->isUnread = msg.isUnread;
}
};
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index 9ce8d6c302..f3c75c4b40 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -231,7 +231,8 @@ int facebook_json_parser::parse_notifications(void *data, std::vector< facebook_
return EXIT_SUCCESS;
}
-bool ignore_duplicits(FacebookProto *proto, std::string mid, std::string text) {
+bool ignore_duplicits(FacebookProto *proto, std::string mid, std::string text)
+{
std::map<std::string, bool>::iterator it = proto->facy.messages_ignore.find(mid);
if (it != proto->facy.messages_ignore.end()) {
std::string msg = "????? Ignoring duplicit/sent message\n" + text;
@@ -246,6 +247,59 @@ bool ignore_duplicits(FacebookProto *proto, std::string mid, std::string text) {
return false;
}
+void parseAttachments(FacebookProto *proto, std::string *message_text, JSONNODE *it)
+{
+ // Process attachements and stickers
+ JSONNODE *has_attachment = json_get(it, "has_attachment");
+ if (has_attachment != NULL && json_as_bool(has_attachment)) {
+ JSONNODE *admin_snippet = json_get(it, "admin_snippet");
+ if (admin_snippet != NULL) {
+ // Append attachements
+ std::string attachments_text = "";
+ JSONNODE *attachments = json_get(it, "attachments");
+ for (unsigned int j = 0; j < json_size(attachments); j++) {
+ JSONNODE *itAttachment = json_at(attachments, j);
+
+ // TODO: behave different for stickers and classic attachements?
+ // JSONNODE *attach_type = json_get(itAttachment, "attach_type"); // "sticker", "photo", "file"
+
+ JSONNODE *name = json_get(itAttachment, "name");
+ JSONNODE *url = json_get(itAttachment, "url");
+ if (url != NULL) {
+ std::string link = json_as_string(url);
+
+ if (link.find("/ajax/mercury/attachments/photo/view/") != std::string::npos)
+ // fix photo url
+ link = utils::url::decode(utils::text::source_get_value(&link, 2, "?uri=", "&"));
+ else if (link.find("/") == 0) {
+ // make absolute url
+ bool useHttps = proto->getByte(FACEBOOK_KEY_FORCE_HTTPS, 1) > 0;
+ link = (useHttps ? HTTP_PROTO_SECURE : HTTP_PROTO_REGULAR) + std::string(FACEBOOK_SERVER_REGULAR) + link;
+ }
+
+ if (!link.empty()) {
+ std::string filename;
+ if (name != NULL)
+ filename = json_as_string(name);
+ if (filename == "null")
+ filename.clear();
+
+ attachments_text += "\n" + (!filename.empty() ? "<" + filename + "> " : "") + link + "\n";
+ }
+ }
+ }
+
+ if (!attachments_text.empty()) {
+ // TODO: have this as extra event, not replace or append message content
+ if (!message_text->empty())
+ *message_text += "\n\n";
+ *message_text += json_as_string(admin_snippet);
+ *message_text += attachments_text;
+ }
+ }
+ }
+}
+
int facebook_json_parser::parse_messages(void* data, std::vector< facebook_message* >* messages, std::vector< facebook_notification* >* notifications)
{
std::string jsonData = static_cast< std::string* >(data)->substr(9);
@@ -316,24 +370,17 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa
if (to == NULL)
continue;
- // TODO: put also outgoing messages into messages array and process it elsewhere
- HANDLE hContact = proto->ContactIDToHContact(json_as_string(to));
- if (!hContact) // TODO: add this contact?
- continue;
-
- DBEVENTINFO dbei = {0};
- dbei.cbSize = sizeof(dbei);
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.flags = DBEF_SENT | DBEF_UTF;
- dbei.szModule = proto->m_szModuleName;
-
- bool local_time = proto->getByte(FACEBOOK_KEY_LOCAL_TIMESTAMP, 0) != 0;
- dbei.timestamp = local_time ? ::time(NULL) : utils::time::fix_timestamp(json_as_float(time));
+ JSONNODE *to_name = json_get(it, "to_name");
- dbei.cbBlob = (DWORD)message_text.length() + 1;
- dbei.pBlob = (PBYTE)message_text.c_str();
- db_event_add(hContact, &dbei);
+ 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(to_name)));
+ message->time = utils::time::fix_timestamp(json_as_float(time));
+ message->user_id = json_as_string(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") {
// we use this only for incomming messages (and getting seen info)
@@ -380,50 +427,7 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa
std::string message_text = json_as_string(body);
// Process attachements and stickers
- JSONNODE *has_attachment = json_get(msg, "has_attachment");
- if (has_attachment != NULL && json_as_bool(has_attachment)) {
- JSONNODE *admin_snippet = json_get(msg, "admin_snippet");
- if (admin_snippet != NULL) {
- // TODO: have this as extra event, not replace or append message content
- if (!message_text.empty())
- message_text += "\n\n";
- message_text += json_as_string(admin_snippet);
-
- // Append attachements
- JSONNODE *attachments = json_get(msg, "attachments");
- for (unsigned int j = 0; j < json_size(attachments); j++) {
- JSONNODE *itAttachment = json_at(attachments, j);
-
- // TODO: behave different for stickers and classic attachements?
- // JSONNODE *attach_type = json_get(itAttachment, "attach_type"); // "sticker", "photo", "file"
-
- JSONNODE *name = json_get(itAttachment, "name");
- JSONNODE *url = json_get(itAttachment, "url");
- if (url != NULL) {
- std::string link = json_as_string(url);
-
- if (link.find("/ajax/mercury/attachments/photo/view/") != std::string::npos)
- // fix photo url
- link = utils::url::decode(utils::text::source_get_value(&link, 2, "?uri=", "&"));
- else if (link.find("/") == 0) {
- // make absolute url
- bool useHttps = proto->getByte(FACEBOOK_KEY_FORCE_HTTPS, 1) > 0;
- link = (useHttps ? HTTP_PROTO_SECURE : HTTP_PROTO_REGULAR) + std::string(FACEBOOK_SERVER_REGULAR) + link;
- }
-
- if (!link.empty()) {
- std::string filename;
- if (name != NULL)
- filename = json_as_string(name);
- if (filename == "null")
- filename.clear();
-
- message_text += "\n" + (!filename.empty() ? "<" + filename + "> " : "") + link + "\n";
- }
- }
- }
- }
- }
+ parseAttachments(proto, &message_text, it);
// Ignore messages from myself, as there is no id of recipient
if (id == proto->facy.self_.user_id)
@@ -588,3 +592,132 @@ int facebook_json_parser::parse_messages(void* data, std::vector< facebook_messa
json_delete(root);
return EXIT_SUCCESS;
}
+
+int facebook_json_parser::parse_unread_threads(void* data, std::vector< std::string >* threads)
+{
+ std::string jsonData = static_cast< std::string* >(data)->substr(9);
+
+ JSONNODE *root = json_parse(jsonData.c_str());
+ if (root == NULL)
+ return EXIT_FAILURE;
+
+ JSONNODE *payload = json_get(root, "payload");
+ if (payload == NULL) {
+ json_delete(root);
+ return EXIT_FAILURE;
+ }
+
+ JSONNODE *unread_threads = json_get(payload, "unread_thread_ids");
+ if (unread_threads == NULL) {
+ json_delete(root);
+ return EXIT_FAILURE;
+ }
+
+ for (unsigned int i = 0; i < json_size(unread_threads); i++) {
+ JSONNODE *it = json_at(unread_threads, i);
+
+ JSONNODE *folder = json_get(it, "folder");
+ JSONNODE *thread_ids = json_get(it, "thread_ids");
+
+ for (unsigned int j = 0; j < json_size(thread_ids); j++) {
+ JSONNODE *id = json_at(thread_ids, j);
+ threads->push_back(json_as_string(id));
+ }
+ }
+
+ json_delete(root);
+ return EXIT_SUCCESS;
+}
+
+int facebook_json_parser::parse_thread_messages(void* data, std::vector< facebook_message* >* messages, bool unreadOnly, int limit)
+{
+ std::string jsonData = static_cast< std::string* >(data)->substr(9);
+
+ JSONNODE *root = json_parse(jsonData.c_str());
+ if (root == NULL)
+ return EXIT_FAILURE;
+
+ JSONNODE *payload = json_get(root, "payload");
+ if (payload == NULL) {
+ json_delete(root);
+ return EXIT_FAILURE;
+ }
+
+ JSONNODE *actions = json_get(payload, "actions");
+ JSONNODE *threads = json_get(payload, "threads");
+ if (actions == NULL || threads == NULL) {
+ json_delete(root);
+ return EXIT_FAILURE;
+ }
+
+ std::map<std::string, std::string> 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 *unread_count = json_get(it, "unread_count"); // TODO: use it to check against number of loaded messages... but how?
+
+ if (canonical == NULL || thread_id == NULL)
+ continue;
+
+ std::string id = json_as_string(canonical);
+ if (id == "null")
+ continue;
+
+ std::string tid = json_as_string(thread_id);
+ thread_ids.insert(std::make_pair(tid, id));
+ }
+
+ for (unsigned int i = 0; i < json_size(actions); i++) {
+ JSONNODE *it = json_at(actions, i);
+
+ JSONNODE *author = json_get(it, "author");
+ JSONNODE *author_email = json_get(it, "author_email");
+ JSONNODE *body = json_get(it, "body");
+ JSONNODE *tid = json_get(it, "thread_id");
+ JSONNODE *mid = json_get(it, "message_id");
+ 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<std::string, std::string>::iterator iter = thread_ids.find(json_as_string(tid));
+ if (iter == thread_ids.end())
+ continue; // not found or ignored multi user thread
+
+ std::string user_id = iter->second;
+ std::string message_id = json_as_string(mid);
+ std::string message_text = json_as_string(body);
+ std::string author_id = json_as_string(author);
+ std::string::size_type pos = author_id.find(":");
+ if (pos != std::string::npos)
+ author_id = author_id.substr(pos+1);
+
+ // Process attachements and stickers
+ parseAttachments(proto, &message_text, it);
+
+ message_text = utils::text::trim(utils::text::special_expressions_decode(utils::text::slashu_to_utf8(message_text)), true);
+ if (message_text.empty())
+ continue;
+
+ facebook_message* message = new facebook_message();
+ message->message_text = message_text;
+ if (author_email != NULL)
+ message->sender_name = json_as_string(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);
+
+ messages->push_back(message);
+ }
+
+ json_delete(root);
+ return EXIT_SUCCESS;
+}
diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h
index de16fe76db..8294c2ec2e 100644
--- a/protocols/FacebookRM/src/json.h
+++ b/protocols/FacebookRM/src/json.h
@@ -34,6 +34,8 @@ public:
int parse_friends(void*, std::map< std::string, facebook_user* >*);
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);
facebook_json_parser(FacebookProto* proto)
{
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp
index 64b85103ac..bb8b95f3ea 100644
--- a/protocols/FacebookRM/src/process.cpp
+++ b/protocols/FacebookRM/src/process.cpp
@@ -263,129 +263,150 @@ void FacebookProto::ProcessFriendList(void* data)
void FacebookProto::ProcessUnreadMessages(void*)
{
- facy.handle_entry("messages");
+ facy.handle_entry("ProcessUnreadMessages");
- int count = 0;
- std::string page;
+ bool loadOther = true; // TODO: db setting? or use everytime?
- while (count < 30) // allow max 30 unread threads to be parsed
- {
- std::string get_data = "&page=" + page;
+ std::string data = "folders[0]=inbox";
+ if (loadOther)
+ data += "&folders[1]=other";
+ data += "&client=mercury";
+ data += "__user=" + facy.self_.user_id;
+ data += "&fb_dtsg=" + (facy.dtsg_.length() ? facy.dtsg_ : "0");
+ data += "&__a=1&__dyn=&__req=&ttstamp=0";
- http::response resp = facy.flap(REQUEST_UNREAD_THREADS, NULL, &get_data);
+ http::response resp = facy.flap(REQUEST_UNREAD_THREADS, &data);
+ facy.validate_response(&resp);
- // Process result data
- facy.validate_response(&resp);
+ if (resp.code == HTTP_CODE_OK) {
+
+ CODE_BLOCK_TRY
+
+ std::vector<std::string> threads;
- if (resp.code == HTTP_CODE_OK)
- {
- std::string items = utils::text::source_get_value(&resp.data, 2, "<div id=\"threadlist_rows", "</body>");
+ facebook_json_parser* p = new facebook_json_parser(this);
+ p->parse_unread_threads(&resp.data, &threads);
+ delete p;
- std::string::size_type pos = 0;
- std::string::size_type pos2 = 0;
+ ForkThread(&FacebookProto::ProcessUnreadMessage, new std::vector<std::string>(threads));
- while ((pos = items.find("id=\"threadlist_row_", pos)) != std::string::npos) {
- std::string item = items.substr(pos, items.find("</div>", pos) - pos);
- pos++; count++;
+ LOG("***** Unread threads list processed");
- std::string tid = utils::text::source_get_value2(&item, "?tid=", "&\"");
- if (tid.empty())
- continue;
+ CODE_BLOCK_CATCH
- ForkThread(&FacebookProto::ProcessUnreadMessage, new std::string(tid));
- }
-
- page = utils::text::source_get_value(&items, 3, "id=\"see_older_threads\"", "page=", "&");
- if (page.empty())
- break; // No more results
- }
- }
+ LOG("***** Error processing unread threads list: %s", e.what());
+ CODE_BLOCK_END
+
+ facy.handle_success("ProcessUnreadMessages");
+ } else {
+ facy.handle_error("ProcessUnreadMessages");
+ }
}
-void FacebookProto::ProcessUnreadMessage(void *tid_data)
+void FacebookProto::ProcessUnreadMessage(void *p)
{
- if (tid_data == NULL)
+ if (p == NULL)
return;
- // TODO: get them from /ajax/mercury/thread_info.php
-
- std::string get_data = "tid=" + *(std::string*)tid_data;
- delete (std::string*)tid_data;
-
- http::response resp = facy.flap(REQUEST_UNREAD_MESSAGES, NULL, &get_data);
- facy.validate_response(&resp);
-
- if (resp.code != HTTP_CODE_OK) {
- LOG(" !! !! Error when getting messages list");
- return;
- }
+ facy.handle_entry("ProcessUnreadMessage");
- if (resp.data.find("<option value=\"leave_conversation\">") != std::string::npos) {
- LOG(" !! !! This is multi user chat");
- return;
- }
+ std::vector<std::string> threads = *(std::vector<std::string>*)p;
+ delete (std::vector<std::string>*)p;
- std::string messageslist = utils::text::source_get_value(&resp.data, 2, "id=\"messageGroup\">", "</form>");
+ int offset = 0;
+ int limit = 21;
- facebook_user fbu;
- HANDLE hContact = NULL;
+ bool local_timestamp = getBool(FACEBOOK_KEY_LOCAL_TIMESTAMP, 0);
- std::string::size_type pos = 0, pos2 = 0;
- while ((pos2 = messageslist.find("class=\"acw apl abt", pos2)) != std::string::npos) {
- pos2 += 19;
- std::string group = messageslist.substr(pos2, messageslist.find("class=\"actions ", pos2) - pos2);
+ http::response resp;
- if (group.find("has_attachment&quot;:true") != std::string::npos) {
- // TODO: do something different for attachements? (inspiration in revision <5236)
+ while (!threads.empty()) {
+ std::string data = "client=mercury";
+ data += "&__user=" + facy.self_.user_id;
+ data += "&fb_dtsg=" + (facy.dtsg_.length() ? facy.dtsg_ : "0");
+ data += "&__a=1&__dyn=&__req=&ttstamp=0";
+
+ for (std::vector<std::string>::size_type i = 0; i < threads.size(); i++) {
+ // request messages from thread
+ data += "&messages[thread_ids][" + threads[i];
+ data += "][offset]=" + utils::conversion::to_string(&offset, UTILS_CONV_SIGNED_NUMBER);
+ data += "&messages[thread_ids][" + threads[i];
+ data += "][limit]=" + utils::conversion::to_string(&limit, UTILS_CONV_SIGNED_NUMBER);
+
+ // request info about thread
+ data += "&threads[thread_ids][" + utils::conversion::to_string(&i, UTILS_CONV_UNSIGNED_NUMBER);
+ data += "]=" + threads[i];
}
- while ((pos = group.find("<div data-store=", pos)) != std::string::npos) {
- std::string message = group.substr(pos, group.find("</div>", pos) - pos);
- pos++;
-
- std::string author = utils::text::source_get_value2(&message, "author&quot;:", ",}");
-
- // Ignore our messages
- if (author == facy.self_.user_id)
- continue;
+ resp = facy.flap(REQUEST_THREAD_INFO, &data);
+ facy.validate_response(&resp);
- // Get/create contact
- if (hContact == NULL) {
- fbu.user_id = author;
- fbu.real_name = utils::text::slashu_to_utf8(utils::text::source_get_value(&group, 2, "name&quot;:&quot;", "&quot;"));
- hContact = AddToContactList(&fbu, CONTACT_NONE);
- // TODO: if contact is newly added, get his user info
- // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages?
+ if (resp.code == HTTP_CODE_OK) {
+
+ CODE_BLOCK_TRY
+
+ std::vector<facebook_message*> messages;
+
+ facebook_json_parser* p = new facebook_json_parser(this);
+ p->parse_thread_messages(&resp.data, &messages, true, limit);
+ delete p;
+
+ for(std::vector<facebook_message*>::size_type i = 0; i < messages.size(); i++) {
+ 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;
+ fbu.real_name = messages[i]->sender_name;
+
+ // TODO: optimize this?
+ HANDLE hContact = AddToContactList(&fbu, CONTACT_NONE);
+ setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str());
+
+ // TODO: if contact is newly added, get his user info
+ // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages?
+
+ ParseSmileys(messages[i]->message_text, hContact);
+
+ if (messages[i]->isIncoming) {
+ PROTORECVEVENT recv = {0};
+ recv.flags = PREF_UTF;
+ recv.szMessage = const_cast<char*>(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);
+ }
+ }
+ delete messages[i];
}
+ messages.clear();
- DWORD timestamp = utils::conversion::to_timestamp(utils::text::source_get_value2(&message, "timestamp&quot;:", ",}"));
- std::string text = utils::text::source_get_value(&message, 2, "<span>", "</span>");
+ LOG("***** Unread messages processed");
- text = utils::text::trim(utils::text::special_expressions_decode(utils::text::remove_html(text)));
- // TODO: fix smileys in text
- /*
- <img src="https://fbstatic-a.akamaihd.net/rsrc.php/v2/yH/r/SOe5wIZyutW.png" width="16" height="16" class="img"/>
+ CODE_BLOCK_CATCH
- "yH/r/viyyiQhRqLr.png" -> :-P
- "yo/r/X8YPpi6kcyo.png" -> :-)
- "yH/r/SOe5wIZyutW.png" -> :-D
- ...
- */
+ LOG("***** Error processing unread messages: %s", e.what());
- if (text.empty() || hContact == NULL)
- continue;
-
- LOG("Got unread message: \"%s\"", text.c_str());
-
- ParseSmileys(text, hContact);
-
- PROTORECVEVENT recv = {0};
- recv.flags = PREF_UTF;
- recv.szMessage = const_cast<char*>(text.c_str());
- recv.timestamp = timestamp;
- ProtoChainRecvMsg(hContact, &recv);
+ CODE_BLOCK_END
+
+ facy.handle_success("ProcessUnreadMessage");
+ } else {
+ facy.handle_error("ProcessUnreadMessage");
}
+
+ offset += limit;
+ limit = 20; // TODO: use better limits?
+
+ threads.clear(); // TODO: if we have limit messages from one user, there may be more unread messages... continue with it... otherwise remove that threadd from threads list -- or do it in json parser? hm = allow more than "limit" unread messages to be parsed
}
}
@@ -429,11 +450,23 @@ void FacebookProto::ProcessMessages(void* data)
ParseSmileys(messages[i]->message_text, hContact);
- PROTORECVEVENT recv = {0};
- recv.flags = PREF_UTF;
- recv.szMessage = const_cast<char*>(messages[i]->message_text.c_str());
- recv.timestamp = local_timestamp ? ::time(NULL) : messages[i]->time;
- ProtoChainRecvMsg(hContact, &recv);
+ if (messages[i]->isIncoming) {
+ PROTORECVEVENT recv = {0};
+ recv.flags = PREF_UTF;
+ recv.szMessage = const_cast<char*>(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);
+ }
}
delete messages[i];
}
@@ -862,4 +895,4 @@ void FacebookProto::SearchIdAckThread(void *targ)
mir_free(targ);
mir_free(arg);
-} \ No newline at end of file
+}