From 6b0438cad083d699d7cab3e5c57f0cbc3384ef92 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 10 Jan 2025 19:24:17 +0300 Subject: Skype: ability to edit messages --- protocols/SkypeWeb/src/skype_history_sync.cpp | 12 ++++---- protocols/SkypeWeb/src/skype_messages.cpp | 43 +++++++++++++++++---------- protocols/SkypeWeb/src/skype_proto.cpp | 11 ++++++- protocols/SkypeWeb/src/skype_proto.h | 7 +++-- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index d455eaf0e5..ffa7b7292e 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -33,11 +33,9 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * std::string syncState = metadata["syncState"].as_string(); bool bOperative = pRequest->pUserInfo != 0; - bool bUseLocalTime = !m_bUseServerTime && bOperative; bool bSetLastTime = false; int64_t lastMsgTime = 0; // max timestamp on this page - time_t iLocalTime = time(0); auto &conv = root["messages"]; for (auto it = conv.rbegin(); it != conv.rend(); ++it) { @@ -59,8 +57,11 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); dbei.hContact = hContact; dbei.szModule = m_szModuleName; - dbei.iTimestamp = (bUseLocalTime) ? iLocalTime : IsoToUnixTime(message["composetime"].as_string()); dbei.szId = szMessageId; + dbei.bSent = IsMe(szFrom); + dbei.bMsec = dbei.bUtf = true; + dbei.iTimestamp = _wtoi64(message["id"].as_mstring()); + if (iUserType == 19) { dbei.szUserId = szFrom; @@ -69,11 +70,8 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * continue; } - dbei.flags = DBEF_UTF; if (!bOperative && !dbei.getEvent()) - dbei.flags |= DBEF_READ; - if (IsMe(szFrom)) - dbei.flags |= DBEF_SENT; + dbei.bRead = true; if (ParseMessage(message, dbei)) { if (dbei) diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index c108cef65d..998501006d 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -44,33 +44,41 @@ void CSkypeProto::OnMessageSent(MHttpResponse *response, AsyncHttpRequest *pRequ // outcoming message flow -int CSkypeProto::SendMsg(MCONTACT hContact, MEVENT, const char *szMessage) +int CSkypeProto::SendServerMsg(MCONTACT hContact, const char *szMessage, int64_t existingMsgId) { if (!IsOnline()) return -1; CMStringA str(szMessage); bool bRich = AddBbcodes(str); - int64_t iRandomId = getRandomId(); m_iMessageId++; CMStringA szUrl = "/users/ME/conversations/" + mir_urlEncode(getId(hContact)) + "/messages"; - AsyncHttpRequest *pReq = new AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, szUrl, &CSkypeProto::OnMessageSent); + if (existingMsgId) + szUrl.AppendFormat("/%lld", existingMsgId); + + AsyncHttpRequest *pReq = new AsyncHttpRequest(existingMsgId ? REQUEST_PUT : REQUEST_POST, HOST_DEFAULT, szUrl, &CSkypeProto::OnMessageSent); pReq->hContact = hContact; pReq->pUserInfo = (HANDLE)m_iMessageId; JSONNode node; - node << INT64_PARAM("clientmessageid", iRandomId) << CHAR_PARAM("messagetype", bRich ? "RichText" : "Text") << CHAR_PARAM("contenttype", "text"); + node << CHAR_PARAM("messagetype", bRich ? "RichText" : "Text") << CHAR_PARAM("contenttype", "text"); if (strncmp(str, "/me ", 4) == 0) node << CHAR_PARAM("content", m_szSkypename + " " + str); else node << CHAR_PARAM("content", str); + + if (!existingMsgId) { + int64_t iRandomId = getRandomId(); + node << INT64_PARAM("clientmessageid", iRandomId); + + mir_cslock lck(m_lckOutMessagesList); + m_OutMessages.insert(new COwnMessage(m_iMessageId, iRandomId)); + } pReq->m_szParam = node.write().c_str(); PushRequest(pReq); - mir_cslock lck(m_lckOutMessagesList); - m_OutMessages.insert(new COwnMessage(m_iMessageId, iRandomId)); return m_iMessageId; } @@ -81,6 +89,11 @@ int CSkypeProto::OnPreCreateMessage(WPARAM, LPARAM lParam) if (mir_strcmp(Proto_GetBaseAccountName(evt->hContact), m_szModuleName)) return 0; + int64_t msgId = (evt->dbei->szId) ? _atoi64(evt->dbei->szId) : -1; + for (auto &it : m_OutMessages) + if (it->hClientMessageId == msgId) + evt->dbei->iTimestamp = it->iTimestamp; + char *message = (char*)evt->dbei->pBlob; if (strncmp(message, "/me ", 4) == 0) { evt->dbei->cbBlob = evt->dbei->cbBlob - 4; @@ -122,6 +135,8 @@ LBL_Deleted: if (dbei.bSent && dbei.szId) { for (auto &it: m_OutMessages) { if (it->hClientMessageId == _atoi64(dbei.szId)) { + it->iTimestamp = dbei.iTimestamp; + ProtoBroadcastAck(dbei.hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)it->hMessage, (LPARAM)dbei.szId); mir_cslock lck(m_lckOutMessagesList); @@ -162,7 +177,7 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) int iUserType; UrlToSkypeId(node["conversationLink"].as_string().c_str(), &iUserType); - CMStringA szId = node["id"].as_mstring(); + int64_t timestamp = _wtoi64(node["id"].as_mstring()); CMStringA szMessageId(getMessageId(node)); CMStringA szConversationName(UrlToSkypeId(node["conversationLink"].as_string().c_str())); CMStringA szFromSkypename(UrlToSkypeId(node["from"].as_mstring())); @@ -173,11 +188,8 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) MCONTACT hContact = AddContact(szConversationName, nullptr, true); - if (m_bHistorySynced) { - int64_t lastMsgId = _atoi64(szId); - if (lastMsgId > getLastTime(hContact)) - setLastTime(hContact, lastMsgId); - } + if (m_bHistorySynced && timestamp > getLastTime(hContact)) + setLastTime(hContact, timestamp); std::string strMessageType = node["messagetype"].as_string(); if (strMessageType == "Control/Typing") { @@ -191,11 +203,10 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); dbei.hContact = hContact; - dbei.iTimestamp = time(0); + dbei.iTimestamp = timestamp; dbei.szId = szMessageId; - dbei.flags = DBEF_UTF; - if (IsMe(szFromSkypename)) - dbei.flags |= DBEF_SENT; + dbei.bUtf = dbei.bMsec = true; + dbei.bSent = IsMe(szFromSkypename); if (iUserType == 19) dbei.szUserId = szFromSkypename; diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index d2f6bf4ba2..620b03b386 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -26,7 +26,6 @@ CSkypeProto::CSkypeProto(const char *protoName, const wchar_t *userName) : m_bAutoHistorySync(this, "AutoSync", true), m_bUseHostnameAsPlace(this, "UseHostName", true), m_bUseBBCodes(this, "UseBBCodes", true), - m_bUseServerTime(this, "UseServerTime", false), m_wstrCListGroup(this, SKYPE_SETTINGS_GROUP, L"Skype"), m_wstrPlace(this, "Place", L""), m_iMood(this, "Mood", 0), @@ -79,6 +78,11 @@ void CSkypeProto::OnEventDeleted(MCONTACT hContact, MEVENT hDbEvent, int flags) PushRequest(new DeleteMessageRequest(this, getId(hContact), dbei.szId)); } +void CSkypeProto::OnEventEdited(MCONTACT hContact, MEVENT, const DBEVENTINFO &dbei) +{ + SendServerMsg(hContact, dbei.pBlob, dbei.iTimestamp); +} + void CSkypeProto::OnModulesLoaded() { setAllContactStatuses(ID_STATUS_OFFLINE, false); @@ -188,6 +192,11 @@ int CSkypeProto::GetInfo(MCONTACT hContact, int) return 0; } +int CSkypeProto::SendMsg(MCONTACT hContact, MEVENT, const char *szMessage) +{ + return SendServerMsg(hContact, szMessage); +} + int CSkypeProto::SetStatus(int iNewStatus) { if (iNewStatus == m_iDesiredStatus) diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 0653e771fa..f7b30ed573 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -26,7 +26,7 @@ struct COwnMessage {} int hMessage; - int64_t hClientMessageId; + int64_t hClientMessageId, iTimestamp = -1; }; struct CSkypeTransfer @@ -86,7 +86,7 @@ public: void OnBuildProtoMenu(void) override; bool OnContactDeleted(MCONTACT, uint32_t flags) override; MWindow OnCreateAccMgrUI(MWindow) override; - // void OnEventEdited(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO &dbei) override; + void OnEventEdited(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO &dbei) override; void OnEventDeleted(MCONTACT hContact, MEVENT hDbEvent, int flags) override; void OnMarkRead(MCONTACT, MEVENT) override; void OnModulesLoaded() override; @@ -117,7 +117,6 @@ public: CMOption m_bAutoHistorySync; CMOption m_bUseBBCodes; - CMOption m_bUseServerTime; // hidden setting! CMOption m_bUseHostnameAsPlace; CMOption m_wstrPlace; @@ -269,6 +268,8 @@ private: // messages std::map m_mpOutMessagesIds; + int SendServerMsg(MCONTACT hContact, const char *szMessage, int64_t iMessageId = 0); + int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); void ProcessContactRecv(MCONTACT hContact, const char *szContent, DB::EventInfo &dbei); -- cgit v1.2.3