diff options
Diffstat (limited to 'protocols/Discord/src/proto.cpp')
-rw-r--r-- | protocols/Discord/src/proto.cpp | 150 |
1 files changed, 115 insertions, 35 deletions
diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp index f85df56fe3..ea3975a983 100644 --- a/protocols/Discord/src/proto.cpp +++ b/protocols/Discord/src/proto.cpp @@ -33,14 +33,24 @@ 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 CreateProtoService(PS_GETSTATUS, &CDiscordProto::GetStatus); + CreateProtoService(PS_CREATEACCMGRUI, &CDiscordProto::SvcCreateAccMgrUI); + + CreateProtoService(PS_GETAVATARINFO, &CDiscordProto::GetAvatarInfo); + CreateProtoService(PS_GETAVATARCAPS, &CDiscordProto::GetAvatarCaps); + CreateProtoService(PS_GETMYAVATAR, &CDiscordProto::GetMyAvatar); + CreateProtoService(PS_SETMYAVATAR, &CDiscordProto::SetMyAvatar); // Events HookProtoEvent(ME_OPT_INITIALISE, &CDiscordProto::OnOptionsInit); - HookProtoEvent(ME_MSG_WINDOWEVENT, &CDiscordProto::OnSrmmEvent); + HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CDiscordProto::OnDbEventRead); + + // database + db_set_resident(m_szModuleName, "XStatusMsg"); // Clist Clist_GroupCreate(NULL, m_wszDefaultGroup); @@ -91,7 +101,7 @@ DWORD_PTR CDiscordProto::GetCaps(int type, MCONTACT) return PF1_IM | PF1_MODEMSGRECV | PF1_SERVERCLIST | PF1_BASICSEARCH | PF1_EXTSEARCH | PF1_ADDSEARCHRES; case PFLAGNUM_2: case PFLAGNUM_3: - return PF2_ONLINE | PF2_HEAVYDND | PF2_INVISIBLE | PF2_IDLE; + return PF2_ONLINE | PF2_LONGAWAY | PF2_HEAVYDND | PF2_INVISIBLE; case PFLAGNUM_4: return PF4_FORCEADDED | PF4_FORCEAUTH | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_SUPPORTTYPING | PF4_SUPPORTIDLE | PF4_AVATARS | PF4_IMSENDOFFLINE; case PFLAG_UNIQUEIDTEXT: @@ -109,33 +119,34 @@ INT_PTR CDiscordProto::GetStatus(WPARAM, LPARAM) int CDiscordProto::SetStatus(int iNewStatus) { + debugLogA("CDiscordProto::SetStatus iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d m_hWorkerThread = %p", iNewStatus, m_iStatus, m_iDesiredStatus, m_hWorkerThread); + if (iNewStatus == m_iStatus) return 0; m_iDesiredStatus = iNewStatus; int iOldStatus = m_iStatus; - // all statuses but offline are treated as online - if (iNewStatus >= ID_STATUS_ONLINE && iNewStatus <= ID_STATUS_OUTTOLUNCH) { - m_iDesiredStatus = ID_STATUS_ONLINE; - - // if we're already connecting and they want to go online - if (IsStatusConnecting(m_iStatus)) - return 0; - - // if we're already connected, don't try to reconnect - if (m_iStatus >= ID_STATUS_ONLINE && m_iStatus <= ID_STATUS_OUTTOLUNCH) - return 0; + // go offline + if (iNewStatus == ID_STATUS_OFFLINE) { + if (m_bOnline) { + SetServerStatus(ID_STATUS_OFFLINE); + ShutdownSession(); + } + m_iStatus = m_iDesiredStatus; + SetAllContactStatuses(ID_STATUS_OFFLINE); + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); + } + // not logged in? come on + else if (m_hWorkerThread == NULL && !IsStatusConnecting(m_iStatus)) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); m_hWorkerThread = ForkThreadEx(&CDiscordProto::ServerThread, NULL, NULL); } - else if (iNewStatus == ID_STATUS_OFFLINE) { - m_iStatus = m_iDesiredStatus; - SetAllContactStatuses(ID_STATUS_OFFLINE); - - ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); + else if (m_bOnline) { + debugLogA("setting server online status to %d", iNewStatus); + SetServerStatus(iNewStatus); } return 0; @@ -258,6 +269,92 @@ MCONTACT CDiscordProto::AddToList(int flags, PROTOSEARCHRESULT *psr) return hContact; } +//////////////////////////////////////////////////////////////////////////////////////// +// RecvMsg + +int CDiscordProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *evt) +{ + T2Utf szResUtf((const wchar_t*)evt->lParam); + evt->pCustomData = (char*)szResUtf; + evt->cbCustomDataSize = (DWORD)mir_strlen(szResUtf); + Proto_RecvMessage(hContact, evt); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// SendMsg + +void __cdecl CDiscordProto::SendMessageAckThread(void *param) +{ + Sleep(100); + ProtoBroadcastAck((MCONTACT)param, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate("Protocol is offline or no JID")); +} + +int CDiscordProto::SendMsg(MCONTACT hContact, int /*flags*/, const char *pszSrc) +{ + if (!m_bOnline) { + ForkThread(&CDiscordProto::SendMessageAckThread, (void*)hContact); + return 1; + } + + ptrW wszText(mir_utf8decodeW(pszSrc)); + if (wszText == NULL) + return 0; + + CDiscordUser *pUser = FindUser(getId(hContact, DB_KEY_ID)); + if (pUser == NULL || pUser->channelId == NULL) + return 0; + + CMStringA szUrl(FORMAT, "/channels/%lld/messages", pUser->channelId); + JSONNode body; body << WCHAR_PARAM("content", wszText); + AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, szUrl, &CDiscordProto::OnReceiveMessage, &body); + pReq->pUserInfo = (void*)hContact; + Push(pReq); + return pReq->m_iReqNum; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +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) @@ -279,23 +376,6 @@ int CDiscordProto::OnPreShutdown(WPARAM, LPARAM) ///////////////////////////////////////////////////////////////////////////////////////// -int CDiscordProto::OnSrmmEvent(WPARAM, LPARAM lParam) -{ - MessageWindowEventData *MWeventdata = (MessageWindowEventData*)lParam; - - if (MWeventdata->uType == MSG_WINDOW_EVT_OPENING && MWeventdata->hContact) { - SnowFlake oldid = getId(MWeventdata->hContact, DB_KEY_LASTMSGID); - if (oldid > 0) - RetrieveHistory(MWeventdata->hContact, MSG_AFTER, oldid, 99); - else - RetrieveHistory(MWeventdata->hContact, MSG_NOFILTER, 0, 99); - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - int CDiscordProto::OnEvent(PROTOEVENTTYPE event, WPARAM wParam, LPARAM lParam) { switch (event) { |