summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/FacebookRM/src/communication.cpp13
-rw-r--r--protocols/FacebookRM/src/constants.h5
-rw-r--r--protocols/FacebookRM/src/contacts.cpp24
-rw-r--r--protocols/FacebookRM/src/json.cpp95
-rw-r--r--protocols/FacebookRM/src/json.h1
-rw-r--r--protocols/FacebookRM/src/process.cpp119
-rw-r--r--protocols/FacebookRM/src/proto.h2
7 files changed, 153 insertions, 106 deletions
diff --git a/protocols/FacebookRM/src/communication.cpp b/protocols/FacebookRM/src/communication.cpp
index 5c99482a89..e1facb8016 100644
--- a/protocols/FacebookRM/src/communication.cpp
+++ b/protocols/FacebookRM/src/communication.cpp
@@ -209,6 +209,7 @@ DWORD facebook_client::choose_security_level(RequestType request_type)
// case REQUEST_HOME:
// case REQUEST_DTSG:
// case REQUEST_BUDDY_LIST:
+// case REQUEST_LOAD_FRIEND:
// case REQUEST_LOAD_FRIENDS:
// case REQUEST_USER_INFO:
// case REQUEST_LOAD_REQUESTS:
@@ -276,6 +277,7 @@ int facebook_client::choose_method(RequestType request_type)
// case REQUEST_PAGES:
// case REQUEST_NOTIFICATIONS:
// case REQUEST_RECONNECT:
+// case REQUEST_LOAD_FRIEND:
// case REQUEST_LOAD_FRIENDS:
// case REQUEST_USER_INFO:
// case REQUEST_LOAD_REQUESTS:
@@ -318,6 +320,7 @@ std::string facebook_client::choose_server(RequestType request_type, std::string
// case REQUEST_LOGOUT:
// case REQUEST_BUDDY_LIST:
+// case REQUEST_LOAD_FRIEND:
// case REQUEST_LOAD_FRIENDS:
// case REQUEST_FEEDS:
// case REQUEST_PAGES:
@@ -368,6 +371,16 @@ std::string facebook_client::choose_action(RequestType request_type, std::string
case REQUEST_BUDDY_LIST:
return "/ajax/chat/buddy_list.php?__a=1";
+ case REQUEST_LOAD_FRIEND:
+ {
+ std::string action = "/ajax/chat/user_info.php?__a=1&viewer=%s&__user=%s";
+ utils::text::replace_all(&action, "%s", self_.user_id);
+ if (get_data != NULL) {
+ action += "&" + (*get_data);
+ }
+ return action;
+ }
+
case REQUEST_LOAD_FRIENDS:
{
std::string action = "/ajax/chat/user_info_all.php?__a=1&viewer=%s&__user=%s";
diff --git a/protocols/FacebookRM/src/constants.h b/protocols/FacebookRM/src/constants.h
index 83da81d108..d3b6a3b2d7 100644
--- a/protocols/FacebookRM/src/constants.h
+++ b/protocols/FacebookRM/src/constants.h
@@ -111,8 +111,9 @@ enum RequestType {
REQUEST_NOTIFICATIONS_READ, // marking notifications read
REQUEST_BUDDY_LIST, // getting regular updates (friends online, ...)
- REQUEST_LOAD_FRIENDS, // getting list of all friends
- REQUEST_USER_INFO, // getting info about particular user
+ REQUEST_LOAD_FRIEND, // getting info about particular friend
+ REQUEST_LOAD_FRIENDS, // getting info about all friends
+ REQUEST_USER_INFO, // getting info about particular user (from mobile website)
REQUEST_REQUEST_FRIEND, // requesting friendships
REQUEST_APPROVE_FRIEND, // approving friendships
REQUEST_DELETE_FRIEND, // deleting friendships
diff --git a/protocols/FacebookRM/src/contacts.cpp b/protocols/FacebookRM/src/contacts.cpp
index d641a775af..1135c3fd6e 100644
--- a/protocols/FacebookRM/src/contacts.cpp
+++ b/protocols/FacebookRM/src/contacts.cpp
@@ -138,6 +138,30 @@ std::string FacebookProto::ThreadIDToContactID(std::string thread_id)
return user_id;
}
+void FacebookProto::LoadContactInfo(facebook_user* fbu)
+{
+ // TODO: support for more friends at once
+ std::string get_query = "&ids[0]=" + utils::url::encode(fbu->user_id);
+
+ http::response resp = facy.flap(REQUEST_LOAD_FRIEND, NULL, &get_query);
+
+ if (resp.code == HTTP_CODE_OK) {
+ CODE_BLOCK_TRY
+
+ facebook_json_parser* p = new facebook_json_parser(this);
+ p->parse_user_info(&resp.data, fbu);
+ delete p;
+
+ debugLogA("***** Thread info processed");
+
+ CODE_BLOCK_CATCH
+
+ debugLogA("***** Error processing thread info: %s", e.what());
+
+ CODE_BLOCK_END
+ }
+}
+
MCONTACT FacebookProto::AddToContactList(facebook_user* fbu, ContactType type, bool dont_check)
{
MCONTACT hContact;
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index 0cce660a62..ee2c9abbab 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -161,6 +161,35 @@ int facebook_json_parser::parse_buddy_list(void* data, List::List< facebook_user
return EXIT_SUCCESS;
}
+void parseUser(JSONNODE *it, facebook_user *fbu)
+{
+ fbu->user_id = json_name(it);
+
+ JSONNODE *name = json_get(it, "name");
+ JSONNODE *thumbSrc = json_get(it, "thumbSrc");
+ JSONNODE *gender = json_get(it, "gender");
+ //JSONNODE *vanity = json_get(it, "vanity"); // username
+ //JSONNODE *uri = json_get(it, "uri"); // profile url
+ //JSONNODE *is_friend = json_get(it, "is_friend"); // e.g. "True"
+ //JSONNODE *type = json_get(it, "type"); // e.g. "friend" (classic contact) or "user" (disabled/deleted account)
+
+
+ if (name)
+ fbu->real_name = utils::text::slashu_to_utf8(utils::text::special_expressions_decode(json_as_pstring(name)));
+ if (thumbSrc)
+ fbu->image_url = utils::text::slashu_to_utf8(utils::text::special_expressions_decode(json_as_pstring(thumbSrc)));
+
+ if (gender)
+ switch (json_as_int(gender)) {
+ case 1: // female
+ fbu->gender = 70;
+ break;
+ case 2: // male
+ fbu->gender = 77;
+ break;
+ }
+}
+
int facebook_json_parser::parse_friends(void* data, std::map< std::string, facebook_user* >* friends)
{
std::string jsonData = static_cast< std::string* >(data)->substr(9);
@@ -177,35 +206,11 @@ int facebook_json_parser::parse_friends(void* data, std::map< std::string, faceb
for (unsigned int i = 0; i < json_size(payload); i++) {
JSONNODE *it = json_at(payload, i);
- const char *id = json_name(it);
-
- JSONNODE *name = json_get(it, "name");
- JSONNODE *thumbSrc = json_get(it, "thumbSrc");
- JSONNODE *gender = json_get(it, "gender");
- //JSONNODE *vanity = json_get(it, "vanity"); // username
- //JSONNODE *uri = json_get(it, "uri"); // profile url
- //JSONNODE *is_friend = json_get(it, "is_friend"); // e.g. "True"
- //JSONNODE *type = json_get(it, "type"); // e.g. "friend" (classic contact) or "user" (disabled/deleted account)
facebook_user *fbu = new facebook_user();
+ parseUser(it, fbu);
- fbu->user_id = id;
- if (name)
- fbu->real_name = utils::text::slashu_to_utf8(utils::text::special_expressions_decode(json_as_pstring(name)));
- if (thumbSrc)
- fbu->image_url = utils::text::slashu_to_utf8(utils::text::special_expressions_decode(json_as_pstring(thumbSrc)));
-
- if (gender)
- switch (json_as_int(gender)) {
- case 1: // female
- fbu->gender = 70;
- break;
- case 2: // male
- fbu-> gender = 77;
- break;
- }
-
- friends->insert(std::make_pair(id, fbu));
+ friends->insert(std::make_pair(fbu->user_id, fbu));
}
json_delete(root);
@@ -963,3 +968,41 @@ int facebook_json_parser::parse_thread_info(void* data, std::string* user_id)
json_delete(root);
return EXIT_SUCCESS;
}
+
+
+int facebook_json_parser::parse_user_info(void* data, facebook_user* fbu)
+{
+ 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 *profiles = json_get(payload, "profiles");
+ if (profiles == NULL) {
+ json_delete(root);
+ return EXIT_FAILURE;
+ }
+
+ std::map<std::string, std::string> user_ids;
+ for (unsigned int i = 0; i < json_size(profiles); i++) {
+ JSONNODE *it = json_at(profiles, i);
+
+ // TODO: allow more users to parse at once
+ std::string id = json_name(it);
+
+ if (fbu->user_id == id) {
+ parseUser(it, fbu);
+ break;
+ }
+ }
+
+ json_delete(root);
+ return EXIT_SUCCESS;
+}
diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h
index 6cd89faac0..33f5538559 100644
--- a/protocols/FacebookRM/src/json.h
+++ b/protocols/FacebookRM/src/json.h
@@ -37,6 +37,7 @@ public:
int parse_unread_threads(void*, std::vector< std::string >*, bool inboxOnly);
int parse_thread_messages(void*, std::vector< facebook_message* >*, std::map< std::string, facebook_chatroom* >*, bool unreadOnly, bool inboxOnly, int limit);
int parse_thread_info(void* data, std::string* user_id);
+ int parse_user_info(void* data, facebook_user* fbu);
facebook_json_parser(FacebookProto* proto)
{
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp
index b39168849a..43402fcfd7 100644
--- a/protocols/FacebookRM/src/process.cpp
+++ b/protocols/FacebookRM/src/process.cpp
@@ -385,52 +385,7 @@ void FacebookProto::ProcessUnreadMessage(void *p)
}
chatrooms.clear();
-
- for (std::vector<facebook_message*>::size_type i = 0; i < messages.size(); i++) {
- if (messages[i]->isChat) {
- debugLogA(" Got chat message: %s", messages[i]->message_text.c_str());
- UpdateChat(_A2T(messages[i]->thread_id.c_str()), messages[i]->user_id.c_str(), messages[i]->sender_name.c_str(), messages[i]->message_text.c_str(), local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time);
- } else if (messages[i]->user_id != facy.self_.user_id) {
- debugLogA(" 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?
- MCONTACT hContact = AddToContactList(&fbu, CONTACT_NONE);
- setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str());
-
- // Save TID if not exists already
- ptrA tid( getStringA(hContact, FACEBOOK_KEY_TID));
- if (!tid || strcmp(tid, messages[i]->thread_id.c_str()))
- setString(hContact, FACEBOOK_KEY_TID, messages[i]->thread_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();
+ ReceiveMessages(messages, local_timestamp);
debugLogA("***** Unread messages processed");
@@ -452,41 +407,22 @@ void FacebookProto::ProcessUnreadMessage(void *p)
}
}
-// TODO: combine processmessages and processunreadmessages? (behavior of showing messages to user should be the same)
-void FacebookProto::ProcessMessages(void* data)
+void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, bool local_timestamp)
{
- if (data == NULL)
- return;
-
- std::string* resp = (std::string*)data;
-
- // receive messages from all folders by default, use hidden setting to receive only inbox messages
- bool inboxOnly = getBool(FACEBOOK_KEY_INBOX_ONLY, 0);
-
- if (isOffline())
- goto exit;
-
- debugLogA("***** Starting processing messages");
-
- CODE_BLOCK_TRY
-
- std::vector< facebook_message* > messages;
- std::vector< facebook_notification* > notifications;
-
- facebook_json_parser* p = new facebook_json_parser(this);
- p->parse_messages(data, &messages, &notifications, inboxOnly);
- delete p;
-
- bool local_timestamp = getBool(FACEBOOK_KEY_LOCAL_TIMESTAMP, 0);
-
- for(std::vector<facebook_message*>::size_type i=0; i<messages.size(); i++)
- {
+ for(std::vector<facebook_message*>::size_type i = 0; i < messages.size(); i++) {
debugLogA(" 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;
- MCONTACT hContact = AddToContactList(&fbu, CONTACT_NONE);
+ MCONTACT hContact = ContactIDToHContact(fbu.user_id);
+ if (hContact == NULL) {
+ // We don't have this contact, lets load info about him
+ LoadContactInfo(&fbu);
+
+ hContact = AddToContactList(&fbu, CONTACT_NONE);
+ }
+
setString(hContact, FACEBOOK_KEY_MESSAGE_ID, messages[i]->message_id.c_str());
// Save TID if not exists already
@@ -494,9 +430,6 @@ void FacebookProto::ProcessMessages(void* data)
if (!tid || strcmp(tid, messages[i]->thread_id.c_str()))
setString(hContact, FACEBOOK_KEY_TID, messages[i]->thread_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) {
@@ -519,6 +452,36 @@ void FacebookProto::ProcessMessages(void* data)
delete messages[i];
}
messages.clear();
+}
+
+// TODO: combine processmessages and processunreadmessages? (behavior of showing messages to user should be the same)
+void FacebookProto::ProcessMessages(void* data)
+{
+ if (data == NULL)
+ return;
+
+ std::string* resp = (std::string*)data;
+
+ // receive messages from all folders by default, use hidden setting to receive only inbox messages
+ bool inboxOnly = getBool(FACEBOOK_KEY_INBOX_ONLY, 0);
+
+ if (isOffline())
+ goto exit;
+
+ debugLogA("***** Starting processing messages");
+
+ CODE_BLOCK_TRY
+
+ std::vector< facebook_message* > messages;
+ std::vector< facebook_notification* > notifications;
+
+ facebook_json_parser* p = new facebook_json_parser(this);
+ p->parse_messages(data, &messages, &notifications, inboxOnly);
+ delete p;
+
+ bool local_timestamp = getBool(FACEBOOK_KEY_LOCAL_TIMESTAMP, 0);
+
+ ReceiveMessages(messages, local_timestamp);
for(std::vector<facebook_notification*>::size_type i=0; i<notifications.size(); i++)
{
diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h
index 319e08074c..414e016bf0 100644
--- a/protocols/FacebookRM/src/proto.h
+++ b/protocols/FacebookRM/src/proto.h
@@ -189,6 +189,7 @@ public:
MCONTACT ContactIDToHContact(std::string);
MCONTACT ChatIDToHContact(std::tstring);
std::string ThreadIDToContactID(std::string thread_id);
+ void FacebookProto::LoadContactInfo(facebook_user* fbu);
MCONTACT AddToContactList(facebook_user*, ContactType type, bool dont_check = false);
void SetAllContactStatuses(int status);
MCONTACT HContactFromAuthEvent(HANDLE hEvent);
@@ -202,6 +203,7 @@ public:
void RemoveChatContact(const TCHAR *chat_id, const char *id);
void SetChatStatus(const char *chat_id, int status);
char *GetChatUsers(const TCHAR *chat_id);
+ void ReceiveMessages(std::vector<facebook_message*> messages, bool local_timestamp);
// Connection client
facebook_client facy; // TODO: Refactor to "client" and make dynamic