diff options
Diffstat (limited to 'protocols/Steam/src/steam_polling.cpp')
-rw-r--r-- | protocols/Steam/src/steam_polling.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/protocols/Steam/src/steam_polling.cpp b/protocols/Steam/src/steam_polling.cpp new file mode 100644 index 0000000000..1a50403fd3 --- /dev/null +++ b/protocols/Steam/src/steam_polling.cpp @@ -0,0 +1,263 @@ +#include "stdafx.h" + +#define POLLING_ERRORS_LIMIT 3 + +void CSteamProto::ParsePollData(JSONNode *data) +{ + JSONNode *node, *item = NULL; + + std::string steamIds; + for (size_t i = 0; i < json_size(data); i++) + { + item = json_at(data, i); + if (item == NULL) + break; + + node = json_get(item, "steamid_from"); + ptrA steamId(mir_t2a(ptrT(json_as_string(node)))); + + node = json_get(item, "utc_timestamp"); + time_t timestamp = atol(ptrA(mir_t2a(ptrT(json_as_string(node))))); + + node = json_get(item, "type"); + ptrT type(json_as_string(node)); + if (!lstrcmpi(type, _T("saytext")) || !lstrcmpi(type, _T("emote")) || + !lstrcmpi(type, _T("my_saytext")) || !lstrcmpi(type, _T("my_emote"))) + { + MCONTACT hContact = FindContact(steamId); + if (!hContact) + continue; + + node = json_get(item, "text"); + ptrT text(json_as_string(node)); + T2Utf szMessage(text); + + if (_tcsstr(type, _T("my_")) == NULL) + { + PROTORECVEVENT recv = { 0 }; + recv.timestamp = timestamp; + recv.szMessage = szMessage; + ProtoChainRecvMsg(hContact, &recv); + } + else + { + AddDBEvent(hContact, EVENTTYPE_MESSAGE, timestamp, DBEF_UTF | DBEF_SENT, (int)mir_strlen(szMessage) + 1, (PBYTE)(char*)szMessage); + } + } + else if (!lstrcmpi(type, _T("typing"))) + { + MCONTACT hContact = FindContact(steamId); + if (hContact) + { + CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)STEAM_TYPING_TIME); + } + } + else if (!lstrcmpi(type, _T("personastate"))) + { + node = json_get(item, "persona_state"); + int status = node ? SteamToMirandaStatus(json_as_int(node)) : -1; + + if (IsMe(steamId)) + { + node = json_get(item, "persona_name"); + setTString("Nick", ptrT(json_as_string(node))); + + if (status == -1 || status == ID_STATUS_OFFLINE) + continue; + + if (status != m_iStatus) + { + debugLog(_T("CSteamProto::ParsePollData: Change own status to %i"), status); + int oldStatus = m_iStatus; + m_iStatus = m_iDesiredStatus = status; + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); + } + + continue; + } + + MCONTACT hContact = FindContact(steamId); + if (hContact == NULL) + continue; // probably this is info about random player playing on same server, so we ignore it + + if (status != -1) + SetContactStatus(hContact, status); + + node = json_get(item, "persona_name"); + setTString(hContact, "Nick", ptrT(json_as_string(node))); + + // todo: find difference between state changing and info changing + steamIds.append(steamId).append(","); + } + else if (!lstrcmpi(type, _T("personarelationship"))) + { + node = json_get(item, "persona_state"); + int state = json_as_int(node); + + switch (state) + { + case 0: + {// removed + MCONTACT hContact = FindContact(steamId); + if (hContact) + { + ContactIsRemoved(hContact); + } + } + break; + + case 1: + {// ignored + MCONTACT hContact = FindContact(steamId); + if (hContact) + { + ContactIsIgnored(hContact); + } + } + break; + + case 2: + {// auth request + /*MCONTACT hContact = FindContact(steamId); + if (!hContact) + hContact = AddContact(steamId, true);*/ + + //RaiseAuthRequestThread((void*)hContact); + + ptrA token(getStringA("TokenSecret")); + + PushRequest( + new GetUserSummariesRequest(token, steamId), + &CSteamProto::OnAuthRequested, + mir_strdup(steamId), + MirFreeArg); + } + break; + + case 3: + // add to list + // todo + break; + + default: continue; + } + } + /*else if (!lstrcmpi(type, _T("leftconversation"))) + { + }*/ + else + { + continue; + } + } + + if (!steamIds.empty()) + { + steamIds.pop_back(); + ptrA token(getStringA("TokenSecret")); + + PushRequest( + new GetUserSummariesRequest(token, steamIds.c_str()), + &CSteamProto::OnGotUserSummaries); + } +} + +void CSteamProto::PollingThread(void*) +{ + debugLog(_T("CSteamProto::PollingThread: entering")); + + ptrA token(getStringA("TokenSecret")); + ptrA umqId(getStringA("UMQID")); + UINT32 messageId = getDword("MessageID", 0); + + int errors = 0; + bool breaked = false; + while (!isTerminated && !breaked && errors < POLLING_ERRORS_LIMIT) + { + PollRequest *request = new PollRequest(token, umqId, messageId, IdleSeconds()); + request->nlc = m_pollingConnection; + HttpResponse *response = request->Send(m_hNetlibUser); + delete request; + + if (!ResponseHttpOk(response)) + { + errors++; + } + else + { + ptrA body(mir_strdup(response->pData)); + JSONROOT root(body); + if (root == NULL) + { + errors++; + } + else + { + errors = 0; + JSONNode *node = json_get(root, "error"); + if (node) { + ptrT error(json_as_string(node)); + + if (!lstrcmpi(error, _T("OK"))) + { + node = json_get(root, "messagelast"); + messageId = json_as_int(node); + + node = json_get(root, "messages"); + JSONNode *nroot = json_as_array(node); + + if (nroot != NULL) + { + ParsePollData(nroot); + json_delete(nroot); + } + + m_pollingConnection = response->nlc; + } + /*else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now + { + if (!IsOnline()) + { + // need to relogin + debugLog(_T("CSteamProto::PollingThread: not logged on")); + + SetStatus(ID_STATUS_OFFLINE); + } + + breaked = true; + }*/ + else if (lstrcmpi(error, _T("Timeout"))) + { + // something wrong + debugLog(_T("CSteamProto::PollingThread: %s (%d)"), error, response->resultCode); + + // token has expired + if (response->resultCode == HTTP_CODE_UNAUTHORIZED) + delSetting("TokenSecret"); + + // too low timeout? + node = json_get(root, "sectimeout"); + int timeout = json_as_int(node); + if (timeout < STEAM_API_TIMEOUT) + debugLog(_T("CSteamProto::PollingThread: Timeout is too low (%d)"), timeout); + + breaked = true; + } + } + } + } + + delete response; + } + + setDword("MessageID", messageId); + + m_hPollingThread = NULL; + debugLog(_T("CSteamProto::PollingThread: leaving")); + + if (!isTerminated) + { + debugLog(_T("CSteamProto::PollingThread: unexpected termination; switching protocol to offline")); + SetStatus(ID_STATUS_OFFLINE); + } +}
\ No newline at end of file |