From 3b576fbd2dc5359c9c2e3b79633f77ec97d307c9 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 16 Apr 2020 20:27:26 +0300 Subject: SkypeWeb: - fixes #2306 (SkypeWeb: sometimes plugin does not show contacts statuses); - obsoleted GetContactsInfoRequest removed (as well as its handler CSkypeProto::LoadContactsInfo); - major optimization for polling process; - ugly & crashy map Contacts removed; - old crappy timer code removed and replaced with CTimer; - version bump --- protocols/SkypeWeb/src/requests/contacts.h | 15 ----- protocols/SkypeWeb/src/requests/poll.h | 4 ++ protocols/SkypeWeb/src/requests/status.h | 13 +++++ protocols/SkypeWeb/src/skype_avatars.cpp | 2 +- protocols/SkypeWeb/src/skype_chatrooms.cpp | 2 +- protocols/SkypeWeb/src/skype_contacts.cpp | 49 +++------------- protocols/SkypeWeb/src/skype_dialogs.cpp | 13 ++--- protocols/SkypeWeb/src/skype_files.cpp | 4 +- protocols/SkypeWeb/src/skype_history_sync.cpp | 2 +- protocols/SkypeWeb/src/skype_login.cpp | 6 +- protocols/SkypeWeb/src/skype_messages.cpp | 2 +- protocols/SkypeWeb/src/skype_polling.cpp | 9 ++- protocols/SkypeWeb/src/skype_proto.cpp | 20 +++---- protocols/SkypeWeb/src/skype_proto.h | 83 ++++++++++++--------------- protocols/SkypeWeb/src/skype_timers.cpp | 51 ---------------- protocols/SkypeWeb/src/skype_trouter.cpp | 57 ++++++++++++++++++ protocols/SkypeWeb/src/skype_utils.cpp | 1 - protocols/SkypeWeb/src/version.h | 2 +- 18 files changed, 148 insertions(+), 187 deletions(-) delete mode 100644 protocols/SkypeWeb/src/skype_timers.cpp diff --git a/protocols/SkypeWeb/src/requests/contacts.h b/protocols/SkypeWeb/src/requests/contacts.h index 880e9c33d1..430b51aa2f 100644 --- a/protocols/SkypeWeb/src/requests/contacts.h +++ b/protocols/SkypeWeb/src/requests/contacts.h @@ -35,21 +35,6 @@ public: } }; -class GetContactsInfoRequest : public HttpRequest -{ -public: - GetContactsInfoRequest(CSkypeProto *ppro, const LIST &skypenames, const char *skypename = "self") : - HttpRequest(REQUEST_POST, FORMAT, "api.skype.com/users/%s/contacts/profiles", skypename) - { - Headers - << CHAR_VALUE("X-Skypetoken", ppro->m_szApiToken) - << CHAR_VALUE("Accept", "application/json"); - - for (auto &it : skypenames) - Body << CHAR_VALUE("contacts[]", it); - } -}; - class GetContactsAuthRequest : public HttpRequest { public: diff --git a/protocols/SkypeWeb/src/requests/poll.h b/protocols/SkypeWeb/src/requests/poll.h index f0078c618a..7293c07067 100644 --- a/protocols/SkypeWeb/src/requests/poll.h +++ b/protocols/SkypeWeb/src/requests/poll.h @@ -25,6 +25,10 @@ public: HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints/SELF/subscriptions/0/poll", ppro->m_szServer) { timeout = 120000; + + if (ppro->m_iPollingId != -1) + Url << INT_VALUE("ackId", ppro->m_iPollingId); + Headers << CHAR_VALUE("Referer", "https://web.skype.com/main") << CHAR_VALUE("Content-Type", "application/x-www-form-urlencoded") diff --git a/protocols/SkypeWeb/src/requests/status.h b/protocols/SkypeWeb/src/requests/status.h index 1000ebbccf..459b30471f 100644 --- a/protocols/SkypeWeb/src/requests/status.h +++ b/protocols/SkypeWeb/src/requests/status.h @@ -18,6 +18,19 @@ along with this program. If not, see . #ifndef _SKYPE_REQUEST_STATUS_H_ #define _SKYPE_REQUEST_STATUS_H_ +class GetStatusRequest : public HttpRequest +{ +public: + GetStatusRequest(CSkypeProto *ppro) : + HttpRequest(REQUEST_GET, FORMAT, "%s/v1/users/ME/contacts/ALL/presenceDocs/messagingService", ppro->m_szServer) + { + Headers + << CHAR_VALUE("Accept", "application/json, text/javascript") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", ppro->m_szToken.get()) + << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8"); + } +}; + class SetStatusRequest : public HttpRequest { public: diff --git a/protocols/SkypeWeb/src/skype_avatars.cpp b/protocols/SkypeWeb/src/skype_avatars.cpp index b7e01445d5..ad4e9646d8 100644 --- a/protocols/SkypeWeb/src/skype_avatars.cpp +++ b/protocols/SkypeWeb/src/skype_avatars.cpp @@ -127,7 +127,7 @@ void CSkypeProto::GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t pszDest[tPathLen++] = '\\'; const wchar_t* szFileType = ProtoGetAvatarExtension(getByte(hContact, "AvatarType", PA_FORMAT_JPEG)); - CMStringA username(Contacts[hContact]); + CMStringA username(getId(hContact)); username.Replace("live:", "__live_"); username.Replace("facebook:", "__facebook_"); mir_snwprintf(pszDest + tPathLen, MAX_PATH - tPathLen, L"%S%s", username.c_str(), szFileType); diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp index c11f15dc80..1a6ed3b71c 100644 --- a/protocols/SkypeWeb/src/skype_chatrooms.cpp +++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp @@ -127,7 +127,7 @@ int CSkypeProto::OnGroupChatEventHook(WPARAM, LPARAM lParam) MCONTACT hContact = dlg.m_hContact; if (hContact != NULL) - SendRequest(new InviteUserToChatRequest(chat_id, Contacts[hContact], "User", this)); + SendRequest(new InviteUserToChatRequest(chat_id, getId(hContact), "User", this)); mir_cslock lck(m_InviteDialogsLock); m_InviteDialogs.remove(&dlg); diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp index a0b117a7f9..22f0b2185d 100644 --- a/protocols/SkypeWeb/src/skype_contacts.cpp +++ b/protocols/SkypeWeb/src/skype_contacts.cpp @@ -60,7 +60,7 @@ MCONTACT CSkypeProto::GetContactFromAuthEvent(MEVENT hEvent) MCONTACT CSkypeProto::FindContact(const char *skypename) { for (auto &hContact : AccContacts()) - if (!mir_strcmpi(skypename, Contacts[hContact])) + if (!mir_strcmpi(skypename, getId(hContact))) return hContact; return 0; @@ -124,24 +124,6 @@ void CSkypeProto::LoadContactsAuth(const NETLIBHTTPREQUEST *response) } } -//[{"username":"echo123", "firstname" : "Echo \/ Sound Test Service", "lastname" : null, "avatarUrl" : null, "mood" : null, "richMood" : null, "displayname" : null, "country" : null, "city" : null},...] -void CSkypeProto::LoadContactsInfo(const NETLIBHTTPREQUEST *response) -{ - JsonReply root(response); - if (root.error()) - return; - - for (auto &item : root.data()) { - std::string skypename = item["username"].as_string(); - MCONTACT hContact = AddContact(skypename.c_str()); - if (hContact) { - UpdateProfileCountry(item, hContact); - UpdateProfileCity(item, hContact); - UpdateProfileXStatusMessage(item, hContact); - } - } -} - //[{"skypename":"echo123", "authorized" : true, "blocked" : false, ...},...] // other properties is exists but empty @@ -151,9 +133,9 @@ void CSkypeProto::LoadContactList(const NETLIBHTTPREQUEST *response) if (reply.error()) return; - auto &root = reply.data(); - LIST skypenames(1); bool loadAll = getBool("LoadAllContacts", false); + + auto &root = reply.data(); for (auto &item : root["contacts"]) { const JSONNode &name = item["name"]; @@ -213,25 +195,10 @@ void CSkypeProto::LoadContactList(const NETLIBHTTPREQUEST *response) break; } } - - if (type == "skype") - skypenames.insert(mir_strdup(skypename.c_str())); } } } - if (skypenames.getCount() > 0) { - int i = 0; - do { - LIST users(1); - for (; i < skypenames.getCount() && users.getCount() <= 50; i++) - users.insert(skypenames[i]); - PushRequest(new GetContactsInfoRequest(this, users), &CSkypeProto::LoadContactsInfo); - } while (i < skypenames.getCount()); - - FreeList(skypenames); - skypenames.destroy(); - } PushRequest(new GetContactsAuthRequest(this), &CSkypeProto::LoadContactsAuth); } @@ -240,7 +207,7 @@ INT_PTR CSkypeProto::OnRequestAuth(WPARAM hContact, LPARAM) if (hContact == INVALID_CONTACT_ID) return 1; - PushRequest(new AddContactRequest(this, Contacts[hContact])); + PushRequest(new AddContactRequest(this, getId(hContact))); return 0; } @@ -249,7 +216,7 @@ INT_PTR CSkypeProto::OnGrantAuth(WPARAM hContact, LPARAM) if (hContact == INVALID_CONTACT_ID) return 1; - PushRequest(new AuthAcceptRequest(this, Contacts[hContact])); + PushRequest(new AuthAcceptRequest(this, getId(hContact))); return 0; } @@ -257,7 +224,7 @@ void CSkypeProto::OnContactDeleted(MCONTACT hContact) { if (IsOnline()) if (hContact && !isChatRoom(hContact)) - PushRequest(new DeleteContactRequest(this, Contacts[hContact])); + PushRequest(new DeleteContactRequest(this, getId(hContact))); } INT_PTR CSkypeProto::BlockContact(WPARAM hContact, LPARAM) @@ -265,7 +232,7 @@ INT_PTR CSkypeProto::BlockContact(WPARAM hContact, LPARAM) if (!IsOnline()) return 1; if (IDYES == MessageBox(NULL, TranslateT("Are you sure?"), TranslateT("Warning"), MB_YESNO | MB_ICONQUESTION)) - SendRequest(new BlockContactRequest(this, Contacts[hContact]), &CSkypeProto::OnBlockContact, (void *)hContact); + SendRequest(new BlockContactRequest(this, getId(hContact)), &CSkypeProto::OnBlockContact, (void *)hContact); return 0; } @@ -278,7 +245,7 @@ void CSkypeProto::OnBlockContact(const NETLIBHTTPREQUEST *response, void *p) INT_PTR CSkypeProto::UnblockContact(WPARAM hContact, LPARAM) { - SendRequest(new UnblockContactRequest(this, Contacts[hContact]), &CSkypeProto::OnUnblockContact, (void *)hContact); + SendRequest(new UnblockContactRequest(this, getId(hContact)), &CSkypeProto::OnUnblockContact, (void *)hContact); return 0; } diff --git a/protocols/SkypeWeb/src/skype_dialogs.cpp b/protocols/SkypeWeb/src/skype_dialogs.cpp index 17f5f9bf4e..d0f3ba18a9 100644 --- a/protocols/SkypeWeb/src/skype_dialogs.cpp +++ b/protocols/SkypeWeb/src/skype_dialogs.cpp @@ -78,15 +78,10 @@ bool CSkypeGCCreateDlg::OnInitDialog() void CSkypeGCCreateDlg::btnOk_OnOk(CCtrlButton*) { for (auto &hContact : m_proto->AccContacts()) { - if (!m_proto->isChatRoom(hContact)) { - if (HANDLE hItem = m_clc.FindContact(hContact)) { - if (m_clc.GetCheck(hItem)) { - char *szName = mir_strdup(m_proto->Contacts[hContact]); - if (szName != nullptr) - m_ContactsList.insert(szName); - } - } - } + if (!m_proto->isChatRoom(hContact)) + if (HANDLE hItem = m_clc.FindContact(hContact)) + if (m_clc.GetCheck(hItem)) + m_ContactsList.insert(m_proto->getId(hContact).Detach()); } m_ContactsList.insert(m_proto->m_szSkypename.GetBuffer()); diff --git a/protocols/SkypeWeb/src/skype_files.cpp b/protocols/SkypeWeb/src/skype_files.cpp index c6ad5743d7..d74dd71fe6 100644 --- a/protocols/SkypeWeb/src/skype_files.cpp +++ b/protocols/SkypeWeb/src/skype_files.cpp @@ -26,7 +26,7 @@ void CSkypeProto::SendFileThread(void *p) ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)fup); T2Utf uszFileName(fup->tszFileName); - SendRequest(new ASMObjectCreateRequest(this, CMStringA(FORMAT, "%d:%s", isChatRoom(fup->hContact) ? 19 : 8, Contacts[fup->hContact]), strrchr((const char*)uszFileName + 1, '\\')), &CSkypeProto::OnASMObjectCreated, fup); + SendRequest(new ASMObjectCreateRequest(this, CMStringA(FORMAT, "%d:%s", isChatRoom(fup->hContact) ? 19 : 8, getId(fup->hContact).c_str()), strrchr((const char*)uszFileName + 1, '\\')), &CSkypeProto::OnASMObjectCreated, fup); } void CSkypeProto::OnASMObjectCreated(const NETLIBHTTPREQUEST *response, void *arg) @@ -105,7 +105,7 @@ void CSkypeProto::OnASMObjectUploaded(const NETLIBHTTPREQUEST *response, void *a tinyxml2::XMLPrinter printer(0, true); doc.Print(&printer); - SendRequest(new SendMessageRequest(Contacts[fup->hContact], time(NULL), printer.CStr(), this, "RichText/Media_GenericFile")); + SendRequest(new SendMessageRequest(getId(fup->hContact), time(NULL), printer.CStr(), this, "RichText/Media_GenericFile")); ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)fup); delete fup; diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index 7b31729bb4..f17d988f26 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -105,7 +105,7 @@ void CSkypeProto::OnGetServerHistory(const NETLIBHTTPREQUEST *response) INT_PTR CSkypeProto::GetContactHistory(WPARAM hContact, LPARAM) { - PushRequest(new GetHistoryRequest(Contacts[hContact], 100, false, 0, this), &CSkypeProto::OnGetServerHistory); + PushRequest(new GetHistoryRequest(getId(hContact), 100, false, 0, this), &CSkypeProto::OnGetServerHistory); return 0; } diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp index 262bc0a6b6..fda2187ca2 100644 --- a/protocols/SkypeWeb/src/skype_login.cpp +++ b/protocols/SkypeWeb/src/skype_login.cpp @@ -17,8 +17,6 @@ along with this program. If not, see . #include "stdafx.h" -UINT_PTR CSkypeProto::m_timer; - void CSkypeProto::Login() { // login @@ -113,6 +111,8 @@ void CSkypeProto::OnLoginSuccess() m_szApiToken = getStringA("TokenSecret"); + m_impl.m_heartBeat.StartSafe(600 * 1000); + SendRequest(new CreateEndpointRequest(this), &CSkypeProto::OnEndpointCreated); } @@ -178,6 +178,8 @@ void CSkypeProto::OnEndpointCreated(const NETLIBHTTPREQUEST *response) return; } + RefreshStatuses(); + SendRequest(new CreateSubscriptionsRequest(this), &CSkypeProto::OnSubscriptionsCreated); } diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index da1892bb18..166222998b 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -193,7 +193,7 @@ void CSkypeProto::MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent) time_t timestamp = dbei.timestamp; if (db_get_dw(hContact, m_szModuleName, "LastMsgTime", 0) > (timestamp - 300)) - PushRequest(new MarkMessageReadRequest(Contacts[hContact], timestamp, timestamp, false, this)); + PushRequest(new MarkMessageReadRequest(getId(hContact), timestamp, timestamp, false, this)); } void CSkypeProto::ProcessContactRecv(MCONTACT hContact, time_t timestamp, const char *szContent, const char *szMessageId) diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index 075b5085e8..c86f90dcd1 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -27,10 +27,10 @@ void CSkypeProto::PollingThread(void*) break; int nErrors = 0; - - PollRequest *request = new PollRequest(this); + m_iPollingId = -1; while ((nErrors < POLLING_ERRORS_LIMIT) && m_iStatus != ID_STATUS_OFFLINE) { + std::unique_ptr request(new PollRequest(this)); NLHR_PTR response(request->Send(m_hNetlibUser)); if (response == nullptr) { nErrors++; @@ -53,7 +53,6 @@ void CSkypeProto::PollingThread(void*) } } } - delete request; if (m_iStatus != ID_STATUS_OFFLINE) { debugLogA(__FUNCTION__ ": unexpected termination; switching protocol to offline"); @@ -73,6 +72,10 @@ void CSkypeProto::ParsePollData(const char *szData) return; for (auto &message : data["eventMessages"]) { + int eventId = message["id"].as_int(); + if (eventId > m_iPollingId) + m_iPollingId = eventId; + const JSONNode &resType = message["resourceType"]; const JSONNode &resource = message["resource"]; diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index 0db6e26836..84b7a1a337 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -26,7 +26,7 @@ CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : m_bThreadsTerminated(false), m_TrouterConnection(nullptr), m_opts(this), - Contacts(this), + m_impl(*this), m_szServer(mir_strdup(SKYPE_ENDPOINTS_HOST)) { InitNetwork(); @@ -55,8 +55,6 @@ CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : g_plugin.addSound("skype_inc_call", L"SkypeWeb", LPGENW("Incoming call")); g_plugin.addSound("skype_call_canceled", L"SkypeWeb", LPGENW("Incoming call canceled")); - SkypeSetTimer(); - m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, NULL, NULL); m_hTrouterThread = ForkThreadEx(&CSkypeProto::TRouterThread, NULL, NULL); } @@ -78,8 +76,6 @@ CSkypeProto::~CSkypeProto() WaitForSingleObject(m_hTrouterThread, INFINITE); m_hTrouterThread = nullptr; } - - SkypeUnsetTimer(); } void CSkypeProto::OnModulesLoaded() @@ -130,7 +126,7 @@ int CSkypeProto::SetAwayMsg(int, const wchar_t *msg) HANDLE CSkypeProto::GetAwayMsg(MCONTACT hContact) { - PushRequest(new GetProfileRequest(this, Contacts[hContact]), [this, hContact](const NETLIBHTTPREQUEST *response) { + PushRequest(new GetProfileRequest(this, getId(hContact)), [this, hContact](const NETLIBHTTPREQUEST *response) { JsonReply reply(response); if (reply.error()) return; @@ -190,7 +186,7 @@ int CSkypeProto::Authorize(MEVENT hDbEvent) if (hContact == INVALID_CONTACT_ID) return 1; - PushRequest(new AuthAcceptRequest(this, Contacts[hContact])); + PushRequest(new AuthAcceptRequest(this, getId(hContact))); return 0; } @@ -200,7 +196,7 @@ int CSkypeProto::AuthDeny(MEVENT hDbEvent, const wchar_t*) if (hContact == INVALID_CONTACT_ID) return 1; - PushRequest(new AuthDeclineRequest(this, Contacts[hContact])); + PushRequest(new AuthDeclineRequest(this, getId(hContact))); return 0; } @@ -214,7 +210,7 @@ int CSkypeProto::AuthRequest(MCONTACT hContact, const wchar_t *szMessage) if (hContact == INVALID_CONTACT_ID) return 1; - PushRequest(new AddContactRequest(this, Contacts[hContact], T2Utf(szMessage))); + PushRequest(new AddContactRequest(this, getId(hContact), T2Utf(szMessage))); return 0; } @@ -223,7 +219,7 @@ int CSkypeProto::GetInfo(MCONTACT hContact, int) if (isChatRoom(hContact)) return 1; - PushRequest(new GetProfileRequest(this, Contacts[hContact]), &CSkypeProto::LoadProfile, (void*)hContact); + PushRequest(new GetProfileRequest(this, getId(hContact)), &CSkypeProto::LoadProfile, (void*)hContact); return 0; } @@ -269,6 +265,8 @@ int CSkypeProto::SetStatus(int iNewStatus) CloseDialogs(); ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, ID_STATUS_OFFLINE); + m_impl.m_heartBeat.StopSafe(); + if (!Miranda_IsTerminated()) setAllContactStatuses(ID_STATUS_OFFLINE, true); return 0; @@ -291,7 +289,7 @@ int CSkypeProto::SetStatus(int iNewStatus) int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) { - SendRequest(new SendTypingRequest(Contacts[hContact], type, this)); + SendRequest(new SendTypingRequest(getId(hContact), type, this)); return 0; } diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index e8d93e62a1..be5926d761 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -26,6 +26,25 @@ struct CSkypeProto : public PROTO < CSkypeProto > friend CSkypeOptionsMain; friend CSkypeGCCreateDlg; + class CSkypeProtoImpl + { + friend struct CSkypeProto; + CSkypeProto &m_proto; + + CTimer m_heartBeat; + void OnHeartBeat(CTimer *) + { + m_proto.ProcessTimer(); + } + + CSkypeProtoImpl(CSkypeProto &pro) : + m_proto(pro), + m_heartBeat(Miranda_GetSystemWindow(), UINT_PTR(this) + 1) + { + m_heartBeat.OnEvent = Callback(this, &CSkypeProtoImpl::OnHeartBeat); + } + } m_impl; + public: ////////////////////////////////////////////////////////////////////////////////////// @@ -85,42 +104,15 @@ public: CSkypeOptions m_opts; + int m_iPollingId; ptrA m_szApiToken, m_szToken, m_szId, m_szServer; CMStringA m_szSkypename, m_szMyname; -private: - struct contacts_list - { - CSkypeProto *m_proto; - std::map m_cache; - - contacts_list(CSkypeProto *ppro) : m_proto(ppro) - {} - - ~contacts_list() - { - for (auto &it : m_cache) - mir_free(it.second); - } - - const char* operator[](MCONTACT hContact) - { - try - { - return m_cache.at(hContact); - } - catch (std::out_of_range&) - { - char *id = m_proto->getStringA(hContact, SKYPE_SETTINGS_ID); - m_cache[hContact] = id; - return id; - } - } - - } Contacts; - - static UINT_PTR m_timer; + __forceinline CMStringA getId(MCONTACT hContact) { + return getMStringA(hContact, SKYPE_SETTINGS_ID); + } +private: class RequestQueue *requestQueue; bool m_bHistorySynced; @@ -147,8 +139,6 @@ private: mir_cs messageSyncLock; mir_cs m_StatusLock; mir_cs m_AppendMessageLock; - static mir_cs accountsLock; - static mir_cs timerLock; bool m_bThreadsTerminated; @@ -220,6 +210,7 @@ private: void OnSubscriptionsCreated(const NETLIBHTTPREQUEST *response); void OnCapabilitiesSended(const NETLIBHTTPREQUEST *response); void OnStatusChanged(const NETLIBHTTPREQUEST *response); + void OnReceiveStatus(const NETLIBHTTPREQUEST *response); //TRouter @@ -274,7 +265,6 @@ private: MCONTACT GetContactFromAuthEvent(MEVENT hEvent); void LoadContactsAuth(const NETLIBHTTPREQUEST *response); - void LoadContactsInfo(const NETLIBHTTPREQUEST *response); void LoadContactList(const NETLIBHTTPREQUEST *response); void OnBlockContact(const NETLIBHTTPREQUEST *response, void *p); @@ -328,13 +318,17 @@ private: void SetChatStatus(MCONTACT hContact, int iStatus); // polling - void __cdecl PollingThread (void*); - void __cdecl ParsePollData (const char*); - void ProcessEndpointPresence (const JSONNode &node); - void ProcessUserPresence (const JSONNode &node); - void ProcessNewMessage (const JSONNode &node); - void ProcessConversationUpdate (const JSONNode &node); - void ProcessThreadUpdate (const JSONNode &node); + void __cdecl PollingThread(void*); + + void ParsePollData(const char*); + + void ProcessNewMessage(const JSONNode &node); + void ProcessUserPresence(const JSONNode &node); + void ProcessThreadUpdate(const JSONNode &node); + void ProcessEndpointPresence(const JSONNode &node); + void ProcessConversationUpdate(const JSONNode &node); + + void RefreshStatuses(void); // utils template @@ -371,12 +365,7 @@ private: static CMStringA UrlToSkypename(const char *url); static CMStringA GetServerFromUrl(const char *url); - //---Timers - void CALLBACK SkypeUnsetTimer(); - void CALLBACK SkypeSetTimer(); void ProcessTimer(); - static void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD); - //---/ CMStringW RunConfirmationCode(); CMStringW ChangeTopicForm(); diff --git a/protocols/SkypeWeb/src/skype_timers.cpp b/protocols/SkypeWeb/src/skype_timers.cpp deleted file mode 100644 index ec050dec4d..0000000000 --- a/protocols/SkypeWeb/src/skype_timers.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright (c) 2015-20 Miranda NG team (https://miranda-ng.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "stdafx.h" - -mir_cs CSkypeProto::timerLock; -mir_cs CSkypeProto::accountsLock; - -void CSkypeProto::ProcessTimer() -{ - if (IsOnline()) { - PushRequest(new GetContactListRequest(this, nullptr), &CSkypeProto::LoadContactList); - SendPresence(false); - } -} - -void CALLBACK CSkypeProto::TimerProc(HWND, UINT, UINT_PTR, DWORD) -{ - mir_cslock lck(accountsLock); - for (auto &it : CMPlugin::g_arInstances) - it->ProcessTimer(); -} - -void CSkypeProto::SkypeSetTimer() -{ - mir_cslock lck(timerLock); - if (!m_timer) - m_timer = SetTimer(nullptr, 0, 600000, TimerProc); -} - -void CSkypeProto::SkypeUnsetTimer() -{ - mir_cslock lck(timerLock); - if (m_timer && CMPlugin::g_arInstances.getCount() == 0) - KillTimer(nullptr, m_timer); - m_timer = 0; -} diff --git a/protocols/SkypeWeb/src/skype_trouter.cpp b/protocols/SkypeWeb/src/skype_trouter.cpp index cfc41f7b8c..79a4f12cf3 100644 --- a/protocols/SkypeWeb/src/skype_trouter.cpp +++ b/protocols/SkypeWeb/src/skype_trouter.cpp @@ -17,6 +17,63 @@ along with this program. If not, see . #include "stdafx.h" +void CSkypeProto::ProcessTimer() +{ + if (!IsOnline()) + return; + + PushRequest(new GetContactListRequest(this, nullptr), &CSkypeProto::LoadContactList); + SendPresence(false); + + RefreshStatuses(); +} + +void CSkypeProto::OnReceiveStatus(const NETLIBHTTPREQUEST *response) +{ + JsonReply reply(response); + if (reply.error()) + return; + + auto &root = reply.data(); + for (auto &it : root["Responses"]) { + std::string id = it["Contact"].as_string(); + id.erase(0, 2); + MCONTACT hContact = AddContact(id.c_str()); + if (hContact) { + int status = SkypeToMirandaStatus(it["Payload"]["status"].as_string().c_str()); + setWord(hContact, "Status", status); + } + } +} + +void CSkypeProto::RefreshStatuses(void) +{ + int nRecs = 0; + GetStatusRequest *pReq = nullptr; + + for (auto &it : AccContacts()) { + CMStringA id(getId(it)); + if (id.IsEmpty()) + continue; + + if (pReq == nullptr) { + pReq = new GetStatusRequest(this); + nRecs = 0; + } + + pReq->Url << CHAR_VALUE("cMri", "8:" + id); + nRecs++; + + if (nRecs >= 10) { + PushRequest(pReq, &CSkypeProto::OnReceiveStatus); + pReq = nullptr; + } + } + + if (pReq) + PushRequest(pReq, &CSkypeProto::OnReceiveStatus); +} + void CSkypeProto::OnCreateTrouter(const NETLIBHTTPREQUEST *response) { JsonReply reply(response); diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index a3a1d3419f..cb27f1bab3 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -595,7 +595,6 @@ INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam) INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) { - mir_cslock lck(accountsLock); for (auto &it : CMPlugin::g_arInstances) if (it->IsOnline()) return it->ParseSkypeUriService(wParam, lParam); diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h index f62177d12b..c2fb3727df 100644 --- a/protocols/SkypeWeb/src/version.h +++ b/protocols/SkypeWeb/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 12 #define __RELEASE_NUM 3 -#define __BUILD_NUM 6 +#define __BUILD_NUM 7 #include -- cgit v1.2.3