summaryrefslogtreecommitdiff
path: root/protocols/Discord/src/proto.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Discord/src/proto.cpp')
-rw-r--r--protocols/Discord/src/proto.cpp150
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) {