From be402c501b9a8e84f959bee959bbe0e0af8e55ca Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 6 Dec 2023 21:26:33 +0300 Subject: =?UTF-8?q?fixes=20#3990=20(ICQ:=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BF=D1=80=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC=20=D0=BE=D1=82=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20=D1=81=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocols/ICQ-WIM/src/poll.cpp | 3 +- protocols/ICQ-WIM/src/proto.cpp | 2 +- protocols/ICQ-WIM/src/proto.h | 3 + protocols/ICQ-WIM/src/server.cpp | 166 +++++++++++++++++++++++++++++---------- protocols/ICQ-WIM/src/stdafx.h | 1 + 5 files changed, 131 insertions(+), 44 deletions(-) diff --git a/protocols/ICQ-WIM/src/poll.cpp b/protocols/ICQ-WIM/src/poll.cpp index 2af3be7348..a75b972e15 100644 --- a/protocols/ICQ-WIM/src/poll.cpp +++ b/protocols/ICQ-WIM/src/poll.cpp @@ -207,8 +207,7 @@ void CIcqProto::ProcessHistData(const JSONNode &ev) setId(hContact, DB_KEY_LASTMSGID, lastMsgId); } - __int64 patchVersion = _wtoi64(ev["patchVersion"].as_mstring()); - setId(hContact, DB_KEY_PATCHVER, patchVersion); + ProcessPatchVersion(hContact, _wtoi64(ev["patchVersion"].as_mstring())); __int64 srvLastId = _wtoi64(ev["lastMsgId"].as_mstring()); diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index ef67bb68e0..94cc02d813 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -538,7 +538,7 @@ HANDLE CIcqProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, wcha //////////////////////////////////////////////////////////////////////////////////////// // PS_SendMessage - sends a message -int CIcqProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *pszSrc) +int CIcqProto::SendMsg(MCONTACT hContact, MEVENT, const char *pszSrc) { CMStringA szUserid(GetUserId(hContact)); if (szUserid.IsEmpty()) diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index 582fc4d8de..a8b2e90eff 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -210,6 +210,7 @@ class CIcqProto : public PROTO void GetPermitDeny(); wchar_t* GetUIN(MCONTACT hContact); void MoveContactToGroup(MCONTACT hContact, const wchar_t *pwszGroup, const wchar_t *pwszNewGroup); + void RetrieveHistoryChunk(MCONTACT hContact, __int64 patchVer, __int64 startMsgId, unsigned iCount); bool RetrievePassword(); void RetrievePresence(MCONTACT hContact); void RetrieveUserCaps(IcqUser *pUser); @@ -229,6 +230,7 @@ class CIcqProto : public PROTO void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg, bool bCreateRead, bool bLocalTime); IcqFileInfo* RetrieveFileInfo(MCONTACT hContact, const CMStringW &wszUrl); int StatusFromPresence(const JSONNode &presence, MCONTACT hContact); + void ProcessPatchVersion(MCONTACT hContact, __int64 currPatch); void ProcessStatus(IcqUser *pUser, int iStatus); void OnLoggedIn(void); @@ -255,6 +257,7 @@ class CIcqProto : public PROTO void OnFileRecv(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); void OnGenToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); void OnGetChatInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); + void OnGetPatches(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); void OnGetPermitDeny(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); void OnGePresence(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); void OnGetSticker(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index aa5f696004..a84efd0a16 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -479,12 +479,7 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo if (msgId > lastMsgId) lastMsgId = msgId; - // ignore duplicates - if (db_event_getById(m_szModuleName, szMsgId)) { - debugLogA("Message %s already exists", szMsgId.c_str()); - return; - } - + MEVENT hOldEvent = db_event_getById(m_szModuleName, szMsgId); int iMsgTime = (bLocalTime) ? time(0) : it["time"].as_int(); if (auto &node = it["chat"]["sender"]) @@ -559,6 +554,9 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo if (wszUrl.IsEmpty()) continue; + if (hOldEvent && fileText2url(wszText)) + return; + if (!CheckFile(hContact, wszUrl, pFileInfo)) continue; @@ -577,8 +575,11 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo } // message text might be a separate file link as well - if (pFileInfo == nullptr) + if (pFileInfo == nullptr && fileText2url(wszText)) { + if (hOldEvent) + return; CheckFile(hContact, wszText, pFileInfo); + } // process our own messages CMStringA reqId(it["reqId"].as_mstring()); @@ -629,17 +630,34 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo ptrA szUtf(mir_utf8encodeW(wszText)); - PROTORECVEVENT pre = {}; - pre.szMsgId = szMsgId; - pre.timestamp = iMsgTime; - pre.szMessage = szUtf; - if (bIsOutgoing) - pre.flags |= PREF_SENT; - if (bCreateRead) - pre.flags |= PREF_CREATEREAD; - if (isChatRoom(hContact)) - pre.szUserId = szSender; - ProtoChainRecvMsg(hContact, &pre); + if (hOldEvent) { + DBEVENTINFO dbei = {}; + dbei.szModule = m_szModuleName; + dbei.timestamp = iMsgTime; + if (bIsOutgoing) + dbei.flags |= DBEF_SENT; + if (bCreateRead) + dbei.flags |= DBEF_READ; + dbei.cbBlob = (int)mir_strlen(szUtf); + dbei.pBlob = (BYTE*)szUtf.get(); + dbei.szId = szMsgId; + if (isChatRoom(hContact)) + dbei.szUserId = szSender; + db_event_edit(hOldEvent, &dbei, true); + } + else { + PROTORECVEVENT pre = {}; + pre.timestamp = iMsgTime; + pre.szMessage = szUtf; + if (bIsOutgoing) + pre.flags |= PREF_SENT; + if (bCreateRead) + pre.flags |= PREF_CREATEREAD; + pre.szMsgId = szMsgId; + if (isChatRoom(hContact)) + pre.szUserId = szSender; + ProtoChainRecvMsg(hContact, &pre); + } } bool CIcqProto::RefreshRobustToken(AsyncHttpRequest *pOrigReq) @@ -764,6 +782,81 @@ void CIcqProto::RetrieveUserInfo(MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// +void CIcqProto::OnGetPatches(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + RobustReply root(pReply); + if (root.error() != 20000) + return; + + auto &results = root.results(); + + CMStringW wszNewPatch(results["patchVersion"].as_mstring()); + if (!wszNewPatch.IsEmpty()) + setId(pReq->hContact, DB_KEY_PATCHVER, _wtoi64(wszNewPatch)); + + std::map<__int64, bool> events; + for (auto &it : results["patch"]) { + std::string type = it["type"].as_string(); + __int64 msgId = _wtoi64(it["msgId"].as_mstring()); + if (type == "update") + events[msgId] = true; + else + events[msgId] = false; + } + + for (auto &it : events) { + if (it.second) + RetrieveHistoryChunk(pReq->hContact, it.first, it.first-1, 1); + else { + char msgId[100]; + _i64toa(it.first, msgId, 10); + if (MEVENT hEvent = db_event_getById(m_szModuleName, msgId)) + db_event_delete(hEvent, true); + } + } +} + +void CIcqProto::ProcessPatchVersion(MCONTACT hContact, __int64 currPatch) +{ + __int64 oldPatch(getId(hContact, DB_KEY_PATCHVER)); + if (!oldPatch) + oldPatch = 1; + + if (currPatch == oldPatch) + return; + + auto *pReq = new AsyncRapiRequest(this, "getHistory", &CIcqProto::OnGetPatches); + #ifndef _DEBUG + pReq->flags |= NLHRF_NODUMPSEND; + #endif + pReq->hContact = hContact; + pReq->params << WCHAR_PARAM("sn", GetUserId(hContact)) << INT_PARAM("fromMsgId", 0) << INT_PARAM("count", 0) << SINT64_PARAM("patchVersion", oldPatch); + Push(pReq); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CIcqProto::OnGetUserHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + RobustReply root(pReply); + if (root.error() != 20000) + return; + + __int64 lastMsgId = getId(pReq->hContact, DB_KEY_LASTMSGID); + + int count = 0; + auto &results = root.results(); + for (auto &it : results["messages"]) { + ParseMessage(pReq->hContact, lastMsgId, it, pReq->pUserInfo != nullptr, false); + count++; + } + + setId(pReq->hContact, DB_KEY_LASTMSGID, lastMsgId); + + if (count >= 999) + RetrieveUserHistory(pReq->hContact, lastMsgId, pReq->pUserInfo != nullptr); +} + void CIcqProto::RetrieveUserHistory(MCONTACT hContact, __int64 startMsgId, bool bCreateRead) { if (startMsgId == 0) @@ -779,11 +872,23 @@ void CIcqProto::RetrieveUserHistory(MCONTACT hContact, __int64 startMsgId, bool #endif pReq->hContact = hContact; pReq->pUserInfo = (bCreateRead) ? pReq : 0; - pReq->params << WCHAR_PARAM("sn", GetUserId(hContact)) << INT64_PARAM("fromMsgId", startMsgId) << INT_PARAM("count", 1000) - << SINT64_PARAM("patchVersion", patchVer) << CHAR_PARAM("language", "ru-ru"); + pReq->params << WCHAR_PARAM("sn", GetUserId(hContact)) << INT64_PARAM("fromMsgId", startMsgId) << INT_PARAM("count", 1000) << SINT64_PARAM("patchVersion", patchVer); Push(pReq); } +void CIcqProto::RetrieveHistoryChunk(MCONTACT hContact, __int64 patchVer, __int64 startMsgId, unsigned iCount) +{ + auto *pReq = new AsyncRapiRequest(this, "getHistory", &CIcqProto::OnGetUserHistory); + #ifndef _DEBUG + pReq->flags |= NLHRF_NODUMPSEND; + #endif + pReq->hContact = hContact; + pReq->params << WCHAR_PARAM("sn", GetUserId(hContact)) << INT64_PARAM("fromMsgId", startMsgId) << INT_PARAM("count", iCount) << SINT64_PARAM("patchVersion", patchVer); + Push(pReq); +} + +///////////////////////////////////////////////////////////////////////////////////////// + void CIcqProto::SetServerStatus(int iStatus) { const char *szStatus = "online"; @@ -1104,27 +1209,6 @@ void CIcqProto::OnGenToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) m_szRToken = results["authToken"].as_mstring(); } -void CIcqProto::OnGetUserHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) -{ - RobustReply root(pReply); - if (root.error() != 20000) - return; - - __int64 lastMsgId = getId(pReq->hContact, DB_KEY_LASTMSGID); - - int count = 0; - auto &results = root.results(); - for (auto &it : results["messages"]) { - ParseMessage(pReq->hContact, lastMsgId, it, pReq->pUserInfo != nullptr, false); - count++; - } - - setId(pReq->hContact, DB_KEY_LASTMSGID, lastMsgId); - - if (count >= 999) - RetrieveUserHistory(pReq->hContact, lastMsgId, pReq->pUserInfo != nullptr); -} - void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) { JsonReply root(pReply); diff --git a/protocols/ICQ-WIM/src/stdafx.h b/protocols/ICQ-WIM/src/stdafx.h index e7cc7ff3e9..d6e059d578 100644 --- a/protocols/ICQ-WIM/src/stdafx.h +++ b/protocols/ICQ-WIM/src/stdafx.h @@ -32,6 +32,7 @@ // Windows includes #include +#include #include // Standard includes -- cgit v1.2.3