diff options
author | George Hazan <ghazan@miranda.im> | 2017-01-19 20:22:23 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2017-01-19 20:22:23 +0300 |
commit | 92e81067e7e81cefcea58f7e91f6d2d8c959fd0d (patch) | |
tree | 469906fd6687a406c4ae232d0260ebe5f731c128 | |
parent | 79d4eb2e8e57025219e6c5680a88446c0a047b8f (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.cpp | 52 | ||||
-rw-r--r-- | protocols/Discord/src/proto.cpp | 5 | ||||
-rw-r--r-- | protocols/Discord/src/proto.h | 3 | ||||
-rw-r--r-- | protocols/Discord/src/server.cpp | 7 |
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); } ///////////////////////////////////////////////////////////////////////////////////////// |