diff options
author | George Hazan <ghazan@miranda.im> | 2017-01-07 22:57:57 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2017-01-07 22:57:57 +0300 |
commit | f1a204292b895a94f142c32b2f3dc69fcc053e67 (patch) | |
tree | 465127e97ce90f457c90b8cfc78ae8f0e00b5064 /protocols/Discord/src/dispatch.cpp | |
parent | e012650957335d5f4295441debf849b3b9b2f4ef (diff) |
first version of Discord that sends messages, catches presence packets and displays typing notification
version bump
Diffstat (limited to 'protocols/Discord/src/dispatch.cpp')
-rw-r--r-- | protocols/Discord/src/dispatch.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/protocols/Discord/src/dispatch.cpp b/protocols/Discord/src/dispatch.cpp index f9cf006a09..e96471f116 100644 --- a/protocols/Discord/src/dispatch.cpp +++ b/protocols/Discord/src/dispatch.cpp @@ -19,6 +19,102 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. extern HWND g_hwndHeartbeat; +#pragma pack(4) + +struct CDiscordCommand +{ + const wchar_t *szCommandId; + GatewayHandlerFunc pFunc; +} +static handlers[] = // these structures must me sorted alphabetically +{ + { L"MESSAGE_CREATE", &CDiscordProto::OnCommandMessage }, + { L"MESSAGE_UPDATE", &CDiscordProto::OnCommandMessage }, + + { L"PRESENCE_UPDATE", &CDiscordProto::OnCommandPresence }, + + { L"READY", &CDiscordProto::OnCommandReady }, + + { L"TYPING_START", &CDiscordProto::OnCommandTyping }, +}; + +static int __cdecl pSearchFunc(const void *p1, const void *p2) +{ + return wcscmp(((CDiscordCommand*)p1)->szCommandId, ((CDiscordCommand*)p2)->szCommandId); +} + +GatewayHandlerFunc CDiscordProto::GetHandler(const wchar_t *pwszCommand) +{ + CDiscordCommand tmp = { pwszCommand, NULL }; + CDiscordCommand *p = (CDiscordCommand*)bsearch(&tmp, handlers, _countof(handlers), sizeof(handlers[0]), pSearchFunc); + return (p != NULL) ? p->pFunc : NULL; +} + +////////////////////////////////////////////////////////////////////////////////////// +// reading a new message + +void CDiscordProto::OnCommandMessage(const JSONNode &pRoot) +{ + PROTORECVEVENT recv = {}; + + CDiscordUser *pUser = PrepareUser(pRoot["author"]); + SnowFlake channelId = _wtoi64(pRoot["channel_id"].as_mstring()); + CMStringW msgId = pRoot["id"].as_mstring(); + CMStringW wszText = pRoot["content"].as_mstring(); + + // if a message has myself as an author, mark it as sent + if (pUser->id == 0) + return; + + const JSONNode &edited = pRoot["edited_timestamp"]; + if (!edited.isnull()) + wszText.AppendFormat(L" (%s %s)", TranslateT("edited at"), edited.as_mstring().c_str()); + + if (pUser->channelId != channelId) { + debugLogA("failed to process a groupchat message, exiting"); + return; + } + + ptrA buf(mir_utf8encodeW(wszText)); + recv.timestamp = (DWORD)StringToDate(pRoot["timestamp"].as_mstring()); + recv.szMessage = buf; + recv.lParam = (LPARAM)msgId.c_str(); + ProtoChainRecvMsg(pUser->hContact, &recv); +} + +////////////////////////////////////////////////////////////////////////////////////// +// someone changed its status + +void CDiscordProto::OnCommandPresence(const JSONNode &pRoot) +{ + CDiscordUser *pUser = PrepareUser(pRoot["user"]); + if (pUser == NULL) + return; + + int iStatus; + CMStringW wszStatus = pRoot["status"].as_mstring(); + if (wszStatus == L"idle") + iStatus = ID_STATUS_IDLE; + else if (wszStatus == L"online") + iStatus = ID_STATUS_ONLINE; + else if (wszStatus == L"offline") + iStatus = ID_STATUS_OFFLINE; + else + iStatus = 0; + + if (iStatus != 0) + setWord(pUser->hContact, "Status", iStatus); + + CMStringW wszGame = pRoot["game"]["name"].as_mstring(); + if (!wszGame.IsEmpty()) + setWString(pUser->hContact, "XStatusMsg", wszGame); + else + delSetting(pUser->hContact, "XStatusMsg"); +} + +////////////////////////////////////////////////////////////////////////////////////// +// gateway session start + void CALLBACK CDiscordProto::HeartbeatTimerProc(HWND, UINT, UINT_PTR id, DWORD) { ((CDiscordProto*)id)->GatewaySendHeartbeat(); @@ -62,3 +158,27 @@ void CDiscordProto::OnCommandReady(const JSONNode &pRoot) setId(pUser->hContact, DB_KEY_CHANNELID, pUser->channelId); } } + +////////////////////////////////////////////////////////////////////////////////////// +// UTN support + +void CDiscordProto::OnCommandTyping(const JSONNode &pRoot) +{ + SnowFlake userId = _wtoi64(pRoot["user_id"].as_mstring()); + SnowFlake channelId = _wtoi64(pRoot["channel_id"].as_mstring()); + debugLogA("user typing notification: userid=%lld, channelid=%lld", userId, channelId); + + CDiscordUser *pUser = FindUser(userId); + if (pUser == NULL) { + debugLogA("user with id=%lld is not found", userId); + return; + } + + if (pUser->channelId == channelId) { + debugLogA("user is typing in his private channel"); + CallService(MS_PROTO_CONTACTISTYPING, pUser->hContact, 20); + } + else { + debugLogA("user is typing in a group channel, skipped"); + } +} |