diff options
author | George Hazan <ghazan@miranda.im> | 2017-01-11 15:28:56 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2017-01-11 15:29:06 +0300 |
commit | 499aee4b2b43b2835a4fb13410cd195fb5a4311a (patch) | |
tree | 2bb70f2b64a96b31ebbb32cec1d37e4b4465bc5c | |
parent | 16fe45e4297e335f76719fcade05999a45a85349 (diff) |
message acks: read confirmations
-rw-r--r-- | protocols/Discord/src/connection.cpp | 2 | ||||
-rw-r--r-- | protocols/Discord/src/dispatch.cpp | 2 | ||||
-rw-r--r-- | protocols/Discord/src/proto.cpp | 46 | ||||
-rw-r--r-- | protocols/Discord/src/proto.h | 9 | ||||
-rw-r--r-- | protocols/Discord/src/server.cpp | 21 | ||||
-rw-r--r-- | protocols/Discord/src/stdafx.h | 1 |
6 files changed, 76 insertions, 5 deletions
diff --git a/protocols/Discord/src/connection.cpp b/protocols/Discord/src/connection.cpp index 3b82e4112b..d3c44b2d9a 100644 --- a/protocols/Discord/src/connection.cpp +++ b/protocols/Discord/src/connection.cpp @@ -77,6 +77,8 @@ void CDiscordProto::OnLoggedOut() m_bTerminated = true; m_iGatewaySeq = 0; + KillTimer(g_hwndHeartbeat, (UINT_PTR)this); + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_OFFLINE); m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; } diff --git a/protocols/Discord/src/dispatch.cpp b/protocols/Discord/src/dispatch.cpp index a2f0320b08..8d314e0836 100644 --- a/protocols/Discord/src/dispatch.cpp +++ b/protocols/Discord/src/dispatch.cpp @@ -17,8 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h" -extern HWND g_hwndHeartbeat; - #pragma pack(4) struct CDiscordCommand diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp index e8ac7c269c..ea3975a983 100644 --- a/protocols/Discord/src/proto.cpp +++ b/protocols/Discord/src/proto.cpp @@ -33,6 +33,7 @@ CDiscordProto::CDiscordProto(const char *proto_name, const wchar_t *username) : m_evRequestsQueue(CreateEvent(NULL, FALSE, FALSE, NULL)), m_wszDefaultGroup(this, DB_KEY_GROUP, DB_KEYVAL_GROUP), m_wszEmail(this, DB_KEY_EMAIL, L""), + arMarkReadQueue(1, compareUsers), arUsers(50, compareUsers) { // Services @@ -46,6 +47,7 @@ CDiscordProto::CDiscordProto(const char *proto_name, const wchar_t *username) : // Events HookProtoEvent(ME_OPT_INITIALISE, &CDiscordProto::OnOptionsInit); + HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CDiscordProto::OnDbEventRead); // database db_set_resident(m_szModuleName, "XStatusMsg"); @@ -305,7 +307,7 @@ int CDiscordProto::SendMsg(MCONTACT hContact, int /*flags*/, const char *pszSrc) CMStringA szUrl(FORMAT, "/channels/%lld/messages", pUser->channelId); JSONNode body; body << WCHAR_PARAM("content", wszText); - AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, szUrl, &CDiscordProto::OnReceiveMessageAck, &body); + AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, szUrl, &CDiscordProto::OnReceiveMessage, &body); pReq->pUserInfo = (void*)hContact; Push(pReq); return pReq->m_iReqNum; @@ -313,6 +315,48 @@ int CDiscordProto::SendMsg(MCONTACT hContact, int /*flags*/, const char *pszSrc) ///////////////////////////////////////////////////////////////////////////////////////// +void CDiscordProto::MarkReadTimerProc(HWND hwnd, UINT, UINT_PTR id, DWORD) +{ + CDiscordProto *ppro = (CDiscordProto*)(id - 1); + + JSONNode root; root.push_back(JSONNode("token", NULL)); + + mir_cslock lck(ppro->csMarkReadQueue); + while (ppro->arMarkReadQueue.getCount()) { + CDiscordUser *pUser = ppro->arMarkReadQueue[0]; + CMStringA szUrl(FORMAT, "/channels/%lld/messages/%lld/ack", pUser->channelId, pUser->lastMessageId); + ppro->Push(new AsyncHttpRequest(ppro, REQUEST_POST, szUrl, &CDiscordProto::OnReceiveMessageAck)); + ppro->arMarkReadQueue.remove(0); + } + KillTimer(hwnd, id); +} + +int CDiscordProto::OnDbEventRead(WPARAM, LPARAM hDbEvent) +{ + MCONTACT hContact = db_event_getContact(hDbEvent); + if (!hContact) + return 0; + + // filter out only events of my protocol + const char *szProto = GetContactProto(hContact); + if (mir_strcmp(szProto, m_szModuleName)) + return 0; + + if (m_bOnline) { + SetTimer(g_hwndHeartbeat, UINT_PTR(this) + 1, 200, &CDiscordProto::MarkReadTimerProc); + + CDiscordUser *pUser = FindUser(getId(hContact, DB_KEY_ID)); + if (pUser != NULL) { + mir_cslock lck(csMarkReadQueue); + if (arMarkReadQueue.indexOf(pUser) == -1) + arMarkReadQueue.insert(pUser); + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + int CDiscordProto::OnModulesLoaded(WPARAM, LPARAM) { return 0; diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h index 21f59e3377..f9a0c99481 100644 --- a/protocols/Discord/src/proto.h +++ b/protocols/Discord/src/proto.h @@ -173,6 +173,9 @@ class CDiscordProto : public PROTO<CDiscordProto> SnowFlake m_ownId; + mir_cs csMarkReadQueue; + LIST<CDiscordUser> arMarkReadQueue; + OBJLIST<CDiscordUser> arUsers; CDiscordUser* FindUser(SnowFlake id); CDiscordUser* FindUser(const wchar_t *pwszUsername, int iDiscriminator); @@ -222,6 +225,7 @@ public: int __cdecl OnModulesLoaded(WPARAM, LPARAM); int __cdecl OnPreShutdown(WPARAM, LPARAM); int __cdecl OnOptionsInit(WPARAM, LPARAM); + int __cdecl OnDbEventRead(WPARAM, LPARAM); // dispatch commands void OnCommandMessage(const JSONNode&); @@ -238,6 +242,7 @@ public: void OnReceiveFriends(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveGateway(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveGuilds(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveMessageAck(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveToken(NETLIBHTTPREQUEST*, AsyncHttpRequest*); @@ -255,6 +260,8 @@ public: CMStringW GetAvatarFilename(MCONTACT hContact); - static void CALLBACK HeartbeatTimerProc(HWND hwnd, UINT msg, UINT_PTR id, DWORD); __forceinline int getHeartbeatInterval() const { return m_iHartbeatInterval; } + + static void CALLBACK HeartbeatTimerProc(HWND hwnd, UINT msg, UINT_PTR id, DWORD); + static void CALLBACK MarkReadTimerProc(HWND hwnd, UINT msg, UINT_PTR id, DWORD); }; diff --git a/protocols/Discord/src/server.cpp b/protocols/Discord/src/server.cpp index 82b6113dfc..270127a904 100644 --- a/protocols/Discord/src/server.cpp +++ b/protocols/Discord/src/server.cpp @@ -241,7 +241,7 @@ void CDiscordProto::OnReceiveGuilds(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest* ///////////////////////////////////////////////////////////////////////////////////////// -void CDiscordProto::OnReceiveMessageAck(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CDiscordProto::OnReceiveMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) { MCONTACT hContact = (MCONTACT)pReq->pUserInfo; @@ -262,6 +262,25 @@ void CDiscordProto::OnReceiveMessageAck(NETLIBHTTPREQUEST *pReply, AsyncHttpRequ ///////////////////////////////////////////////////////////////////////////////////////// +void CDiscordProto::OnReceiveMessageAck(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +{ + if (pReply->resultCode != 200) + return; + + JSONNode root = JSONNode::parse(pReply->pData); + if (!root) + return; + + CMStringW wszToken(root["token"].as_mstring()); + if (!wszToken.IsEmpty()) { + JSONNode props; props.set_name("properties"); + root << CHAR_PARAM("event", "ack_messages") << props; + Push(new AsyncHttpRequest(this, REQUEST_POST, "/track", NULL, &root)); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + void CDiscordProto::OnReceiveToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) { if (pReply->resultCode != 200) { diff --git a/protocols/Discord/src/stdafx.h b/protocols/Discord/src/stdafx.h index 80d87bc6de..9bf1ba7cc1 100644 --- a/protocols/Discord/src/stdafx.h +++ b/protocols/Discord/src/stdafx.h @@ -44,6 +44,7 @@ #include "../../libs/zlib/src/zlib.h" extern HINSTANCE g_hInstance; +extern HWND g_hwndHeartbeat; #include "version.h" #include "proto.h" |