File indexing completed on 2024-09-15 04:28:32
0001 // SPDX-FileCopyrightText: 2022 Bharadwaj Raju <bharadwaj.raju777@protonmail.com> 0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-or-later OR LicenseRef-KDE-Accepted-GPL 0003 0004 #include "linkpreviewer.h" 0005 0006 #include <Quotient/connection.h> 0007 #include <Quotient/csapi/content-repo.h> 0008 #include <Quotient/events/roommessageevent.h> 0009 0010 #include "neochatconfig.h" 0011 #include "neochatroom.h" 0012 #include "utils.h" 0013 0014 using namespace Quotient; 0015 0016 LinkPreviewer::LinkPreviewer(const NeoChatRoom *room, const Quotient::RoomMessageEvent *event) 0017 : QObject(nullptr) 0018 , m_currentRoom(room) 0019 , m_event(event) 0020 , m_loaded(false) 0021 , m_url(linkPreview(event)) 0022 { 0023 connect(this, &LinkPreviewer::urlChanged, this, &LinkPreviewer::emptyChanged); 0024 0025 if (m_event != nullptr && m_currentRoom != nullptr) { 0026 loadUrlPreview(); 0027 connect(m_currentRoom, &NeoChatRoom::urlPreviewEnabledChanged, this, &LinkPreviewer::loadUrlPreview); 0028 // Make sure that we react to edits 0029 connect(m_currentRoom, &NeoChatRoom::replacedEvent, this, [this](const Quotient::RoomEvent *newEvent) { 0030 if (m_event->id() == newEvent->id()) { 0031 m_event = eventCast<const Quotient::RoomMessageEvent>(newEvent); 0032 m_url = linkPreview(m_event); 0033 Q_EMIT urlChanged(); 0034 loadUrlPreview(); 0035 } 0036 }); 0037 } 0038 connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, &LinkPreviewer::loadUrlPreview); 0039 } 0040 0041 bool LinkPreviewer::loaded() const 0042 { 0043 return m_loaded; 0044 } 0045 0046 QString LinkPreviewer::title() const 0047 { 0048 return m_title; 0049 } 0050 0051 QString LinkPreviewer::description() const 0052 { 0053 return m_description; 0054 } 0055 0056 QUrl LinkPreviewer::imageSource() const 0057 { 0058 return m_imageSource; 0059 } 0060 0061 QUrl LinkPreviewer::url() const 0062 { 0063 return m_url; 0064 } 0065 0066 void LinkPreviewer::loadUrlPreview() 0067 { 0068 if (!m_currentRoom || !NeoChatConfig::showLinkPreview() || !m_currentRoom->urlPreviewEnabled()) { 0069 return; 0070 } 0071 if (m_url.scheme() == QStringLiteral("https")) { 0072 m_loaded = false; 0073 Q_EMIT loadedChanged(); 0074 0075 auto conn = m_currentRoom->connection(); 0076 GetUrlPreviewJob *job = conn->callApi<GetUrlPreviewJob>(m_url); 0077 0078 connect(job, &BaseJob::success, this, [this, job, conn]() { 0079 const auto json = job->jsonData(); 0080 m_title = json["og:title"_ls].toString().trimmed(); 0081 m_description = json["og:description"_ls].toString().trimmed().replace("\n"_ls, " "_ls); 0082 0083 auto imageUrl = QUrl(json["og:image"_ls].toString()); 0084 if (imageUrl.isValid() && imageUrl.scheme() == QStringLiteral("mxc")) { 0085 m_imageSource = conn->makeMediaUrl(imageUrl); 0086 } else { 0087 m_imageSource = QUrl(); 0088 } 0089 0090 m_loaded = true; 0091 Q_EMIT titleChanged(); 0092 Q_EMIT descriptionChanged(); 0093 Q_EMIT imageSourceChanged(); 0094 Q_EMIT loadedChanged(); 0095 }); 0096 } 0097 } 0098 0099 bool LinkPreviewer::empty() const 0100 { 0101 return m_url.isEmpty(); 0102 } 0103 0104 QUrl LinkPreviewer::linkPreview(const Quotient::RoomMessageEvent *event) 0105 { 0106 if (event == nullptr) { 0107 return {}; 0108 } 0109 0110 QString text; 0111 if (event->hasTextContent()) { 0112 auto textContent = static_cast<const Quotient::EventContent::TextContent *>(event->content()); 0113 if (textContent) { 0114 text = textContent->body; 0115 } else { 0116 text = event->plainBody(); 0117 } 0118 } else { 0119 text = event->plainBody(); 0120 } 0121 0122 auto data = text.remove(TextRegex::removeRichReply); 0123 auto linksMatch = TextRegex::url.globalMatch(data); 0124 while (linksMatch.hasNext()) { 0125 auto link = linksMatch.next().captured(); 0126 if (!link.contains(QStringLiteral("matrix.to"))) { 0127 return QUrl(link); 0128 } 0129 } 0130 return {}; 0131 } 0132 0133 bool LinkPreviewer::hasPreviewableLinks(const Quotient::RoomMessageEvent *event) 0134 { 0135 return !linkPreview(event).isEmpty(); 0136 } 0137 0138 #include "moc_linkpreviewer.cpp"