diff options
-rw-r--r-- | protocols/Steam/src/api/history.h | 27 | ||||
-rw-r--r-- | protocols/Steam/src/stdafx.h | 1 | ||||
-rw-r--r-- | protocols/Steam/src/steam_contacts.cpp | 8 | ||||
-rw-r--r-- | protocols/Steam/src/steam_history.cpp | 121 | ||||
-rw-r--r-- | protocols/Steam/src/steam_polling.cpp | 6 | ||||
-rw-r--r-- | protocols/Steam/src/steam_proto.cpp | 4 | ||||
-rw-r--r-- | protocols/Steam/src/steam_proto.h | 17 |
7 files changed, 183 insertions, 1 deletions
diff --git a/protocols/Steam/src/api/history.h b/protocols/Steam/src/api/history.h new file mode 100644 index 0000000000..fc3c7c8a6b --- /dev/null +++ b/protocols/Steam/src/api/history.h @@ -0,0 +1,27 @@ +#ifndef _STEAM_REQUEST_HISTORY_H_ +#define _STEAM_REQUEST_HISTORY_H_ + +class GetConversationsRequest : public HttpRequest +{ +public: + GetConversationsRequest(const char *token) : + HttpRequest(REQUEST_GET, STEAM_API_URL "/IFriendMessagesService/GetActiveMessageSessions/v0001") + { + AddParameter("access_token", token); + } +}; + +class GetHistoryMessagesRequest : public HttpRequest +{ +public: + GetHistoryMessagesRequest(const char *token, const char *steamId, const char *who, time_t since) : + HttpRequest(REQUEST_GET, STEAM_API_URL "/IFriendMessagesService/GetRecentMessages/v0001") + { + AddParameter("access_token", token); + AddParameter("steamid1", steamId); + AddParameter("steamid2", who); + AddParameter("rtime32_start_time=%d", since); + } +}; + +#endif //_STEAM_REQUEST_HISTORY_H_ diff --git a/protocols/Steam/src/stdafx.h b/protocols/Steam/src/stdafx.h index da39bcaed8..b86ae3908f 100644 --- a/protocols/Steam/src/stdafx.h +++ b/protocols/Steam/src/stdafx.h @@ -69,6 +69,7 @@ extern HANDLE hExtraXStatus; #include "api\captcha.h"
#include "api\friend.h"
#include "api\friend_list.h"
+#include "api\history.h"
#include "api\login.h"
#include "api\message.h"
#include "api\pending.h"
diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp index 69572b2953..b069052cbc 100644 --- a/protocols/Steam/src/steam_contacts.cpp +++ b/protocols/Steam/src/steam_contacts.cpp @@ -432,15 +432,21 @@ void CSteamProto::OnGotFriendList(const HttpResponse *response) // We need to delete nroot here at the end, because we had references to JSONNode objects stored in friends map json_delete(nroot); + ptrA token(getStringA("TokenSecret")); + if (!steamIds.empty()) { //steamIds.pop_back(); - ptrA token(getStringA("TokenSecret")); PushRequest( new GetUserSummariesRequest(token, steamIds.c_str()), &CSteamProto::OnGotUserSummaries); } + + // Download last messages + PushRequest( + new GetConversationsRequest(token), + &CSteamProto::OnGotConversations); } void CSteamProto::OnGotBlockList(const HttpResponse *response) diff --git a/protocols/Steam/src/steam_history.cpp b/protocols/Steam/src/steam_history.cpp new file mode 100644 index 0000000000..dc1f746928 --- /dev/null +++ b/protocols/Steam/src/steam_history.cpp @@ -0,0 +1,121 @@ +#include "stdafx.h" + +void CSteamProto::OnGotConversations(const HttpResponse *response) +{ + if (!ResponseHttpOk(response)) + return; + + JSONROOT root(response->pData); + if (root == NULL) + return; + + JSONNode *node = json_get(root, "response"); + + if (m_lastMessageTS <= 0) + { + // Remember and save actual timestamp (as it is first we've got) + JSONNode *timestampNode = json_get(node, "timestamp"); + m_lastMessageTS = _ttoi64(ptrT(json_as_string(timestampNode))); + setDword("LastMessageTS", m_lastMessageTS); + + // And don't load any messages as it may cause duplicates + return; + } + + JSONNode *sessions = json_get(node, "message_sessions"); + JSONNode *nsessions = json_as_array(sessions); + + if (nsessions != NULL) + { + ptrA token(getStringA("TokenSecret")); + ptrA steamId(getStringA("SteamID")); + + + for (size_t i = 0; i < json_size(nsessions); i++) + { + JSONNode *session = json_at(nsessions, i); + + node = json_get(session, "accountid_friend"); + const char *who = AccountIdToSteamId(_ttoi64(ptrT(json_as_string(node)))); + + node = json_get(session, "last_message"); + time_t lastMessageTS = _ttoi64(ptrT(json_as_string(node))); + + /*node = json_get(session, "last_view"); + time_t last_view = _ttoi64(ptrT(json_as_string(node))); + + node = json_get(session, "unread_message_count"); + long unread_count = json_as_int(node);*/ + + if (lastMessageTS > m_lastMessageTS) + { + PushRequest( + new GetHistoryMessagesRequest(token, steamId, who, m_lastMessageTS), + &CSteamProto::OnGotHistoryMessages, + mir_strdup(who), + MirFreeArg); + } + } + + json_delete(nsessions); + } +} + +void CSteamProto::OnGotHistoryMessages(const HttpResponse *response, void *arg) +{ + MCONTACT hContact = FindContact((char*)arg); + if (!hContact) + return; + + if (!ResponseHttpOk(response)) + return; + + JSONROOT root(response->pData); + if (root == NULL) + return; + + JSONNode *node = json_get(root, "response"); + + JSONNode *messages = json_get(node, "messages"); + JSONNode *nmessages = json_as_array(messages); + + // Self SteamID + ptrA steamId(getStringA("SteamID")); + + for (size_t i = json_size(nmessages) - 1; i >= 0; i--) + { + JSONNode *message = json_at(nmessages, i); + + node = json_get(message, "accountid"); + const char *authorSteamId = AccountIdToSteamId(_ttoi64(ptrT(json_as_string(node)))); + + node = json_get(message, "message"); + ptrT text(json_as_string(node)); + T2Utf szMessage(text); + + node = json_get(message, "timestamp"); + time_t timestamp = _ttoi64(ptrT(json_as_string(node))); + + PROTORECVEVENT recv = { 0 }; + recv.timestamp = timestamp; + recv.szMessage = szMessage; + + if (strcmp(steamId, authorSteamId)) + { + // Received message + ProtoChainRecvMsg(hContact, &recv); + } + else + { + // Sent message + recv.flags = PREF_SENT; + Proto_RecvMessage(hContact, &recv); + } + + // Update last message timestamp + if (timestamp > getDword("LastMessageTS", 0)) + setDword("LastMessageTS", timestamp); + } + + json_delete(nmessages); +} diff --git a/protocols/Steam/src/steam_polling.cpp b/protocols/Steam/src/steam_polling.cpp index 8086db033e..eadade3d99 100644 --- a/protocols/Steam/src/steam_polling.cpp +++ b/protocols/Steam/src/steam_polling.cpp @@ -215,6 +215,12 @@ void CSteamProto::PollingThread(void*) if (!lstrcmpi(error, _T("OK"))) { + // Remember last message timestamp + node = json_get(root, "timestamp"); + time_t lastMessageTS = _ttoi64(ptrT(json_as_string(node))); + if (lastMessageTS > getDword("LastMessageTS", 0)) + setDword("LastMessageTS", lastMessageTS); + node = json_get(root, "messagelast"); messageId = json_as_int(node); diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index 8d70098aa0..e0ec091bee 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -7,6 +7,7 @@ CSteamProto::CSteamProto(const char* protoName, const TCHAR* userName) CreateProtoService(PS_CREATEACCMGRUI, &CSteamProto::OnAccountManagerInit); m_idleTS = 0; + m_lastMessageTS = 0; isLoginAgain = false; m_hQueueThread = NULL; m_pollingConnection = NULL; @@ -319,6 +320,9 @@ int CSteamProto::SetStatus(int new_status) } else if (old_status == ID_STATUS_OFFLINE) { + // Load last message timestamp for correct loading of messages history + m_lastMessageTS = getDword("LastMessageTS", 0); + m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 3c282f35e7..88fb947eab 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -86,6 +86,12 @@ protected: mir_cs set_status_lock;
std::map<HANDLE, time_t> m_mpOutMessages;
+ /**
+ * Used only to compare in steam_history.cpp, others should write such value directly to db profile, because PollingThread
+ * may start sooner than steam_history requests so it could possibly break getting history messages from server
+ */
+ time_t m_lastMessageTS;
+
// instances
static LIST<CSteamProto> InstanceList;
static int CompareProtos(const CSteamProto *p1, const CSteamProto *p2);
@@ -162,6 +168,10 @@ protected: void OnMessageSent(const HttpResponse *response, void *arg);
int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam);
+ // history
+ void OnGotConversations(const HttpResponse *response);
+ void OnGotHistoryMessages(const HttpResponse *response, void *arg);
+
// menus
static int hChooserMenu;
static HGENMENU contactMenuItems[CMI_MAX];
@@ -231,6 +241,13 @@ protected: // ... or we can report real idle info
// return m_idleTS ? time(0) - m_idleTS : 0;
}
+
+ inline const char *AccountIdToSteamId(long long accountId)
+ {
+ static char steamId[20];
+ mir_snprintf(steamId, "%llu", accountId + 76561197960265728ll);
+ return steamId;
+ }
};
int OnReloadIcons(WPARAM wParam, LPARAM lParam);
|