diff options
author | Robert Pösel <robyer@seznam.cz> | 2016-05-17 20:15:33 +0000 |
---|---|---|
committer | Robert Pösel <robyer@seznam.cz> | 2016-05-17 20:15:33 +0000 |
commit | 5e5cabbee2c2249be4e34efc9bafa1b05136111a (patch) | |
tree | 5705bd162306f31b1d41dc2b1d48ae53ca4046d4 /protocols/FacebookRM/src/json.cpp | |
parent | 82cd0bd751e964a84746740abd03a419b8b80532 (diff) |
Facebook: Rework loading online contacts (not properly finished!); version bump
This is work in progress, which might (and will) cause wrong status reporting and maybe related problems. On the other hand this way is only "preferred" way. Previous way (using buddy_list request) isn't used anymore and might cause the captcha problems and antivirus checks from FB...
git-svn-id: http://svn.miranda-ng.org/main/trunk@16843 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/FacebookRM/src/json.cpp')
-rw-r--r-- | protocols/FacebookRM/src/json.cpp | 293 |
1 files changed, 168 insertions, 125 deletions
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index 901b28ada6..7b5ac5dd04 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -22,100 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h" -int facebook_json_parser::parse_buddy_list(std::string *data, List::List< facebook_user >* buddy_list) -{ - facebook_user* current = NULL; - std::string jsonData = data->substr(9); - - JSONNode root = JSONNode::parse(jsonData.c_str()); - if (!root) - return EXIT_FAILURE; - - const JSONNode &list = root["payload"].at("buddy_list"); - if (!list) - return EXIT_FAILURE; - - // Set all contacts in map to offline (and reset client) - for (List::Item< facebook_user >* i = buddy_list->begin(); i != NULL; i = i->next) { - i->data->status_id = ID_STATUS_OFFLINE; - if (i->data->client == 0) - i->data->client = CLIENT_WEB; - } - - // Load last active times - const JSONNode &lastActive = list["last_active_times"]; - for (auto it = lastActive.begin(); it != lastActive.end(); ++it) { - const char *id = (*it).name(); - - current = buddy_list->find(id); - if (current == NULL) { - buddy_list->insert(std::make_pair(id, new facebook_user())); - current = buddy_list->find(id); - current->user_id = id; - } - - current->last_active = (*it).as_int(); - } - - // Find mobile friends - const JSONNode &mobileFriends = list["mobile_friends"]; - for (auto it = mobileFriends.begin(); it != mobileFriends.end(); ++it) { - std::string id = (*it).as_string(); - - current = buddy_list->find(id); - if (current == NULL) { - buddy_list->insert(std::make_pair(id, new facebook_user())); - current = buddy_list->find(id); - current->user_id = id; - } - - current->status_id = ID_STATUS_OFFLINE; - current->client = CLIENT_MOBILE; - } - - time_t now = ::time(NULL); - - // Find now available contacts - const JSONNode &nowAvailable = list["nowAvailableList"]; - for (auto it = nowAvailable.begin(); it != nowAvailable.end(); ++it) { - const char *id = (*it).name(); - - current = buddy_list->find(id); - if (current == NULL) { - buddy_list->insert(std::make_pair(id, new facebook_user())); - current = buddy_list->find(id); - current->user_id = id; - } - - current->status_id = (current->client == CLIENT_MOBILE || current->client == CLIENT_MESSENGER) ? ID_STATUS_ONTHEPHONE : ID_STATUS_ONLINE; - - // Set contacts that were last active more than 1 minute ago as away - if (current->status_id == ID_STATUS_ONLINE && current->last_active > 0 && (now - current->last_active) > 60) { - current->status_id = ID_STATUS_AWAY; - } - } - - // Get aditional informations about contacts (if available) - const JSONNode &userInfos = list["userInfos"]; - for (auto it = userInfos.begin(); it != userInfos.end(); ++it) { - const char *id = (*it).name(); - - current = buddy_list->find(id); - if (current == NULL) - continue; - - std::string name = (*it)["name"].as_string(); - if (!name.empty()) - current->real_name = utils::text::slashu_to_utf8(name); - - std::string thumbSrc = (*it)["thumbSrc"].as_string(); - if (!thumbSrc.empty()) - current->image_url = utils::text::slashu_to_utf8(thumbSrc); - } - - return EXIT_SUCCESS; -} - void parseUser(const JSONNode &it, facebook_user *fbu) { fbu->user_id = it.name(); @@ -758,54 +664,191 @@ int facebook_json_parser::parse_messages(std::string *pData, std::vector<faceboo proto->SetStatus(isVisible ? ID_STATUS_ONLINE : ID_STATUS_INVISIBLE); } } + else if (t == "chatproxy-presence") { + const JSONNode &buddyList = (*it)["buddyList"]; + if (!buddyList) + continue; + + for (auto itNodes = buddyList.begin(); itNodes != buddyList.end(); ++itNodes) { + std::string id = (*itNodes).name(); + + MCONTACT hContact = proto->ContactIDToHContact(id); + if (!hContact) { + // FIXME: What to do, when we don't have this contact? What does it mean? + // fbu->handle = AddToContactList(fbu, CONTACT_FRIEND); // add this contact as friend? + continue; + } + + // TODO: Check for friends existence/inexistence? Here we should get all friends (but we're already doing friendslist request, so we should have fresh data already) + + const JSONNode &p_ = (*itNodes)["p"]; // possible values: 0, 2 (something more?) (might not be present) + const JSONNode &lat_ = (*itNodes)["lat"]; // timestamp of last activity (could be 0) (is always present) + const JSONNode &vc_ = (*itNodes)["vc"]; // possible values: 0, 8, 10 (something more?) (might not be present) + + int status = ID_STATUS_DND; // DND to easily spot some problem, as we expect it will always be p==0 or p==2 below + + // Probably means presence: 0 = away, 2 = online, when not present then that probably means don't change that status + if (p_) { + int p = p_.as_int(); + + if (p == 0) + status = ID_STATUS_AWAY; + else if (p == 2) + status = ID_STATUS_ONLINE; + + if (proto->getWord(hContact, "Status", 0) != status) + proto->setWord(hContact, "Status", status); + } + + // Last active time + if (lat_) { + time_t last_active = utils::time::from_string(lat_.as_string()); + + if (proto->getDword(hContact, "LastActiveTS", 0) != last_active) { + if (last_active > 0) + proto->setDword(hContact, "LastActiveTS", last_active); + else + proto->delSetting(hContact, "LastActiveTS"); + } + } + + // Probably means client: guess 0 = web, 8 = messenger, 10 = something else? + if (vc_) { + int vc = vc_.as_int(); + TCHAR *client; + + if (vc == 0) { + client = _T(FACEBOOK_CLIENT_WEB); + } + else if (vc == 8) { + client = _T(FACEBOOK_CLIENT_MESSENGER); // I was online on Miranda, but when looked at myself at messenger.com I had icon of Messenger. + } + else if (vc == 10) { + client = _T(FACEBOOK_CLIENT_MOBILE); + } + else { + client = _T(FACEBOOK_CLIENT_OTHER); + } + + ptrT oldClient(proto->getTStringA(hContact, "MirVer")); + if (!oldClient || mir_tstrcmp(oldClient, client)) + proto->setTString(hContact, "MirVer", client); + } + } + } else if (t == "buddylist_overlay") { - // additional info about user status (used client) + // TODO: This is now supported also via /ajax/mercury/tabs_presence.php request (probably) + // additional info about user status (status, used client) const JSONNode &overlay = (*it)["overlay"]; if (!overlay) continue; for (auto itNodes = overlay.begin(); itNodes != overlay.end(); ++itNodes) { - std::string id = (*itNodes).as_string(); + std::string id = (*itNodes).name(); - const JSONNode &p_ = (*itNodes)["p"]; - if (!p_) + MCONTACT hContact = proto->ContactIDToHContact(id); + if (!hContact) { + // FIXME: What to do, when we don't have this contact? What does it mean? + // fbu->handle = AddToContactList(fbu, CONTACT_FRIEND); // add this contact as friend? continue; + } - // TODO: This is now supported also via /ajax/mercury/tabs_presence.php request - const JSONNode &p = (*it)["p"]; - if (p) { - facebook_user* current = proto->facy.buddies.find(id); // HACKISH-WAY to get buddies... - if (current == NULL) - continue; + // TODO: Check for friends existence/inexistence? - std::string status = p["status"].as_string(); // this seems to be "active" or "invisible" or null - std::string webStatus = p["webStatus"].as_string(); // "active", "idle" or "offline" - std::string fbAppStatus = p["fbAppStatus"].as_string(); // "offline" or "active" or "invisible" or null - std::string messengerStatus = p["messengerStatus"].as_string(); // "offline" or "active" or "invisible" or null - std::string otherStatus = p["otherStatus"].as_string(); // "offline" or "active" or "invisible" or null - this seems to be "active" when webStatus is "idle" or "active" only + /* if (getByte(fbu->handle, FACEBOOK_KEY_CONTACT_TYPE, 0) != CONTACT_FRIEND) { + setByte(fbu->handle, FACEBOOK_KEY_CONTACT_TYPE, CONTACT_FRIEND); + // TODO: remove that popup and use "Contact added you" event? + } - // this may never happen - if (status != "active") - current->status_id = ID_STATUS_OFFLINE; + // Wasn't contact removed from "server-list" someday? + if (getDword(fbu->handle, FACEBOOK_KEY_DELETED, 0)) { + delSetting(fbu->handle, FACEBOOK_KEY_DELETED); - bool b; + std::string url = FACEBOOK_URL_PROFILE + fbu->user_id; + std::string contactname = getContactName(this, fbu->handle, !fbu->real_name.empty() ? fbu->real_name.c_str() : fbu->user_id.c_str()); - // "webStatus" and "otherStatus" are marked as "WEB" on FB website - if ((b = (webStatus == "active")) || otherStatus == "active") { - current->status_id = ID_STATUS_ONLINE; - current->client = b ? CLIENT_WEB : CLIENT_OTHER; - } + ptrT szTitle(mir_utf8decodeT(contactname.c_str())); + NotifyEvent(szTitle, TranslateT("Contact is back on server-list."), fbu->handle, FACEBOOK_EVENT_FRIENDSHIP, &url); + } */ + + + /* ptrT client(getTStringA(fbu->handle, "MirVer")); + if (!client || mir_tstrcmp(client, fbu->getMirVer())) + setTString(fbu->handle, "MirVer", fbu->getMirVer()); + */ + + const JSONNode &a_ = (*itNodes)["a"]; // possible values: 0, 2 (something more?) + const JSONNode &la_ = (*itNodes)["la"]; // timestamp of last activity (could be 0) + const JSONNode &s_ = (*itNodes)["s"]; // possible values: push (something more?) + const JSONNode &vc_ = (*itNodes)["vc"]; // possible values: 0, 8, 10 (something more?) + + // Friller account has also these: + // const JSONNode &ol_ = (*itNodes)["ol"]; // possible values: -1 (when goes to offline), 0 (when goes back online) (something more?) + // const JSONNode &p_ = (*itNodes)["p"]; // class with fbAppStatus, messengerStatus, otherStatus, status, webStatus + + int status = ID_STATUS_FREECHAT; // FREECHAT to easily spot some problem, as we expect it will always be p==0 or p==2 below + + if (a_) { + int a = a_.as_int(); + + if (a == 0) + status = ID_STATUS_OFFLINE; + else if (a == 2) + status = ID_STATUS_ONLINE; + } - // "fbAppStatus" and "messengerStatus" are marked as "MOBILE" on FB website - if ((b = (fbAppStatus == "active")) || messengerStatus == "active") { - current->status_id = ID_STATUS_ONTHEPHONE; - current->client = b ? CLIENT_APP : CLIENT_MESSENGER; + if (proto->getWord(hContact, "Status", 0) != status) + proto->setWord(hContact, "Status", status); + + + if (la_ && status != ID_STATUS_ONLINE) { + 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 (/*(fbu->idle || status == ID_STATUS_OFFLINE) &&*/ last_active > 0) + proto->setDword(hContact, "IdleTS", last_active); + else + proto->delSetting(hContact, "IdleTS"); } - // this is not marked anyhow on website (yet?) - current->idle = webStatus == "idle" || otherStatus == "idle" || fbAppStatus == "idle" || messengerStatus == "idle"; + /*if (proto->getDword(hContact, "LastActiveTS", 0) != last_active) { + if (last_active > 0) + proto->setDword(hContact, "LastActiveTS", last_active); + else + proto->delSetting(hContact, "LastActiveTS"); + }*/ + } + else { + proto->delSetting(hContact, "IdleTS"); + } + + if (s_) { + // what to do with this? + } + // Probably means client: guess 0 = web, 8 = messenger, 10 = something else? + if (vc_) { + int vc = vc_.as_int(); + TCHAR *client = _T(FACEBOOK_CLIENT_WEB); + + /*if (vc == 0) { + // means active some time ago? (on messenger or also on web) + client = _T(FACEBOOK_CLIENT_WEB); + } + else if (vc == 8) { + client = _T(FACEBOOK_CLIENT_MESSENGER); // I was online on Miranda, but when looked at myself at messenger.com I had icon of Messenger. + } + else if (vc == 10) { + // means actually active on messenger + client = _T(FACEBOOK_CLIENT_MOBILE); + } + else { + client = _T(FACEBOOK_CLIENT_OTHER); + }*/ - // TODO: save that info to DB + ptrT oldClient(proto->getTStringA(hContact, "MirVer")); + if (!oldClient || mir_tstrcmp(oldClient, client)) + proto->setTString(hContact, "MirVer", client); } } } else if (t == "ticker_update:home") { |