summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2023-12-06 21:26:33 +0300
committerGeorge Hazan <george.hazan@gmail.com>2023-12-06 21:26:33 +0300
commitbe402c501b9a8e84f959bee959bbe0e0af8e55ca (patch)
tree7703628ff62ba81ad9809d0c0b61311ac94a38ea /protocols
parentcfdabde550aa3cdb3b13e5352f3654e2f6131718 (diff)
fixes #3990 (ICQ: реализовать прием отредактированных сообщений с сервера)
Diffstat (limited to 'protocols')
-rw-r--r--protocols/ICQ-WIM/src/poll.cpp3
-rw-r--r--protocols/ICQ-WIM/src/proto.cpp2
-rw-r--r--protocols/ICQ-WIM/src/proto.h3
-rw-r--r--protocols/ICQ-WIM/src/server.cpp166
-rw-r--r--protocols/ICQ-WIM/src/stdafx.h1
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<CIcqProto>
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<CIcqProto>
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<CIcqProto>
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 <windows.h>
+#include <map>
#include <memory>
// Standard includes