From 340d879890f5099c21e36fc147d6432a1ac050bf Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 5 Apr 2015 11:10:02 +0000 Subject: SteamWeb: - fixed logout (patck from MikalaiR) - fixed action (/me) sending - added message duplication filter git-svn-id: http://svn.miranda-ng.org/main/trunk@12604 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/src/http_request.h | 2 +- protocols/SkypeWeb/src/requests/logout.h | 1 + protocols/SkypeWeb/src/requests/messages.h | 4 +- protocols/SkypeWeb/src/skype_messages.cpp | 97 ++++++++++++++++-------- protocols/SkypeWeb/src/skype_poll_processing.cpp | 11 ++- protocols/SkypeWeb/src/skype_proto.cpp | 8 ++ protocols/SkypeWeb/src/skype_proto.h | 8 +- protocols/SkypeWeb/src/skype_utils.cpp | 12 +++ 8 files changed, 108 insertions(+), 35 deletions(-) (limited to 'protocols/SkypeWeb/src') diff --git a/protocols/SkypeWeb/src/http_request.h b/protocols/SkypeWeb/src/http_request.h index e39bdf3032..50e9528dfd 100644 --- a/protocols/SkypeWeb/src/http_request.h +++ b/protocols/SkypeWeb/src/http_request.h @@ -34,7 +34,7 @@ struct FORMAT_VALUE : public VALUE } }; -class HttpRequest : private NETLIBHTTPREQUEST, public MZeroedObject +class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject { private: va_list formatArgs; diff --git a/protocols/SkypeWeb/src/requests/logout.h b/protocols/SkypeWeb/src/requests/logout.h index 989a36776e..f8b07ce713 100644 --- a/protocols/SkypeWeb/src/requests/logout.h +++ b/protocols/SkypeWeb/src/requests/logout.h @@ -6,6 +6,7 @@ class LogoutRequest : public HttpRequest public: LogoutRequest() : HttpRequest(REQUEST_GET, "login.skype.com/logout") { + flags |= NLHRF_REDIRECT; Url << INT_VALUE("client_id", 578134) << CHAR_VALUE("redirect_uri", "https%3A%2F%2Fweb.skype.com&intsrc=client-_-webapp-_-production-_-go-signin"); diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h index 8dde3f9b5a..130dd0c938 100644 --- a/protocols/SkypeWeb/src/requests/messages.h +++ b/protocols/SkypeWeb/src/requests/messages.h @@ -1,10 +1,10 @@ #ifndef _SKYPE_REQUEST_MESSAGES_H_ #define _SKYPE_REQUEST_MESSAGES_H_ -class SendMsgRequest : public HttpRequest +class SendMessageRequest : public HttpRequest { public: - SendMsgRequest(const char *regToken, const char *username, time_t timestamp, const char *message, const char *server = "client-s.gateway.messenger.live.com") : + SendMessageRequest(const char *regToken, const char *username, time_t timestamp, const char *message, const char *server = "client-s.gateway.messenger.live.com") : HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/conversations/8:%s/messages", server, username) { Headers diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index 89231ff905..6893feb2a3 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -1,30 +1,63 @@ #include "common.h" +MEVENT CSkypeProto::GetMessageFromDB(MCONTACT hContact, DWORD timestamp, const char *messageId) +{ + mir_cslock lock(messageSyncLock); + + size_t messageIdLength = mir_strlen(messageId); + for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) + { + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.cbBlob = db_event_getBlobSize(hDbEvent); + if (dbei.cbBlob < messageIdLength) + continue; + + mir_ptr blob((PBYTE)mir_alloc(dbei.cbBlob)); + dbei.pBlob = blob; + db_event_get(hDbEvent, &dbei); + + if (dbei.timestamp < timestamp) + break; + + if ((dbei.eventType == EVENTTYPE_MESSAGE || dbei.eventType == SKYPE_DB_EVENT_TYPE_ACTION)) + if (memcmp(&dbei.pBlob[dbei.cbBlob - messageIdLength], messageId, messageIdLength) == 0) + return hDbEvent; + } + + return NULL; +} + +MEVENT CSkypeProto::AddMessageToDb(MCONTACT hContact, DWORD timestamp, DWORD flags, const char *messageId, char *content, int emoteOffset) +{ + if (MEVENT hDbEvent = GetMessageFromDB(hContact, timestamp, messageId)) + return hDbEvent; + + size_t messageLength = mir_strlen(&content[emoteOffset]) + 1; + size_t messageIdLength = mir_strlen(messageId); + size_t cbBlob = messageLength + messageIdLength; + PBYTE pBlob = (PBYTE)mir_alloc(cbBlob); + memcpy(pBlob, &content[emoteOffset], messageLength); + memcpy(pBlob + messageLength, messageId, messageIdLength); + + return AddEventToDb(hContact, emoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, timestamp, flags, cbBlob, pBlob); +} + /* MESSAGE RECEIVING */ // incoming message flow -int CSkypeProto::OnReceiveMessage(const char *messageId, const char *from, const char *to, time_t timestamp, char *content, int emoteOffset, bool isRead) +int CSkypeProto::OnReceiveMessage(const char *messageId, const char *skypename, time_t timestamp, char *content, int emoteOffset, bool isRead) { setDword("LastMsgTime", timestamp); PROTORECVEVENT recv = { 0 }; recv.flags = PREF_UTF; recv.timestamp = timestamp; - recv.szMessage = &content[emoteOffset]; - recv.lParam = emoteOffset == 0 - ? EVENTTYPE_MESSAGE - : SKYPE_DB_EVENT_TYPE_ACTION; + recv.szMessage = content; + recv.lParam = emoteOffset; recv.pCustomData = (void*)messageId; recv.cbCustomDataSize = mir_strlen(messageId); if (isRead) recv.flags |= PREF_CREATEREAD; - ptrA skypename(ContactUrlToName(from)); debugLogA("Incoming message from %s", skypename); - if (IsMe(skypename)) - { - recv.flags |= PREF_SENT; - MCONTACT hContact = GetContact(ptrA(ContactUrlToName(to))); - return SaveMessageToDb(hContact, &recv); - } MCONTACT hContact = GetContact(skypename); return ProtoChainRecvMsg(hContact, &recv); } @@ -36,19 +69,13 @@ int CSkypeProto::SaveMessageToDb(MCONTACT hContact, PROTORECVEVENT *pre) if (pre->szMessage == NULL) return NULL; - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.szModule = GetContactProto(hContact); - dbei.timestamp = pre->timestamp; - dbei.flags = DBEF_UTF; + int flags = DBEF_UTF; if ((pre->flags & PREF_CREATEREAD) == PREF_CREATEREAD) - dbei.flags |= DBEF_READ; + flags |= DBEF_READ; if ((pre->flags & PREF_SENT) == PREF_SENT) - dbei.flags |= DBEF_SENT; - dbei.eventType = pre->lParam; - dbei.cbBlob = (DWORD)strlen(pre->szMessage) + 1; - dbei.pBlob = (PBYTE)pre->szMessage; + flags |= DBEF_SENT; - return (INT_PTR)db_event_add(hContact, &dbei); + return AddMessageToDb(hContact, pre->timestamp, flags, (char*)pre->pCustomData, pre->szMessage, pre->lParam); } /* MESSAGE SENDING */ @@ -87,10 +114,9 @@ int CSkypeProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessa ptrA username(getStringA(hContact, "Skypename")); if (strncmp(message, "/me ", 4) == 0) { - // TODO: make /me action send when it will work in skype web + // TODO: make /me action send support } - PushRequest(new SendMsgRequest(token, username, timestamp, message, server), &CSkypeProto::OnMessageSent, param); - + PushRequest(new SendMessageRequest(token, username, timestamp, message, server), &CSkypeProto::OnMessageSent, param); return timestamp; } @@ -115,8 +141,6 @@ void CSkypeProto::OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg) ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, hMessage, (LPARAM)error.GetBuffer()); return; } - - ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, hMessage, 0); } // preparing message/action to writing into db @@ -130,14 +154,14 @@ int CSkypeProto::OnPreCreateMessage(WPARAM, LPARAM lParam) if (strncmp(message, "/me ", 4) == 0) { evt->dbei->cbBlob = evt->dbei->cbBlob - 4; - memcpy(&evt->dbei->pBlob, &evt->dbei->pBlob[4], evt->dbei->cbBlob); + memmove(evt->dbei->pBlob, &evt->dbei->pBlob[4], evt->dbei->cbBlob); evt->dbei->eventType = SKYPE_DB_EVENT_TYPE_ACTION; } char messageId[20]; itoa(evt->seq, messageId, 10); int messageIdLength = mir_strlen(messageId); evt->dbei->pBlob = (PBYTE)mir_realloc(evt->dbei->pBlob, evt->dbei->cbBlob + messageIdLength); - memcpy((char *)&evt->dbei->pBlob[evt->dbei->cbBlob], messageId, messageIdLength); + memcpy(&evt->dbei->pBlob[evt->dbei->cbBlob], messageId, messageIdLength); evt->dbei->cbBlob += messageIdLength; return 1; @@ -170,7 +194,20 @@ void CSkypeProto::OnGetServerHistory(const NETLIBHTTPREQUEST *response) if (conversationLink != NULL && strstr(conversationLink, "/8:")) { int emoteOffset = json_as_int(json_get(message, "skypeemoteoffset")); - OnReceiveMessage(clientMsgId, from, conversationLink, timestamp, content, emoteOffset, true); + + int flags = DBEF_UTF | DBEF_READ; + + ptrA skypename(ContactUrlToName(from)); + + bool isMe = IsMe(skypename); + if (isMe) + flags |= DBEF_READ; + + MCONTACT hContact = IsMe(skypename) + ? GetContact(ptrA(ContactUrlToName(conversationLink))) + : GetContact(skypename); + + AddMessageToDb(hContact, timestamp, flags, clientMsgId, content, emoteOffset); } } } \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_poll_processing.cpp b/protocols/SkypeWeb/src/skype_poll_processing.cpp index 9f0cc24fa1..fc20ed6683 100644 --- a/protocols/SkypeWeb/src/skype_poll_processing.cpp +++ b/protocols/SkypeWeb/src/skype_poll_processing.cpp @@ -106,7 +106,16 @@ void CSkypeProto::ProcessNewMessageRes(JSONNODE *node) else if (!mir_strcmpi(messageType, "Text") || !mir_strcmpi(messageType, "RichText")) { int emoteOffset = json_as_int(json_get(node, "skypeemoteoffset")); - OnReceiveMessage(clientMsgId, from, conversationLink, timestamp, content, emoteOffset); + ptrA skypename(ContactUrlToName(from)); + if (IsMe(skypename)) + { + MCONTACT hContact = GetContact(ptrA(ContactUrlToName(conversationLink))); + int hMessage = atoi(clientMsgId); + ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)hMessage, 0); + AddMessageToDb(hContact, timestamp, DBEF_UTF | DBEF_SENT, clientMsgId, &content[emoteOffset], emoteOffset); + return; + } + OnReceiveMessage(clientMsgId, from, timestamp, content, emoteOffset); } else if (!mir_strcmpi(messageType, "Event/SkypeVideoMessage")) { diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index f7ceb14f7c..38d466208b 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -17,6 +17,14 @@ PROTO(protoName, userName), password(NULL) requestQueue = new RequestQueue(m_hNetlibUser); CreateProtoService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit); + + // custom event + DBEVENTTYPEDESCR dbEventType = { sizeof(dbEventType) }; + dbEventType.module = m_szModuleName; + dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW; + dbEventType.eventType = SKYPE_DB_EVENT_TYPE_ACTION; + dbEventType.descr = Translate("Action"); + CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&dbEventType); } CSkypeProto::~CSkypeProto() diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 52219480d1..27db01cf6d 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -174,7 +174,12 @@ private: int __cdecl OnContactDeleted(MCONTACT, LPARAM); // messages - int OnReceiveMessage(const char *messageId, const char *from, const char *to, time_t timestamp, char *content, int emoteOffset = 0, bool isRead = false); + mir_cs messageSyncLock; + + MEVENT GetMessageFromDB(MCONTACT hContact, DWORD timestamp, const char *messageId); + MEVENT AddMessageToDb(MCONTACT hContact, DWORD timestamp, DWORD flags, const char *messageId, char *content, int emoteOffset = 0); + + int OnReceiveMessage(const char *messageId, const char *skypename, time_t timestamp, char *content, int emoteOffset = 0, bool isRead = false); int SaveMessageToDb(MCONTACT hContact, PROTORECVEVENT *pre); int OnSendMessage(MCONTACT hContact, int flags, const char *message); @@ -192,6 +197,7 @@ private: // utils bool IsOnline(); + MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob); time_t __stdcall IsoToUnixTime(const TCHAR *stamp); char *GetStringChunk(const char *haystack, size_t len, const char *start, const char *end); bool IsMe(const char *skypeName); diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index 0ec221a7e5..d9c1501b0b 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -5,6 +5,18 @@ bool CSkypeProto::IsOnline() return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread; } +MEVENT CSkypeProto::AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob) +{ + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = this->m_szModuleName; + dbei.timestamp = timestamp; + dbei.eventType = type; + dbei.cbBlob = cbBlob; + dbei.pBlob = pBlob; + dbei.flags = flags; + return db_event_add(hContact, &dbei); +} + time_t __stdcall CSkypeProto::IsoToUnixTime(const TCHAR *stamp) { TCHAR date[9]; -- cgit v1.2.3