1// SPDX-FileCopyrightText: 2020 Kitsune Ral <kitsune-ral@users.sf.net>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#include "uriresolver.h"
5
6#include "connection.h"
7#include "user.h"
8
9using namespace Quotient;
10
11UriResolverBase::~UriResolverBase() = default;
12
13UriResolveResult UriResolverBase::visitResource(Connection* account,
14 const Uri& uri)
15{
16 switch (uri.type()) {
17 case Uri::NonMatrix:
18 return visitNonMatrix(url: uri.toUrl()) ? UriResolved : CouldNotResolve;
19 case Uri::Invalid:
20 case Uri::Empty:
21 return InvalidUri;
22 default:;
23 }
24
25 if (!account)
26 return NoAccount;
27
28 switch (uri.type()) {
29 case Uri::UserId: {
30 if (uri.action() == "join"_ls)
31 return IncorrectAction;
32 auto* user = account->user(uId: uri.primaryId());
33 Q_ASSERT(user != nullptr);
34 return visitUser(user, action: uri.action());
35 }
36 case Uri::RoomId:
37 case Uri::RoomAlias: {
38 auto* room = uri.type() == Uri::RoomId
39 ? account->room(roomId: uri.primaryId())
40 : account->roomByAlias(roomAlias: uri.primaryId());
41 if (room != nullptr) {
42 visitRoom(room, eventId: uri.secondaryId());
43 return UriResolved;
44 }
45 if (uri.action() == "join"_ls) {
46 joinRoom(account, roomAliasOrId: uri.primaryId(), viaServers: uri.viaServers());
47 return UriResolved;
48 }
49 [[fallthrough]];
50 }
51 default:
52 return CouldNotResolve;
53 }
54}
55
56// This template is only instantiated once, for Quotient::visitResource()
57template <typename... FnTs>
58class StaticUriDispatcher : public UriResolverBase {
59public:
60 StaticUriDispatcher(const FnTs&... fns) : fns_(fns...) {}
61
62private:
63 UriResolveResult visitUser(User* user, const QString& action) override
64 {
65 return std::get<0>(fns_)(user, action);
66 }
67 void visitRoom(Room* room, const QString& eventId) override
68 {
69 std::get<1>(fns_)(room, eventId);
70 }
71 void joinRoom(Connection* account, const QString& roomAliasOrId,
72 const QStringList& viaServers = {}) override
73 {
74 std::get<2>(fns_)(account, roomAliasOrId, viaServers);
75 }
76 bool visitNonMatrix(const QUrl& url) override
77 {
78 return std::get<3>(fns_)(url);
79 }
80
81 std::tuple<FnTs...> fns_;
82};
83template <typename... FnTs>
84StaticUriDispatcher(FnTs&&... fns) -> StaticUriDispatcher<FnTs...>;
85
86UriResolveResult Quotient::visitResource(
87 Connection* account, const Uri& uri,
88 std::function<UriResolveResult(User*, QString)> userHandler,
89 std::function<void(Room*, QString)> roomEventHandler,
90 std::function<void(Connection*, QString, QStringList)> joinHandler,
91 std::function<bool(const QUrl&)> nonMatrixHandler)
92{
93 return StaticUriDispatcher(userHandler, roomEventHandler, joinHandler,
94 nonMatrixHandler)
95 .visitResource(account, uri);
96}
97
98UriResolveResult UriDispatcher::visitUser(User *user, const QString &action)
99{
100 emit userAction(user, action);
101 return UriResolved;
102}
103
104void UriDispatcher::visitRoom(Room *room, const QString &eventId)
105{
106 emit roomAction(room, eventId);
107}
108
109void UriDispatcher::joinRoom(Connection* account, const QString& roomAliasOrId,
110 const QStringList& viaServers)
111{
112 emit joinAction(account, roomAliasOrId, viaServers);
113}
114
115bool UriDispatcher::visitNonMatrix(const QUrl &url)
116{
117 emit nonMatrixAction(url);
118 return true;
119}
120