From d759d08e5b180f5a872ffde53dbb764d52b73724 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 20 Jul 2024 15:58:03 +0300 Subject: =?UTF-8?q?fixes=20#4548=20(SkypeWeb:=20=D0=BE=D1=80=D0=B3=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D1=8C=20=D0=B8=D1=81=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=B3=D1=80=D1=83=D0=BF=D1=87=D0=B0=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B2=20=D0=91=D0=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocols/SkypeWeb/src/skype_chatrooms.cpp | 36 +--------- protocols/SkypeWeb/src/skype_db.cpp | 74 ++----------------- protocols/SkypeWeb/src/skype_history_sync.cpp | 100 +++++++++++++------------- protocols/SkypeWeb/src/skype_messages.cpp | 73 +++++++++++-------- protocols/SkypeWeb/src/skype_polling.cpp | 15 ---- protocols/SkypeWeb/src/skype_proto.h | 8 --- 6 files changed, 101 insertions(+), 205 deletions(-) (limited to 'protocols') diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp index ddd627f46d..a5e6652c32 100644 --- a/protocols/SkypeWeb/src/skype_chatrooms.cpp +++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . void CSkypeProto::InitGroupChatModule() { GCREGISTER gcr = {}; + gcr.dwFlags = GC_DATABASE | GC_PERSISTENT; gcr.iMaxText = 0; gcr.ptszDispName = m_tszUserName; gcr.pszModule = m_szModuleName; @@ -248,10 +249,6 @@ void CSkypeProto::OnChatEvent(const JSONNode &node) CMStringW wszTopic(node["threadtopic"].as_mstring()); CMStringW wszContent(node["content"].as_mstring()); - time_t timestamp = IsoToUnixTime(node["composetime"].as_string()); - - int nEmoteOffset = node["skypeemoteoffset"].as_int(); - SESSION_INFO *si = Chat_Find(wszChatId, m_szModuleName); if (si == nullptr) { si = StartChatRoom(wszChatId, wszTopic); @@ -262,11 +259,7 @@ void CSkypeProto::OnChatEvent(const JSONNode &node) } std::string messageType = node["messagetype"].as_string(); - if (messageType == "Text" || messageType == "RichText") { - CMStringW wszClearedContent(messageType == "RichText" ? RemoveHtml(wszContent) : wszContent); - AddMessageToChat(si, szFromId, wszClearedContent, nEmoteOffset != NULL, nEmoteOffset, timestamp); - } - else if (messageType == "ThreadActivity/AddMember") { + if (messageType == "ThreadActivity/AddMember") { // 14291862291648:initiator8:user TiXmlDocument doc; if (0 != doc.Parse(T2Utf(wszContent))) @@ -355,31 +348,6 @@ void CSkypeProto::SendChatMessage(SESSION_INFO *si, const wchar_t *tszMessage) PushRequest(new SendChatMessageRequest(chat_id, time(0), szMessage)); } -void CSkypeProto::AddMessageToChat(SESSION_INFO *si, const wchar_t *from, const wchar_t *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading) -{ - ptrW tnick(GetChatContactNick(si->hContact, from)); - - GCEVENT gce = { si, isAction ? GC_EVENT_ACTION : GC_EVENT_MESSAGE }; - gce.bIsMe = IsMe(from); - gce.pszNick.w = tnick; - gce.time = timestamp; - gce.pszUID.w = from; - - CMStringW wszText(content); - wszText.Replace(L"%", L"%%"); - - if (!isAction) { - gce.pszText.w = wszText; - gce.dwFlags |= GCEF_ADDTOLOG; - } - else gce.pszText.w = wszText.c_str() + emoteOffset; - - if (isLoading) - gce.dwFlags |= GCEF_NOTNOTIFY; - - Chat_Event(&gce); -} - void CSkypeProto::OnGetChatInfo(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); diff --git a/protocols/SkypeWeb/src/skype_db.cpp b/protocols/SkypeWeb/src/skype_db.cpp index 0ea0be0fb2..2786e7727b 100644 --- a/protocols/SkypeWeb/src/skype_db.cpp +++ b/protocols/SkypeWeb/src/skype_db.cpp @@ -17,7 +17,12 @@ along with this program. If not, see . #include "stdafx.h" -struct { int type; char *name; uint32_t flags; } g_SkypeDBTypes[] = +struct { + int type; + char *name; + int flags; +} +static g_SkypeDBTypes[] = { { SKYPE_DB_EVENT_TYPE_INCOMING_CALL, LPGEN("Incoming call"), DETF_NONOTIFY }, { SKYPE_DB_EVENT_TYPE_EDITED_MESSAGE, LPGEN("Edited message"), 0 }, @@ -30,73 +35,6 @@ struct { int type; char *name; uint32_t flags; } g_SkypeDBTypes[] = { SKYPE_DB_EVENT_TYPE_UNKNOWN, LPGEN("Unknown event"), 0 }, }; -MEVENT CSkypeProto::GetMessageFromDb(const char *messageId) -{ - if (messageId == nullptr) - return NULL; - - return db_event_getById(m_szModuleName, messageId); -} - -MEVENT CSkypeProto::AddDbEvent(uint16_t type, MCONTACT hContact, uint32_t timestamp, uint32_t flags, const CMStringW &content, const CMStringA &msgId) -{ - if (MEVENT hDbEvent = GetMessageFromDb(msgId)) - return hDbEvent; - - T2Utf szMsg(content); - DBEVENTINFO dbei = {}; - dbei.szModule = m_szModuleName; - dbei.timestamp = timestamp; - dbei.eventType = type; - dbei.cbBlob = (uint32_t)mir_strlen(szMsg) + 1; - dbei.pBlob = szMsg; - dbei.flags = flags; - dbei.szId = msgId; - return db_event_add(hContact, &dbei); -} - -void CSkypeProto::EditEvent(MEVENT hEvent, const CMStringW &szContent, time_t edit_time) -{ - mir_cslock lck(m_AppendMessageLock); - - DB::EventInfo dbei(hEvent); - if (!dbei) - return; - - JSONNode jMsg = JSONNode::parse((char*)dbei.pBlob); - if (jMsg) { - JSONNode &jEdits = jMsg["edits"]; - if (jEdits) { - for (auto &it : jEdits) - if (it["time"].as_int() == edit_time) - return; - - JSONNode jEdit; - jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); - jEdits << jEdit; - } - } - else { - JSONNode jOriginalMsg; jOriginalMsg.set_name("original_message"); - jOriginalMsg << INT_PARAM("time", (long)dbei.timestamp) << CHAR_PARAM("text", (char *)dbei.pBlob); - - jMsg = JSONNode(); - jMsg << jOriginalMsg; - - JSONNode jEdit; - jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); - - JSONNode jEdits(JSON_ARRAY); jEdits.set_name("edits"); - jEdits << jEdit; - jMsg << jEdits; - } - - std::string newMsg = jMsg.write().c_str(); - dbei.cbBlob = int(newMsg.size() + 1); - dbei.pBlob = (char *)newMsg.c_str(); - db_event_edit(hEvent, &dbei, true); -} - void CSkypeProto::InitDBEvents() { // custom event diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index 7c5092c0b3..3984845d7c 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -27,7 +27,6 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * auto &root = reply.data(); const JSONNode &metadata = root["_metadata"]; - const JSONNode &conversations = root["messages"].as_array(); int totalCount = metadata["totalCount"].as_int(); std::string syncState = metadata["syncState"].as_string(); @@ -37,17 +36,16 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * uint32_t lastMsgTime = 0; time_t iLocalTime = time(0); - for (int i = (int)conversations.size(); i >= 0; i--) { - const JSONNode &message = conversations.at(i); - + auto &conv = root["messages"]; + for (auto it = conv.rbegin(); it != conv.rend(); ++it) { + auto &message = *it; CMStringA szMessageId = message["clientmessageid"] ? message["clientmessageid"].as_string().c_str() : message["skypeeditedid"].as_string().c_str(); - int userType; - CMStringW wszChatId = UrlToSkypeId(message["conversationLink"].as_mstring(), &userType); - CMStringW wszContent = message["content"].as_mstring(); - CMStringW wszFrom = UrlToSkypeId(message["from"].as_mstring()); + int iUserType; + CMStringA szChatId = UrlToSkypeId(message["conversationLink"].as_mstring(), &iUserType); + CMStringA szFrom = UrlToSkypeId(message["from"].as_mstring()); - MCONTACT hContact = FindContact(wszChatId); + MCONTACT hContact = FindContact(szChatId); std::string messageType = message["messagetype"].as_string(); int emoteOffset = message["skypeemoteoffset"].as_int(); @@ -55,7 +53,12 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * if (timestamp > getDword(hContact, "LastMsgTime", 0)) setDword(hContact, "LastMsgTime", timestamp); - bool isEdited = message["skypeeditedid"]; + CMStringW wszContent = message["content"].as_mstring(); + T2Utf szMsg(wszContent); + if (messageType == "RichText/Contacts") { + ProcessContactRecv(hContact, timestamp, szMsg, szMessageId); + return; + } uint32_t id = message["id"].as_int(); if (id > lastMsgTime) @@ -64,53 +67,50 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * if (bUseLocalTime) timestamp = iLocalTime; - if (userType == 8 || userType == 2) { - uint32_t iFlags = DBEF_UTF; + DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); - if (!markAllAsUnread) - iFlags |= DBEF_READ; + dbei.flags = DBEF_UTF; + if (!markAllAsUnread) + dbei.flags |= DBEF_READ; + if (IsMe(szFrom)) + dbei.flags |= DBEF_SENT; - if (IsMe(wszFrom)) - iFlags |= DBEF_SENT; - - if (messageType == "Text" || messageType == "RichText") { - CMStringW szMessage(messageType == "RichText" ? RemoveHtml(wszContent) : wszContent); - MEVENT dbevent = GetMessageFromDb(szMessageId); - if (isEdited && dbevent != NULL) - EditEvent(dbevent, szMessage, timestamp); - else - AddDbEvent(emoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, iFlags, szMessage.c_str()+emoteOffset, szMessageId); - } - else if (messageType == "Event/Call") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, iFlags, wszContent, szMessageId); - } - else if (messageType == "RichText/Files") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, iFlags, wszContent, szMessageId); - } - else if (messageType == "RichText/UriObject") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, iFlags, wszContent, szMessageId); - } - else if (messageType == "RichText/Contacts") { - ProcessContactRecv(hContact, timestamp, T2Utf(wszContent), szMessageId); - } - else if (messageType == "RichText/Media_Album") { - // do nothing - } - else { - AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, iFlags, wszContent, szMessageId); - } + if (messageType == "Text" || messageType == "RichText") { + CMStringW szMessage(messageType == "RichText" ? RemoveHtml(wszContent) : wszContent); + dbei.eventType = (emoteOffset == 0) ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION; + } + else if (messageType == "Event/Call") { + dbei.eventType = SKYPE_DB_EVENT_TYPE_CALL_INFO; + } + else if (messageType == "RichText/Files") { + dbei.eventType = SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO; + } + else if (messageType == "RichText/UriObject") { + dbei.eventType = SKYPE_DB_EVENT_TYPE_URIOBJ; + } + else if (messageType == "RichText/Media_Album") { + // do nothing + } + else { + dbei.eventType = SKYPE_DB_EVENT_TYPE_UNKNOWN; } - else if (userType == 19) { - auto *si = Chat_Find(wszChatId, m_szModuleName); - if (si == nullptr) - return; - if (messageType == "Text" || messageType == "RichText") - AddMessageToChat(si, wszFrom, messageType == "RichText" ? RemoveHtml(wszContent) : wszContent, emoteOffset != NULL, emoteOffset, timestamp, true); + dbei.szModule = m_szModuleName; + dbei.timestamp = timestamp; + dbei.cbBlob = (uint32_t)mir_strlen(szMsg); + dbei.pBlob = szMsg; + dbei.szId = szMessageId; + if (iUserType == 19) + dbei.szUserId = szFrom; + + if (dbei) { + db_event_edit(dbei.getEvent(), &dbei, true); + dbei.pBlob = nullptr; } + else db_event_add(hContact, &dbei); } - if (totalCount >= 99 || conversations.size() >= 99) { + if (totalCount >= 99 || conv.size() >= 99) { CMStringA szUrl(pRequest->m_szUrl); int i1 = szUrl.Find("startTime="); int i2 = szUrl.Find("&", i1); diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index 17fc4ebc70..4c57fa2322 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -87,19 +87,21 @@ int CSkypeProto::OnPreCreateMessage(WPARAM, LPARAM lParam) /* MESSAGE EVENT */ -void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node) +void CSkypeProto::ProcessNewMessage(const JSONNode &node) { - CMStringA szMessageId = node["clientmessageid"] ? node["clientmessageid"].as_string().c_str() : node["skypeeditedid"].as_string().c_str(); + int iUserType; + UrlToSkypeId(node["conversationLink"].as_string().c_str(), &iUserType); + + CMStringA szMessageId = node["clientmessageid"] ? node["clientmessageid"].as_mstring() : node["skypeeditedid"].as_mstring(); CMStringA szConversationName(UrlToSkypeId(node["conversationLink"].as_string().c_str())); - CMStringA szFromSkypename(UrlToSkypeId(node["from"].as_string().c_str())); - + CMStringA szFromSkypename(UrlToSkypeId(node["from"].as_mstring())); + CMStringW wszContent = node["content"].as_mstring(); std::string strMessageType = node["messagetype"].as_string(); if (strMessageType == "RichText") wszContent = RemoveHtml(wszContent); - bool bEdited = node["skypeeditedid"]; time_t timestamp = time(0); // fuck the server time, we need to place events in the order of our local time int nEmoteOffset = node["skypeemoteoffset"].as_int(); @@ -115,11 +117,24 @@ void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node) if (strMessageType == "Control/Typing") { CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_INFINITE); + return; } - else if (strMessageType == "Control/ClearTyping") { + if (strMessageType == "Control/ClearTyping") { CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF); + return; } - else if (strMessageType == "Text" || strMessageType == "RichText") { + + T2Utf szMsg(wszContent); + + DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); + dbei.timestamp = timestamp; + dbei.pBlob = szMsg; + dbei.cbBlob = (uint32_t)mir_strlen(szMsg); + dbei.szId = szMessageId; + if (iUserType == 19) + dbei.szUserId = szFromSkypename; + + if (strMessageType == "Text" || strMessageType == "RichText") { if (IsMe(szFromSkypename)) { HANDLE hMessage = (HANDLE)atoi(szMessageId); if (m_OutMessages.getIndex(hMessage) != -1) { @@ -127,50 +142,48 @@ void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node) mir_cslock lck(m_lckOutMessagesList); m_OutMessages.remove(hMessage); - } - else AddDbEvent(nEmoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, dwFlags, wszContent.c_str()+nEmoteOffset, szMessageId); - } - else { - CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF); - - MEVENT hDbEvent = GetMessageFromDb(szMessageId); - if (bEdited && hDbEvent != NULL) - EditEvent(hDbEvent, wszContent, timestamp); - else { - T2Utf szMsg(wszContent); - DB::EventInfo dbei; - dbei.timestamp = timestamp; - dbei.pBlob = szMsg; - dbei.cbBlob = nEmoteOffset; - dbei.szId = szMessageId; - ProtoChainRecvMsg(hContact, dbei); + return; } } + else CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF); + + dbei.eventType = nEmoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION; } else if (strMessageType == "Event/Call") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, dwFlags, wszContent, szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_CALL_INFO; } else if (strMessageType == "RichText/Files") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, dwFlags, wszContent , szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO; } else if (strMessageType == "RichText/UriObject") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, dwFlags, wszContent, szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_URIOBJ; } else if (strMessageType == "RichText/Contacts") { ProcessContactRecv(hContact, timestamp, T2Utf(wszContent), szMessageId); + return; } else if (strMessageType == "RichText/Media_FlikMsg") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_MOJI, hContact, timestamp, dwFlags, wszContent, szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_MOJI; } else if (strMessageType == "RichText/Media_GenericFile") { - AddDbEvent(SKYPE_DB_EVENT_TYPE_FILE, hContact, timestamp, dwFlags, wszContent, szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_FILE; } else if (strMessageType == "RichText/Media_Album") { // do nothing } + else if (iUserType == 19) { + OnChatEvent(node); + return; + } else { - AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, dwFlags, wszContent, szMessageId); + dbei.eventType = SKYPE_DB_EVENT_TYPE_UNKNOWN; + } + + if (dbei) { + db_event_edit(dbei.getEvent(), &dbei, true); + dbei.pBlob = nullptr; } + else ProtoChainRecvMsg(hContact, dbei); } void CSkypeProto::OnMarkRead(MCONTACT hContact, MEVENT hDbEvent) diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index e0dac080bc..5a680dab30 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -189,20 +189,5 @@ void CSkypeProto::ProcessUserPresence(const JSONNode &node) } } -void CSkypeProto::ProcessNewMessage(const JSONNode &node) -{ - debugLogA(__FUNCTION__); - - std::string conversationLink = node["conversationLink"].as_string(); - - int iUserType; - UrlToSkypeId(conversationLink.c_str(), &iUserType); - - if (iUserType == 2 || iUserType == 8) - OnPrivateMessageEvent(node); - else if (iUserType == 19) - OnChatEvent(node); -} - void CSkypeProto::ProcessConversationUpdate(const JSONNode &) {} void CSkypeProto::ProcessThreadUpdate(const JSONNode &) {} diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index f6fa6faf31..a4f9d7850f 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -180,7 +180,6 @@ private: mir_cs m_lckOutMessagesList; mir_cs messageSyncLock; mir_cs m_StatusLock; - mir_cs m_AppendMessageLock; bool m_bThreadsTerminated; @@ -253,16 +252,10 @@ private: // messages std::map m_mpOutMessagesIds; - MEVENT GetMessageFromDb(const char *messageId); - MEVENT AddDbEvent(uint16_t type, MCONTACT hContact, uint32_t timestamp, uint32_t flags, const CMStringW &content, const CMStringA &msgId); - void EditEvent(MEVENT hEvent, const CMStringW &content, time_t edit_time); - int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); void MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent); - void OnPrivateMessageEvent(const JSONNode &node); - void ProcessContactRecv(MCONTACT hContact, time_t timestamp, const char *szContent, const char *szMessageId); // chats @@ -278,7 +271,6 @@ private: void OnChatEvent(const JSONNode &node); wchar_t* GetChatContactNick(MCONTACT hContact, const wchar_t *id, const wchar_t *name = nullptr); - void AddMessageToChat(SESSION_INFO *si, const wchar_t *from, const wchar_t *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading = false); void AddChatContact(SESSION_INFO *si, const wchar_t *id, const wchar_t *role, bool isChange = false); void RemoveChatContact(SESSION_INFO *si, const wchar_t *id, bool isKick = false, const wchar_t *initiator = L""); void SendChatMessage(SESSION_INFO *si, const wchar_t *tszMessage); -- cgit v1.2.3