summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/Steam/src/api/history.h27
-rw-r--r--protocols/Steam/src/stdafx.h1
-rw-r--r--protocols/Steam/src/steam_contacts.cpp8
-rw-r--r--protocols/Steam/src/steam_history.cpp121
-rw-r--r--protocols/Steam/src/steam_polling.cpp6
-rw-r--r--protocols/Steam/src/steam_proto.cpp4
-rw-r--r--protocols/Steam/src/steam_proto.h17
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);