diff options
Diffstat (limited to 'protocols/FacebookRM/src')
-rw-r--r-- | protocols/FacebookRM/src/process.cpp | 145 | ||||
-rw-r--r-- | protocols/FacebookRM/src/requests/search.h | 10 |
2 files changed, 95 insertions, 60 deletions
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp index 6b1d126a7e..bd081c8e38 100644 --- a/protocols/FacebookRM/src/process.cpp +++ b/protocols/FacebookRM/src/process.cpp @@ -1208,75 +1208,106 @@ void FacebookProto::SearchAckThread(void *targ) { facy.handle_entry("searchAckThread"); - int count = 0; + // We want to search separately people and then pages + for (int searchType = 0; searchType < 2; searchType++) { + // searchType: 0 = search people, 1 = search pages + bool searchPages = (searchType == 1); - std::string search = utils::url::encode(T2Utf((wchar_t *)targ).str()); - std::string ssid; - int pn = 1; + int count = 0; + std::string search = utils::url::encode(T2Utf((wchar_t *)targ).str()); + std::string ssid; + int pn = 1; - while (count < 50 && !isOffline()) - { - SearchRequest *request = new SearchRequest(facy.mbasicWorks, search.c_str(), count, pn, ssid.c_str()); - http::response resp = facy.sendRequest(request); - - if (resp.code == HTTP_CODE_OK) + while (count < 50 && !isOffline()) { - std::string items = utils::text::source_get_value(&resp.data, 4, "<body", "</form", "<table", "</body>"); + SearchRequest *request = new SearchRequest(facy.mbasicWorks, searchPages ? SEARCH_TYPE_PAGES : SEARCH_TYPE_PEOPLE, search.c_str(), count, pn, ssid.c_str()); + http::response resp = facy.sendRequest(request); - std::string::size_type pos = 0; - std::string::size_type pos2 = 0; - - while ((pos = items.find("<tr", pos)) != std::string::npos) { - std::string item = items.substr(pos, items.find("</tr>", pos) - pos); - pos++; count++; + if (resp.code == HTTP_CODE_OK) + { + std::string items = utils::text::source_get_value(&resp.data, 4, "<body", "</form", "<table", "</table>"); - std::string id = utils::text::source_get_value2(&item, "?id=", "&\""); - if (id.empty()) - id = utils::text::source_get_value2(&item, "?ids=", "&\""); + std::string::size_type pos = 0; + std::string::size_type pos2 = 0; - std::string name = utils::text::source_get_value(&item, 3, "<a", ">", "</"); - std::string surname; - std::string nick; - std::string common = utils::text::source_get_value(&item, 4, "</a>", "<span", ">", "</span>"); + while ((pos = items.find("<tr", pos)) != std::string::npos) { + std::string item = items.substr(pos, items.find("</tr>", pos) - pos); + pos++; count++; - if ((pos2 = name.find("<span class=\"alternate_name\">")) != std::string::npos) { - nick = name.substr(pos2 + 30, name.length() - pos2 - 31); // also remove brackets around nickname - name = name.substr(0, pos2 - 1); - } + std::string id = utils::text::source_get_value2(&item, "?id=", "&\""); + if (id.empty()) { + id = utils::text::source_get_value2(&item, "?ids=", "&\""); + } + if (id.empty()) { + // For pages that user already likes we must parse "sld" value + // We could parse it for all contacts this way, but above solution is more effective + std::string url = utils::text::source_get_value(&item, 3, "<a", "href=\"", "\""); + std::string sld = utils::text::source_get_value2(&url, "sld=", "&\"", true); + // sld is Base64 encoded and then URL encoded string. So replace potential "%3D" with "=" + utils::text::replace_all(&sld, "%3D", "="); + // decode Base64 string + ptrA data_((char*)mir_base64_decode(sld.c_str(), 0)); + if (data_) { + std::string data = data_; + id = utils::text::source_get_value2(&data, "\"ent_id\":", ",}"); + } + } - if ((pos2 = name.find(" ")) != std::string::npos) { - surname = name.substr(pos2 + 1, name.length() - pos2 - 1); - name = name.substr(0, pos2); - } + std::string name = utils::text::source_get_value(&item, 3, "<a", ">", "</"); + std::string surname; + std::string nick; + std::string common = utils::text::source_get_value(&item, 4, "</a>", "<span", ">", "</span>"); + + if (searchPages) { + // When searching pages we use whole name as nick and use prefix + nick = m_pagePrefix + " " + name; + name = ""; + if (common.empty()) { + // Pages has additional data in <div>, not in <span> as people + common = utils::text::source_get_value(&item, 4, "</a>", "<div", ">", "</div>"); + } + } else { + // When searching for people we try to parse nick and split first/last name + if ((pos2 = name.find("<span class=\"alternate_name\">")) != std::string::npos) { + nick = name.substr(pos2 + 30, name.length() - pos2 - 31); // also remove brackets around nickname + name = name.substr(0, pos2 - 1); + } - // ignore self contact and empty ids - if (id.empty() || id == facy.self_.user_id) - continue; + if ((pos2 = name.find(" ")) != std::string::npos) { + surname = name.substr(pos2 + 1, name.length() - pos2 - 1); + name = name.substr(0, pos2); + } + } - ptrW tid(mir_utf8decodeW(id.c_str())); - ptrW tname(mir_utf8decodeW(utils::text::html_entities_decode(name).c_str())); - ptrW tsurname(mir_utf8decodeW(utils::text::html_entities_decode(surname).c_str())); - ptrW tnick(mir_utf8decodeW(utils::text::html_entities_decode(nick).c_str())); - ptrW tcommon(mir_utf8decodeW(utils::text::html_entities_decode(common).c_str())); + // ignore self contact and empty ids + if (id.empty() || id == facy.self_.user_id) + continue; + + ptrW tid(mir_utf8decodeW(id.c_str())); + ptrW tname(mir_utf8decodeW(utils::text::html_entities_decode(name).c_str())); + ptrW tsurname(mir_utf8decodeW(utils::text::html_entities_decode(surname).c_str())); + ptrW tnick(mir_utf8decodeW(utils::text::html_entities_decode(nick).c_str())); + ptrW tcommon(mir_utf8decodeW(utils::text::html_entities_decode(common).c_str())); + + PROTOSEARCHRESULT psr = { 0 }; + psr.cbSize = sizeof(psr); + psr.flags = PSR_UNICODE; + psr.id.w = tid; + psr.nick.w = tnick; + psr.firstName.w = tname; + psr.lastName.w = tsurname; + psr.email.w = tcommon; + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, targ, (LPARAM)&psr); + } - PROTOSEARCHRESULT psr = { 0 }; - psr.cbSize = sizeof(psr); - psr.flags = PSR_UNICODE; - psr.id.w = tid; - psr.nick.w = tnick; - psr.firstName.w = tname; - psr.lastName.w = tsurname; - psr.email.w = tcommon; - ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, targ, (LPARAM)&psr); + ssid = utils::text::source_get_value(&resp.data, 3, "id=\"more_objects\"", "ssid=", "&"); + pn++; // increment page number + if (ssid.empty()) + break; // No more results + } + else { + break; } - - ssid = utils::text::source_get_value(&items, 3, "id=\"more_objects\"", "ssid=", "&"); - pn++; // increment page number - if (ssid.empty()) - break; // No more results - } - else { - break; } } diff --git a/protocols/FacebookRM/src/requests/search.h b/protocols/FacebookRM/src/requests/search.h index 127a559dba..6ca35b10cd 100644 --- a/protocols/FacebookRM/src/requests/search.h +++ b/protocols/FacebookRM/src/requests/search.h @@ -3,7 +3,7 @@ Facebook plugin for Miranda Instant Messenger _____________________________________________ -Copyright � 2011-17 Robert P�sel +Copyright © 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 @@ -23,12 +23,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifndef _FACEBOOK_REQUEST_SEARCH_H_ #define _FACEBOOK_REQUEST_SEARCH_H_ +#define SEARCH_TYPE_PEOPLE "people" +#define SEARCH_TYPE_PAGES "pages" +// other type for searching is "events" or "groups", but that's pointless to search in Miranda + // searching class SearchRequest : public HttpRequest { public: - SearchRequest(bool mobileBasicWorks, const char *query, int s, int pn, const char *ssid) : - HttpRequest(REQUEST_GET, FORMAT, "%s/search/people/", mobileBasicWorks ? FACEBOOK_SERVER_MBASIC : FACEBOOK_SERVER_MOBILE) + SearchRequest(bool mobileBasicWorks, const char *type, const char *query, int s, int pn, const char *ssid) : + HttpRequest(REQUEST_GET, FORMAT, "%s/search/%s/", mobileBasicWorks ? FACEBOOK_SERVER_MBASIC : FACEBOOK_SERVER_MOBILE, type) { flags |= NLHRF_REDIRECT; |