summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2017-01-11 15:28:56 +0300
committerGeorge Hazan <ghazan@miranda.im>2017-01-11 15:29:06 +0300
commit499aee4b2b43b2835a4fb13410cd195fb5a4311a (patch)
tree2bb70f2b64a96b31ebbb32cec1d37e4b4465bc5c /protocols
parent16fe45e4297e335f76719fcade05999a45a85349 (diff)
message acks: read confirmations
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Discord/src/connection.cpp2
-rw-r--r--protocols/Discord/src/dispatch.cpp2
-rw-r--r--protocols/Discord/src/proto.cpp46
-rw-r--r--protocols/Discord/src/proto.h9
-rw-r--r--protocols/Discord/src/server.cpp21
-rw-r--r--protocols/Discord/src/stdafx.h1
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"