summaryrefslogtreecommitdiff
path: root/protocols/Teams/src/teams_history.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Teams/src/teams_history.cpp')
-rw-r--r--protocols/Teams/src/teams_history.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/protocols/Teams/src/teams_history.cpp b/protocols/Teams/src/teams_history.cpp
new file mode 100644
index 0000000000..4630b33aa3
--- /dev/null
+++ b/protocols/Teams/src/teams_history.cpp
@@ -0,0 +1,195 @@
+/*
+Copyright (c) 2025 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+/* HISTORY SYNC */
+
+void CTeamsProto::FetchMissingHistory(const JSONNode &node, MCONTACT hContact)
+{
+ const JSONNode &lastMessage = node["lastMessage"];
+ if (lastMessage && hContact) {
+ int64_t id = _atoi64(lastMessage["id"].as_string().c_str());
+ auto lastMsgTime = getLastTime(hContact);
+ if (lastMsgTime && lastMsgTime < id && m_bAutoHistorySync)
+ GetServerHistory(hContact, 100, lastMsgTime, true);
+ }
+}
+
+void CTeamsProto::OnSyncConversations(MHttpResponse *response, AsyncHttpRequest *)
+{
+ TeamsReply reply(response);
+ if (reply.error())
+ return;
+
+ auto &root = reply.data();
+ const JSONNode &conversations = root["conversations"].as_array();
+
+ for (auto &it : conversations) {
+ CMStringA szSkypename = it["id"].as_mstring();
+ int iUserType = atoi(szSkypename);
+ MCONTACT hContact = FindContact(szSkypename);
+
+ switch (iUserType) {
+ case 19:
+ {
+ auto &props = it["threadProperties"];
+ CMStringA szType = props["productThreadType"].as_mstring(), szChatType;
+
+ int idx = szSkypename.ReverseFind('@');
+ if (idx != -1)
+ szChatType = szSkypename.Mid(idx + 1);
+
+ if (szType == "Chat" || szChatType == "thread.skype") {
+ auto *si = StartChatRoom(it["id"].as_mstring(), props["topic"].as_mstring(), props["version"].as_string().c_str());
+ for (auto &cc : props["members"])
+ AddChatContact(si, cc.as_mstring(), L"Admin");
+ }
+ else if (szType == "OneToOneChat") {
+ hContact = FindContact(it["properties"]["addedBy"].as_string().c_str());
+ if (hContact)
+ setString(hContact, "ChatId", szSkypename);
+ }
+ }
+ FetchMissingHistory(it, hContact);
+ break;
+
+ case 8:
+ case 2:
+ CMStringA szChatId(it["properties"]["onetoonethreadid"].as_mstring());
+ if (!szChatId.IsEmpty() && hContact) {
+ if (szChatId.Left(3) != "19:")
+ szChatId.Insert(0, "19:");
+ setString(hContact, "ChatId", szChatId);
+ }
+
+ FetchMissingHistory(it, hContact);
+ }
+ }
+
+ m_bHistorySynced = true;
+}
+
+void CTeamsProto::RefreshConversations()
+{
+ auto *pReq = new AsyncHttpRequest(REQUEST_GET, HOST_CHATS, "/users/ME/conversations", &CTeamsProto::OnSyncConversations);
+ pReq << INT_PARAM("startTime", 0) << INT_PARAM("pageSize", 100)
+ << CHAR_PARAM("view", "msnp24Equivalent") << CHAR_PARAM("targetType", "Passport|Skype|Lync|Thread|PSTN|Agent");
+
+ PushRequest(pReq);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void CTeamsProto::GetServerHistory(MCONTACT hContact, int pageSize, int64_t timestamp, bool bOperative)
+{
+ CMStringA szChatId(getMStringA(hContact, "ChatId"));
+ if (szChatId.IsEmpty())
+ szChatId = getId(hContact);
+
+ auto *pReq = new AsyncHttpRequest(REQUEST_GET, HOST_CHATS, "/users/ME/conversations/" + mir_urlEncode(szChatId) + "/messages", &CTeamsProto::OnGetServerHistory);
+ pReq->hContact = hContact;
+ if (bOperative)
+ pReq->pUserInfo = this;
+
+ pReq << INT64_PARAM("startTime", timestamp) << INT_PARAM("pageSize", pageSize)
+ << CHAR_PARAM("view", "msnp24Equivalent") << CHAR_PARAM("targetType", "Passport|Skype|Lync|Thread");
+
+ PushRequest(pReq);
+}
+
+void CTeamsProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest *pRequest)
+{
+ TeamsReply reply(response);
+ if (reply.error())
+ return;
+
+ auto &root = reply.data();
+ const JSONNode &metadata = root["_metadata"];
+
+ int totalCount = metadata["totalCount"].as_int();
+ std::string syncState = metadata["syncState"].as_string();
+
+ bool bOperative = pRequest->pUserInfo != 0;
+ bool bSetLastTime = false;
+
+ int64_t lastMsgTime = 0; // max timestamp on this page
+
+ auto &conv = root["messages"];
+ for (auto it = conv.rbegin(); it != conv.rend(); ++it) {
+ auto &message = *it;
+ CMStringA szId = message["id"].as_mstring();
+ int64_t id = _atoi64(szId);
+ if (id > lastMsgTime) {
+ bSetLastTime = true;
+ lastMsgTime = id;
+ }
+
+ int iUserType;
+ CMStringA szMessageId(getMessageId(message));
+ CMStringA szChatId = UrlToSkypeId(message["conversationLink"].as_mstring(), &iUserType);
+ CMStringA szFrom = UrlToSkypeId(message["from"].as_mstring());
+
+ DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId));
+ dbei.hContact = pRequest->hContact;
+ dbei.szModule = m_szModuleName;
+ 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;
+
+ CMStringA szType(message["messagetype"].as_mstring());
+ if (szType.Left(15) == "ThreadActivity/")
+ continue;
+ }
+
+ if (!bOperative && !dbei.getEvent())
+ dbei.bRead = true;
+
+ if (ParseMessage(message, dbei)) {
+ if (dbei)
+ db_event_edit(dbei.getEvent(), &dbei, true);
+ else
+ db_event_add(pRequest->hContact, &dbei);
+ }
+ }
+
+ if (bSetLastTime && lastMsgTime > getLastTime(pRequest->hContact))
+ setLastTime(pRequest->hContact, lastMsgTime);
+
+ if (totalCount >= 99 || conv.size() >= 99)
+ GetServerHistory(pRequest->hContact, 100, lastMsgTime, pRequest->pUserInfo != 0);
+}
+
+INT_PTR CTeamsProto::SvcLoadHistory(WPARAM hContact, LPARAM)
+{
+ GetServerHistory(hContact, 100, 0, false);
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CTeamsProto::SvcEmptyHistory(WPARAM hContact, LPARAM flags)
+{
+ if (flags & CDF_DEL_HISTORY)
+ PushRequest(new AsyncHttpRequest(REQUEST_DELETE, HOST_CHATS, "/users/ME/conversations/" + mir_urlEncode(getId(hContact)) + "/messages"));
+
+ return 0;
+}