summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2017-01-19 20:22:23 +0300
committerGeorge Hazan <ghazan@miranda.im>2017-01-19 20:22:23 +0300
commit92e81067e7e81cefcea58f7e91f6d2d8c959fd0d (patch)
tree469906fd6687a406c4ae232d0260ebe5f731c128
parent79d4eb2e8e57025219e6c5680a88446c0a047b8f (diff)
Discord:
- added support for channel addition & removal; - added support for reading message acks; - now Miranda reads the whole history, not only first 99 messages -
-rw-r--r--protocols/Discord/src/dispatch.cpp52
-rw-r--r--protocols/Discord/src/proto.cpp5
-rw-r--r--protocols/Discord/src/proto.h3
-rw-r--r--protocols/Discord/src/server.cpp7
4 files changed, 56 insertions, 11 deletions
diff --git a/protocols/Discord/src/dispatch.cpp b/protocols/Discord/src/dispatch.cpp
index 80239a9b5e..74672391ca 100644
--- a/protocols/Discord/src/dispatch.cpp
+++ b/protocols/Discord/src/dispatch.cpp
@@ -26,6 +26,10 @@ struct CDiscordCommand
}
static handlers[] = // these structures must me sorted alphabetically
{
+ { L"CHANNEL_CREATE", &CDiscordProto::OnChannelCreated },
+ { L"CHANNEL_DELETE", &CDiscordProto::OnChannelDeleted },
+
+ { L"MESSAGE_ACK", &CDiscordProto::OnCommandMessageAck },
{ L"MESSAGE_CREATE", &CDiscordProto::OnCommandMessage },
{ L"MESSAGE_UPDATE", &CDiscordProto::OnCommandMessage },
@@ -54,6 +58,27 @@ GatewayHandlerFunc CDiscordProto::GetHandler(const wchar_t *pwszCommand)
}
//////////////////////////////////////////////////////////////////////////////////////
+// channel operations
+
+void CDiscordProto::OnChannelCreated(const JSONNode &pRoot)
+{
+ CDiscordUser *pUser = PrepareUser(pRoot["user"]);
+ if (pUser != NULL) {
+ pUser->channelId = _wtoi64(pRoot["id"].as_mstring());
+ setId(pUser->hContact, DB_KEY_CHANNELID, pUser->channelId);
+ }
+}
+
+void CDiscordProto::OnChannelDeleted(const JSONNode &pRoot)
+{
+ CDiscordUser *pUser = FindUserByChannel(pRoot["channel_id"]);
+ if (pUser != NULL) {
+ pUser->channelId = 0;
+ delSetting(pUser->hContact, DB_KEY_CHANNELID);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
// reading a new message
void CDiscordProto::OnCommandFriendAdded(const JSONNode &pRoot)
@@ -91,18 +116,17 @@ void CDiscordProto::OnCommandMessage(const JSONNode &pRoot)
return;
}
- CDiscordUser *pUser = PrepareUser(pRoot["author"]);
+ // try to find a sender by his channel
SnowFlake channelId = _wtoi64(pRoot["channel_id"].as_mstring());
+ CDiscordUser *pUser = FindUserByChannel(channelId);
+ if (pUser == NULL) {
+ debugLogA("skipping message with unknown channel id=%lld", channelId);
+ return;
+ }
- // if a message has myself as an author, find the author via channel id
- if (pUser->id == 0) {
- pUser = FindUserByChannel(channelId);
- if (pUser == NULL) {
- debugLogA("skipping message with unknown channel id=%lld", channelId);
- return;
- }
+ // if a message has myself as an author, add some flags
+ if (_wtoi64(pRoot["author"]["id"].as_mstring()) == m_ownId)
recv.flags = PREF_CREATEREAD | PREF_SENT;
- }
CMStringW wszText = pRoot["content"].as_mstring();
@@ -129,6 +153,16 @@ void CDiscordProto::OnCommandMessage(const JSONNode &pRoot)
//////////////////////////////////////////////////////////////////////////////////////
// someone changed its status
+void CDiscordProto::OnCommandMessageAck(const JSONNode &pRoot)
+{
+ CDiscordUser *pUser = FindUserByChannel(pRoot["channel_id"]);
+ if (pUser != NULL)
+ pUser->lastMessageId = _wtoi64(pRoot["message_id"].as_mstring());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// someone changed its status
+
void CDiscordProto::OnCommandPresence(const JSONNode &pRoot)
{
CDiscordUser *pUser = PrepareUser(pRoot["user"]);
diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp
index f161d27e49..83cc7c1941 100644
--- a/protocols/Discord/src/proto.cpp
+++ b/protocols/Discord/src/proto.cpp
@@ -350,10 +350,13 @@ int CDiscordProto::SendMsg(MCONTACT hContact, int /*flags*/, const char *pszSrc)
if (pUser == NULL || pUser->channelId == NULL)
return 0;
- CMStringA szUrl(FORMAT, "/channels/%lld/messages", pUser->channelId);
+ // we generate a random 64-bit integer and pass it to the server
+ // to distinguish our own messages from these generated by another clients
SnowFlake nonce; Utils_GetRandom(&nonce, sizeof(nonce));
JSONNode body; body << WCHAR_PARAM("content", wszText) << INT64_PARAM("nonce", nonce);
arOwnMessages.insert(new SnowFlake(nonce));
+
+ CMStringA szUrl(FORMAT, "/channels/%lld/messages", pUser->channelId);
AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, szUrl, &CDiscordProto::OnReceiveMessage, &body);
pReq->pUserInfo = (void*)hContact;
Push(pReq);
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h
index fec13c787c..3631c1237a 100644
--- a/protocols/Discord/src/proto.h
+++ b/protocols/Discord/src/proto.h
@@ -232,9 +232,12 @@ public:
int __cdecl OnDbEventRead(WPARAM, LPARAM);
// dispatch commands
+ void OnChannelCreated(const JSONNode&);
+ void OnChannelDeleted(const JSONNode&);
void OnCommandFriendAdded(const JSONNode&);
void OnCommandFriendRemoved(const JSONNode&);
void OnCommandMessage(const JSONNode&);
+ void OnCommandMessageAck(const JSONNode&);
void OnCommandPresence(const JSONNode&);
void OnCommandReady(const JSONNode&);
void OnCommandTyping(const JSONNode&);
diff --git a/protocols/Discord/src/server.cpp b/protocols/Discord/src/server.cpp
index ee4aa23204..e8cc6a752f 100644
--- a/protocols/Discord/src/server.cpp
+++ b/protocols/Discord/src/server.cpp
@@ -65,7 +65,8 @@ void CDiscordProto::OnReceiveHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest
SnowFlake lastId = getId(pUser->hContact, DB_KEY_LASTMSGID); // as stored in a database
- for (auto it = root.begin(); it != root.end(); ++it) {
+ int iNumMessages = 0;
+ for (auto it = root.begin(); it != root.end(); ++it, ++iNumMessages) {
JSONNode &p = *it;
SnowFlake authorid = _wtoi64(p["author"]["id"].as_mstring());
@@ -89,6 +90,10 @@ void CDiscordProto::OnReceiveHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest
}
setId(pUser->hContact, DB_KEY_LASTMSGID, lastId);
+
+ // if we fetched 99 messages, but have smth more to go, continue fetching
+ if (iNumMessages == 99 && lastId < pUser->lastMessageId)
+ RetrieveHistory(pUser->hContact, MSG_AFTER, lastId, 99);
}
/////////////////////////////////////////////////////////////////////////////////////////