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 | |
9 | using namespace Quotient; |
10 | |
11 | UriResolverBase::~UriResolverBase() = default; |
12 | |
13 | UriResolveResult 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() |
57 | template <typename... FnTs> |
58 | class StaticUriDispatcher : public UriResolverBase { |
59 | public: |
60 | StaticUriDispatcher(const FnTs&... fns) : fns_(fns...) {} |
61 | |
62 | private: |
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 | }; |
83 | template <typename... FnTs> |
84 | StaticUriDispatcher(FnTs&&... fns) -> StaticUriDispatcher<FnTs...>; |
85 | |
86 | UriResolveResult 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 | |
98 | UriResolveResult UriDispatcher::visitUser(User *user, const QString &action) |
99 | { |
100 | emit userAction(user, action); |
101 | return UriResolved; |
102 | } |
103 | |
104 | void UriDispatcher::visitRoom(Room *room, const QString &eventId) |
105 | { |
106 | emit roomAction(room, eventId); |
107 | } |
108 | |
109 | void UriDispatcher::joinRoom(Connection* account, const QString& roomAliasOrId, |
110 | const QStringList& viaServers) |
111 | { |
112 | emit joinAction(account, roomAliasOrId, viaServers); |
113 | } |
114 | |
115 | bool UriDispatcher::visitNonMatrix(const QUrl &url) |
116 | { |
117 | emit nonMatrixAction(url); |
118 | return true; |
119 | } |
120 | |