Page MenuHomePhorge

D34.1726783767.diff
No OneTemporary

D34.1726783767.diff

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -22,6 +22,7 @@
matrix-event-reader.cpp
matrix-event-reader-list-model.cpp
matrix-event.cpp
+ matrix-link.cpp
meta-types.cpp
l10n-provider.cpp
qt-rand-adapter.cpp
diff --git a/src/matrix-link.hpp b/src/matrix-link.hpp
new file mode 100644
--- /dev/null
+++ b/src/matrix-link.hpp
@@ -0,0 +1,52 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#pragma once
+#include <libkazv-config.hpp>
+
+#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
+
+#include <tuple>
+#include <vector>
+#include <QObject>
+#include <QStringList>
+
+class QUrl;
+
+/**
+ * A link that represents a Matrix object.
+ */
+class MatrixLink
+{
+ Q_GADGET
+ Q_PROPERTY(bool isUser READ isUser CONSTANT)
+ Q_PROPERTY(bool isRoom READ isRoom CONSTANT)
+ Q_PROPERTY(bool isEvent READ isEvent CONSTANT)
+ Q_PROPERTY(QStringList identifiers READ identifiers CONSTANT)
+ Q_PROPERTY(QStringList routingServers READ routingServers CONSTANT)
+
+public:
+ enum Type {
+ None,
+ User,
+ RoomId,
+ RoomAlias,
+ Event,
+ };
+
+ MatrixLink(const QUrl &url);
+
+ bool isValid() const;
+ bool isUser() const;
+ bool isRoom() const;
+ bool isEvent() const;
+ QStringList identifiers() const;
+ QStringList routingServers() const;
+
+private:
+ std::vector<std::pair<Type, QString>> m_identifiers;
+ QStringList m_routingServers;
+};
diff --git a/src/matrix-link.cpp b/src/matrix-link.cpp
new file mode 100644
--- /dev/null
+++ b/src/matrix-link.cpp
@@ -0,0 +1,102 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+
+#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
+
+#include <QUrl>
+#include <QUrlQuery>
+#include <QDebug>
+
+#include "matrix-link.hpp"
+
+std::pair<MatrixLink::Type, QString> parseMatrixToComp(QString comp)
+{
+ comp = QUrl("foo:#" + comp).fragment(QUrl::FullyDecoded);
+ if (comp.startsWith('@')) {
+ return {MatrixLink::User, comp};
+ } else if (comp.startsWith('#')) {
+ return {MatrixLink::RoomAlias, comp};
+ } else if (comp.startsWith('!')) {
+ return {MatrixLink::RoomId, comp};
+ } else if (comp.startsWith('$')) {
+ return {MatrixLink::Event, comp};
+ } else {
+ return {MatrixLink::None, comp};
+ }
+}
+
+QStringList parseMatrixToQuery(QString query)
+{
+ auto q = QUrlQuery(query);
+ return q.allQueryItemValues("via");
+}
+
+MatrixLink::MatrixLink(const QUrl &url)
+{
+ // matrix.to link
+ if (url.scheme() == "https"
+ && url.host() == "matrix.to") {
+ auto frag = url.fragment();
+ auto parts = frag.split('?');
+ QString ids = parts[0];
+ QString query = parts.size() > 1 ? parts[1] : "";
+
+ auto comps = ids.split('/');
+ if (comps.empty() || comps[0] != "") {
+ return;
+ }
+ comps.pop_front();
+ for (auto comp : comps) {
+ m_identifiers.push_back(parseMatrixToComp(comp));
+ }
+
+ m_routingServers = parseMatrixToQuery(query);
+ }
+}
+
+bool MatrixLink::isValid() const
+{
+ return !m_identifiers.empty()
+ && m_identifiers[0].first != None
+ && m_identifiers[0].first != Event
+ && (m_identifiers.size() == 1 || (
+ m_identifiers[1].first == Event
+ && (m_identifiers[0].first == RoomId
+ || m_identifiers[0].first == RoomAlias)));
+}
+
+bool MatrixLink::isUser() const
+{
+ return isValid() && m_identifiers[0].first == User;
+}
+
+bool MatrixLink::isRoom() const
+{
+ return isValid() && (
+ m_identifiers[0].first == RoomId
+ || m_identifiers[0].first == RoomAlias);
+}
+
+bool MatrixLink::isEvent() const
+{
+ return isValid() && m_identifiers.size() == 2;
+}
+
+QStringList MatrixLink::identifiers() const
+{
+ QStringList ret;
+ for (auto [_, id] : m_identifiers) {
+ ret.push_back(id);
+ }
+ return ret;
+}
+
+QStringList MatrixLink::routingServers() const
+{
+ return m_routingServers;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -18,6 +18,7 @@
matrix-room-list-test.cpp
kazv-markdown-test.cpp
matrix-sticker-pack-test.cpp
+ matrix-link-test.cpp
LINK_LIBRARIES Qt5::Test kazvtestlib
)
diff --git a/src/tests/matrix-link-test.cpp b/src/tests/matrix-link-test.cpp
new file mode 100644
--- /dev/null
+++ b/src/tests/matrix-link-test.cpp
@@ -0,0 +1,106 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
+
+#include <vector>
+#include <QtTest>
+
+#include "matrix-link.hpp"
+
+class MatrixLinkTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void testInvalidLink();
+ void testUserLink();
+ void testRoomLink();
+ void testEventLink();
+ void testRoutingServers();
+};
+
+void MatrixLinkTest::testInvalidLink()
+{
+ std::vector<QUrl> links = {
+ QUrl("https://matrix.to/#"),
+ QUrl("https://matrix.to/#/"),
+ QUrl("https://matrix.to/#//"),
+ QUrl("https://matrix.to/#///"),
+ QUrl("http://matrix.to/#/%40alice%3Aexample.org"),
+ QUrl("https://lol.lol/#/%40alice%3Aexample.org"),
+ QUrl("https://matrix.to/#%40alice%3Aexample.org"),
+ };
+ for (auto link : links) {
+ MatrixLink ml(link);
+ QVERIFY(!ml.isValid());
+ }
+}
+
+void MatrixLinkTest::testUserLink()
+{
+ std::vector<QUrl> links = {
+ QUrl("https://matrix.to/#/%40alice%3Aexample.org"),
+ QUrl("https://matrix.to/#/@alice%3Aexample.org"),
+ QUrl("https://matrix.to/#/%40alice:example.org"),
+ QUrl("https://matrix.to/#/@alice:example.org"),
+ };
+ for (auto link : links) {
+ MatrixLink ml(link);
+ QVERIFY(ml.isUser());
+ QCOMPARE(ml.identifiers(), QStringList{"@alice:example.org"});
+ }
+}
+
+void MatrixLinkTest::testRoomLink()
+{
+ std::vector<std::tuple<QUrl, QString>> links = {
+ {QUrl("https://matrix.to/#/%23somewhere%3Aexample.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/%23somewhere:example.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/#somewhere%3Aexample.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/#somewhere:example.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere%3Aexample.org?via=elsewhere.ca"), "!somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere:example.org?via=elsewhere.ca"), "!somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere%3Aexample.org"), "!somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere:example.org"), "!somewhere:example.org"},
+ };
+ for (auto [link, pointed] : links) {
+ MatrixLink ml(link);
+ QVERIFY(ml.isRoom());
+ QCOMPARE(ml.identifiers(), QStringList{pointed});
+ }
+}
+
+void MatrixLinkTest::testEventLink()
+{
+ std::vector<std::tuple<QUrl, QString>> links = {
+ {QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event%3Aexample.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event:example.org"), "#somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere%3Aexample.org/%24event%3Aexample.org?via=elsewhere.ca"), "!somewhere:example.org"},
+ {QUrl("https://matrix.to/#/!somewhere%3Aexample.org/$event:example.org?via=elsewhere.ca"), "!somewhere:example.org"},
+ };
+ for (auto [link, pointed] : links) {
+ MatrixLink ml(link);
+ QVERIFY(ml.isRoom());
+ QCOMPARE(ml.identifiers(), (QStringList{pointed, "$event:example.org"}));
+ }
+}
+
+void MatrixLinkTest::testRoutingServers()
+{
+ QCOMPARE(MatrixLink(QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event:example.org")).routingServers(), (QStringList{}));
+
+ QCOMPARE(MatrixLink(QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event:example.org?via=a.org")).routingServers(), (QStringList{"a.org"}));
+
+ QCOMPARE(MatrixLink(QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event:example.org?via=a.org&via=b.org")).routingServers(), (QStringList{"a.org", "b.org"}));
+
+ QCOMPARE(MatrixLink(QUrl("https://matrix.to/#/%23somewhere%3Aexample.org/%24event:example.org?foo=bar&via=a.org&via=b.org")).routingServers(), (QStringList{"a.org", "b.org"}));
+}
+
+QTEST_MAIN(MatrixLinkTest)
+
+#include "matrix-link-test.moc"

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 19, 3:09 PM (5 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15872
Default Alt Text
D34.1726783767.diff (8 KB)

Event Timeline