summaryrefslogtreecommitdiff
path: root/protocols/Facebook/src/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Facebook/src/server.cpp')
-rw-r--r--protocols/Facebook/src/server.cpp131
1 files changed, 97 insertions, 34 deletions
diff --git a/protocols/Facebook/src/server.cpp b/protocols/Facebook/src/server.cpp
index 573f7a2c85..33d6b69f4a 100644
--- a/protocols/Facebook/src/server.cpp
+++ b/protocols/Facebook/src/server.cpp
@@ -41,59 +41,116 @@ void FacebookProto::OnLoggedOut()
m_bOnline = false;
}
-/////////////////////////////////////////////////////////////////////////////////////////
+bool FacebookProto::RefreshContacts()
+{
+ auto *pReq = CreateRequestGQL(FB_API_QUERY_CONTACTS);
+ pReq << CHAR_PARAM("query_params", "{\"0\":[\"user\"],\"1\":\"" FB_API_CONTACTS_COUNT "\"}");
+ pReq->CalcSig();
-void FacebookProto::ServerThread(void *)
+ JsonReply reply(ExecuteRequest(pReq));
+ if (reply.error())
+ return false;
+
+ for (auto &it : reply.data()["viewer"]["messenger_contacts"]["nodes"]) {
+ auto &n = it["represented_profile"];
+ CMStringW wszId(n["id"].as_mstring());
+ __int64 id = _wtoi64(wszId);
+
+ MCONTACT hContact;
+ if (id != m_uid) {
+ auto *pUser = FindUser(id);
+ if (pUser == nullptr) {
+ hContact = db_add_contact();
+ Proto_AddToContact(hContact, m_szModuleName);
+ setWString(hContact, DBKEY_ID, wszId);
+
+ m_users.insert(new FacebookUser(id, hContact));
+ }
+ else hContact = pUser->hContact;
+ }
+ else hContact = 0;
+
+ if (auto &nName = n["structured_name"]) {
+ CMStringW wszName(nName["text"].as_mstring());
+ setWString(hContact, DBKEY_NICK, wszName);
+ for (auto &nn : nName["parts"]) {
+ CMStringW wszPart(nn["part"].as_mstring());
+ int offset = nn["offset"].as_int(), length = nn["length"].as_int();
+ if (wszPart == L"first")
+ setWString(hContact, DBKEY_FIRST_NAME, wszName.Mid(offset, length));
+ else if (wszPart == L"last")
+ setWString(hContact, DBKEY_LAST_NAME, wszName.Mid(offset, length));
+ }
+ }
+
+ if (auto &nBirth = n["birthdate"]) {
+ setDword(hContact, "BirthDay", nBirth["day"].as_int());
+ setDword(hContact, "BirthMonth", nBirth["month"].as_int());
+ }
+
+ if (auto &nCity = n["current_city"])
+ setDword(hContact, "City", nCity["name"].as_int());
+
+ if (auto &nAva = n["smallPictureUrl"])
+ setWString(hContact, "Avatar", nAva["uri"].as_mstring());
+ }
+ return true;
+}
+
+bool FacebookProto::RefreshToken()
{
- m_szAuthToken = getMStringA(DBKEY_TOKEN);
+ auto *pReq = CreateRequest("authenticate", "auth.login");
+ pReq->m_szUrl = FB_API_URL_AUTH;
+ pReq << CHAR_PARAM("email", getMStringA(DBKEY_LOGIN));
+ pReq << CHAR_PARAM("password", getMStringA(DBKEY_PASS));
+ pReq->CalcSig();
- if (m_szAuthToken.IsEmpty()) {
- auto *pReq = CreateRequest("authenticate", "auth.login");
- pReq->m_szUrl = FB_API_URL_AUTH;
+ JsonReply reply(ExecuteRequest(pReq));
+ if (reply.error())
+ return false;
- pReq << CHAR_PARAM("email", getMStringA(DBKEY_LOGIN));
- pReq << CHAR_PARAM("password", getMStringA(DBKEY_PASS));
+ m_szAuthToken = reply.data()["access_token"].as_mstring();
+ setString(DBKEY_TOKEN, m_szAuthToken);
- pReq->CalcSig();
+ m_uid = reply.data()["uid"].as_int();
+ CMStringA m_szUid = reply.data()["uid"].as_mstring();
+ setString(DBKEY_ID, m_szUid);
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
- JsonReply reply(ExecuteRequest(pReq));
+void FacebookProto::ServerThread(void *)
+{
+ m_szAuthToken = getMStringA(DBKEY_TOKEN);
- if (reply.error()) {
+ if (m_szAuthToken.IsEmpty()) {
+ if (!RefreshToken()) {
+FAIL:
ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)m_iStatus, m_iDesiredStatus);
m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, m_iDesiredStatus);
return;
}
-
- m_szAuthToken = reply.data()["access_token"].as_mstring();
- setString(DBKEY_TOKEN, m_szAuthToken);
-
- m_uid = reply.data()["uid"].as_int();
- CMStringA m_szUid = reply.data()["uid"].as_mstring();
- setString(DBKEY_ID, m_szUid);
}
- auto *pReq = CreateRequestGQL(FB_API_QUERY_CONTACTS);
- pReq << CHAR_PARAM("query_params", "{\"0\":[\"user\"],\"1\":\"" FB_API_CONTACTS_COUNT "\"}");
- pReq->CalcSig();
-
- JsonReply reply(ExecuteRequest(pReq));
- if (reply.error()) {
-FAIL:
- ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)m_iStatus, m_iDesiredStatus);
-
- m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
- ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, m_iDesiredStatus);
- return;
- }
+ if (!RefreshContacts())
+ goto FAIL;
// connect to MQTT server
- if (!MqttConnect())
+ NETLIBOPENCONNECTION nloc = {};
+ nloc.szHost = "mqtt.facebook.com";
+ nloc.wPort = 443;
+ nloc.flags = NLOCF_SSL | NLOCF_V2;
+ m_mqttConn = Netlib_OpenConnection(m_hNetlibUser, &nloc);
+ if (m_mqttConn == nullptr) {
+ debugLogA("connection failed, exiting");
goto FAIL;
+ }
// send initial packet
- MqttOpen();
+ MqttLogin();
__int64 startTime = GetTickCount64();
@@ -200,7 +257,13 @@ void FacebookProto::OnPublishP(FbThriftReader &rdr)
assert(fieldId == 1);
assert(rdr.readInt32(u32));
- debugLogA("Presence from user %lld => %d", userId, u32);
+ auto *pUser = FindUser(userId);
+ if (pUser == nullptr)
+ debugLogA("Skipping presence from unknown user %lld", userId);
+ else {
+ debugLogA("Presence from user %lld => %d", userId, u32);
+ setWord(pUser->hContact, "Status", (u32 != 0) ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ }
assert(rdr.readField(fieldType, fieldId));
assert(fieldType == FB_THRIFT_TYPE_I64);