libkazv
room-model.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of libkazv.
3  * SPDX-FileCopyrightText: 2021-2023 tusooa <tusooa@kazv.moe>
4  * SPDX-License-Identifier: AGPL-3.0-or-later
5  */
6 
7 
8 #pragma once
9 #include <libkazv-config.hpp>
10 
11 #include <string>
12 #include <variant>
13 #include <immer/flex_vector.hpp>
14 #include <immer/map.hpp>
15 
20 
21 #include <csapi/sync.hpp>
22 #include <event.hpp>
23 
24 #include <crypto.hpp>
25 #include "push-rules-desc.hpp"
26 #include "local-echo.hpp"
27 #include "clientutil.hpp"
28 
29 namespace Kazv
30 {
32  {
33  std::string txnId;
34  immer::map<std::string, immer::map<std::string, Event>> messages;
35 
36  friend bool operator==(const PendingRoomKeyEvent &a, const PendingRoomKeyEvent &b) = default;
37  friend bool operator!=(const PendingRoomKeyEvent &a, const PendingRoomKeyEvent &b) = default;
38  };
39 
40  PendingRoomKeyEvent makePendingRoomKeyEventV0(std::string txnId, Event event, immer::map<std::string, immer::flex_vector<std::string>> devices);
41 
42  struct ReadReceipt
43  {
44  std::string eventId;
46  friend bool operator==(const ReadReceipt &a, const ReadReceipt &b) = default;
47  friend bool operator!=(const ReadReceipt &a, const ReadReceipt &b) = default;
48  };
49 
50  template<class Archive>
51  void serialize(Archive &ar, ReadReceipt &r, std::uint32_t const /* version */)
52  {
53  ar & r.eventId & r.timestamp;
54  }
55 
56 
57  struct EventReader
58  {
59  std::string userId;
61  friend bool operator==(const EventReader &a, const EventReader &b) = default;
62  friend bool operator!=(const EventReader &a, const EventReader &b) = default;
63  };
64 
66  {
67  immer::flex_vector<Event> stateEvents;
68  };
69 
74  {
75  immer::flex_vector<Event> stateEvents;
76  };
77 
79  {
81  immer::flex_vector<Event> events;
82  std::optional<std::string> prevBatch;
83  std::optional<bool> limited;
84  std::optional<std::string> gapEventId;
85  };
86 
88  {
89  immer::flex_vector<Event> events;
90  };
91 
93  {
95  };
96 
98  {
99  immer::flex_vector<Event> events;
100  };
101 
103  {
105  };
106 
108  {
109  std::string localDraft;
110  };
111 
113  {
114  };
115 
117  {
118  };
119 
121  {
122  immer::flex_vector<std::string> heroIds;
123  };
124 
126  {
128  };
129 
131  {
132  std::string txnId;
133  };
134 
136  {
138  };
139 
141  {
142  std::string txnId;
143  };
144 
146  {
147  std::size_t joinedMemberCount;
148  };
149 
151  {
152  std::size_t invitedMemberCount;
153  };
154 
159  {
162  std::string myUserId;
163  };
164 
167  {
168  std::string myUserId;
169  };
170 
173  {
174  std::string localReadMarker;
175  std::string myUserId;
176  };
177 
178  inline const double ROOM_TAG_DEFAULT_ORDER = 2;
179 
180  template<class Archive>
181  void serialize(Archive &ar, PendingRoomKeyEvent &e, std::uint32_t const version)
182  {
183  if (version < 1) {
184  // loading an older version where there is only one event
185  std::string txnId;
186  Event event;
187  immer::map<std::string, immer::flex_vector<std::string>> devices;
188  ar & txnId & event & devices;
190  std::move(txnId), std::move(event), std::move(devices));
191  } else {
192  ar & e.txnId & e.messages;
193  }
194  }
195 
206  auto sortKeyForTimelineEvent(Event e) -> std::tuple<Timestamp, std::string>;
207 
208  struct RoomModel
209  {
211  using ReverseEventRelationshipMap = immer::map<
212  std::string /* related event id */,
213  immer::map<std::string /* relation type */, immer::flex_vector<std::string /* relater event id */>>>;
214 
215  std::string roomId;
216  immer::map<KeyOfState, Event> stateEvents;
217  immer::map<KeyOfState, Event> inviteState;
218  // Smaller indices mean earlier events
219  // (oldest) 0 --------> n (latest)
220  immer::flex_vector<std::string> timeline;
221  immer::map<std::string, Event> messages;
222  immer::map<std::string, Event> accountData;
224  std::string paginateBackToken;
226  bool canPaginateBack{true};
227 
228  immer::map<std::string /* eventId */, std::string /* prevBatch */> timelineGaps;
229 
230  immer::map<std::string, Event> ephemeral;
231 
232  std::string localDraft;
233 
234  bool encrypted{false};
240 
241  bool membersFullyLoaded{false};
242  immer::flex_vector<std::string> heroIds;
243 
244  immer::flex_vector<LocalEchoDesc> localEchoes;
245 
246  immer::flex_vector<PendingRoomKeyEvent> pendingRoomKeyEvents;
247 
249 
250  std::size_t joinedMemberCount{0};
251  std::size_t invitedMemberCount{0};
252 
255  std::string localReadMarker;
257  std::size_t localUnreadCount{0};
260  std::size_t localNotificationCount{0};
262  immer::map<std::string /* userId */, ReadReceipt> readReceipts;
265  immer::map<
266  std::string /* eventId */,
267  immer::flex_vector<std::string /* userId */>> eventReadUsers;
268 
271  immer::map<
272  std::string /* sessionId */,
273  immer::flex_vector<std::string /* eventId */>> undecryptedEvents;
274 
275  immer::flex_vector<std::string> unreadNotificationEventIds;
276 
277  immer::flex_vector<std::string> joinedMemberIds() const;
278  immer::flex_vector<std::string> invitedMemberIds() const;
279  immer::flex_vector<std::string> knockedMemberIds() const;
280  immer::flex_vector<std::string> leftMemberIds() const;
281  immer::flex_vector<std::string> bannedMemberIds() const;
282 
286  EventList leftMemberEvents() const;
288  EventList heroMemberEvents() const;
289 
291 
292  bool hasUser(std::string userId) const;
293 
294  std::optional<LocalEchoDesc> getLocalEchoByTxnId(std::string txnId) const;
295  std::optional<PendingRoomKeyEvent> getPendingRoomKeyEventByTxnId(std::string txnId) const;
296 
297  immer::map<std::string, double> tags() const;
298 
299  Event makeAddTagEvent(std::string tagId, std::optional<double> order) const;
300  Event makeRemoveTagEvent(std::string tagId) const;
301 
309  void generateRelationships(EventList newEvents);
310 
312 
319  void addToUndecryptedEvents(EventList newEvents);
320 
322 
323  using Action = std::variant<
344  >;
345 
346  static RoomModel update(RoomModel r, Action a);
347 
348  friend bool operator==(const RoomModel &a, const RoomModel &b) = default;
349  };
350 
352 
354  {
355  std::string roomId;
357  };
358 
360  {
361  immer::map<std::string, RoomModel> rooms;
362 
363  inline auto at(std::string id) const { return rooms.at(id); }
364  inline auto operator[](std::string id) const { return rooms[id]; }
365  inline bool has(std::string id) const { return rooms.find(id); }
366 
367  using Action = std::variant<
369  >;
371 
372  friend bool operator==(const RoomListModel &a, const RoomListModel &b) = default;
373  };
374 
376 
377  template<class Archive>
378  void serialize(Archive &ar, RoomModel &r, std::uint32_t const version)
379  {
380  ar
381  & r.roomId
382  & r.stateEvents
383  & r.inviteState
384 
385  & r.timeline
386  & r.messages
387  & r.accountData
388  & r.membership
390  & r.canPaginateBack
391 
392  & r.timelineGaps
393  & r.ephemeral
394 
395  & r.localDraft
396 
397  & r.encrypted
399 
401  ;
402 
403  if (version >= 1) {
404  ar
405  & r.heroIds
406  ;
407  }
408  if (version >= 2) {
409  ar & r.localEchoes;
410  }
411  if (version >= 3) {
412  ar & r.pendingRoomKeyEvents;
413  }
414  if (version >= 4) {
416  } else { // must be reading from an older version
417  if constexpr (typename Archive::is_loading()) {
419  }
420  }
421  if (version >= 5) {
423  }
424  if (version >= 6) {
425  ar
426  & r.localReadMarker
427  & r.localUnreadCount
429  & r.readReceipts
430  & r.eventReadUsers;
431  }
432  if (version >= 7) {
433  ar & r.undecryptedEvents;
434  } else {
435  if constexpr (typename Archive::is_loading()) {
437  }
438  }
439  if (version >= 8) {
441  }
442  }
443 
444  template<class Archive>
445  void serialize(Archive &ar, RoomListModel &l, std::uint32_t const /*version*/)
446  {
447  ar & l.rooms;
448  }
449 }
450 
451 BOOST_CLASS_VERSION(Kazv::PendingRoomKeyEvent, 1)
452 BOOST_CLASS_VERSION(Kazv::ReadReceipt, 0)
453 BOOST_CLASS_VERSION(Kazv::RoomModel, 8)
454 BOOST_CLASS_VERSION(Kazv::RoomListModel, 0)
Definition: event.hpp:21
Definition: push-rules-desc.hpp:38
Definition: location.hpp:10
RoomModel::Action RoomAction
Definition: room-model.hpp:351
const double ROOM_TAG_DEFAULT_ORDER
Definition: room-model.hpp:178
std::int_fast64_t Timestamp
Definition: event.hpp:18
PendingRoomKeyEvent makePendingRoomKeyEventV0(std::string txnId, Event event, immer::map< std::string, immer::flex_vector< std::string >> devices)
Definition: room-model.cpp:40
auto sortKeyForTimelineEvent(Event e) -> std::tuple< Timestamp, std::string >
Get the sort key for a timeline event.
Definition: room-model.cpp:56
RoomMembership
Definition: types.hpp:128
immer::flex_vector< Event > EventList
Definition: types.hpp:107
void serialize(Archive &ar, ClientModel &m, std::uint32_t const version)
Definition: client-model.hpp:584
RoomListModel::Action RoomListAction
Definition: room-model.hpp:375
Definition: room-model.hpp:88
immer::flex_vector< Event > events
Definition: room-model.hpp:89
Definition: room-model.hpp:103
EventList events
Definition: room-model.hpp:104
Definition: room-model.hpp:126
LocalEchoDesc localEcho
Definition: room-model.hpp:127
Update local notifications to include the new events.
Definition: room-model.hpp:159
std::string myUserId
Definition: room-model.hpp:162
EventList newEvents
Definition: room-model.hpp:160
PushRulesDesc pushRulesDesc
Definition: room-model.hpp:161
Definition: room-model.hpp:136
PendingRoomKeyEvent pendingRoomKeyEvent
Definition: room-model.hpp:137
Definition: room-model.hpp:66
immer::flex_vector< Event > stateEvents
Definition: room-model.hpp:67
Definition: room-model.hpp:79
std::optional< std::string > prevBatch
Definition: room-model.hpp:82
std::optional< std::string > gapEventId
Definition: room-model.hpp:84
std::optional< bool > limited
Definition: room-model.hpp:83
immer::flex_vector< Event > events
Events from oldest to latest.
Definition: room-model.hpp:81
Definition: room-model.hpp:98
immer::flex_vector< Event > events
Definition: room-model.hpp:99
Definition: room-model.hpp:93
RoomMembership membership
Definition: room-model.hpp:94
Definition: room-model.hpp:58
friend bool operator!=(const EventReader &a, const EventReader &b)=default
friend bool operator==(const EventReader &a, const EventReader &b)=default
std::string userId
Definition: room-model.hpp:59
Timestamp timestamp
Definition: room-model.hpp:60
Describes a local echo.
Definition: local-echo.hpp:19
Definition: room-model.hpp:117
Go from the back of stateEvents to the beginning, adding the event to room state only if the room has...
Definition: room-model.hpp:74
immer::flex_vector< Event > stateEvents
Definition: room-model.hpp:75
Definition: crypto.hpp:27
Definition: room-model.hpp:32
friend bool operator!=(const PendingRoomKeyEvent &a, const PendingRoomKeyEvent &b)=default
immer::map< std::string, immer::map< std::string, Event > > messages
Definition: room-model.hpp:34
friend bool operator==(const PendingRoomKeyEvent &a, const PendingRoomKeyEvent &b)=default
std::string txnId
Definition: room-model.hpp:33
Definition: room-model.hpp:43
Timestamp timestamp
Definition: room-model.hpp:45
std::string eventId
Definition: room-model.hpp:44
friend bool operator!=(const ReadReceipt &a, const ReadReceipt &b)=default
friend bool operator==(const ReadReceipt &a, const ReadReceipt &b)=default
Definition: room-model.hpp:131
std::string txnId
Definition: room-model.hpp:132
Definition: room-model.hpp:141
std::string txnId
Definition: room-model.hpp:142
Remove local notifications that are already read.
Definition: room-model.hpp:167
std::string myUserId
Definition: room-model.hpp:168
Definition: room-model.hpp:360
std::variant< UpdateRoomAction > Action
Definition: room-model.hpp:369
auto at(std::string id) const
Definition: room-model.hpp:363
static RoomListModel update(RoomListModel l, Action a)
Definition: room-model.cpp:395
bool has(std::string id) const
Definition: room-model.hpp:365
immer::map< std::string, RoomModel > rooms
Definition: room-model.hpp:361
friend bool operator==(const RoomListModel &a, const RoomListModel &b)=default
auto operator[](std::string id) const
Definition: room-model.hpp:364
Definition: room-model.hpp:209
immer::flex_vector< std::string > unreadNotificationEventIds
Definition: room-model.hpp:275
immer::map< KeyOfState, Event > stateEvents
Definition: room-model.hpp:216
EventList invitedMemberEvents() const
Definition: room-model.cpp:483
EventList knockedMemberEvents() const
Definition: room-model.cpp:488
Event makeRemoveTagEvent(std::string tagId) const
Definition: room-model.cpp:623
bool canPaginateBack
whether this room has earlier events to be fetched
Definition: room-model.hpp:226
immer::map< std::string, std::string > timelineGaps
Definition: room-model.hpp:228
immer::map< std::string, Event > ephemeral
Definition: room-model.hpp:230
bool encrypted
Definition: room-model.hpp:234
immer::map< std::string, double > tags() const
Definition: room-model.cpp:582
immer::flex_vector< std::string > timeline
Definition: room-model.hpp:220
std::string paginateBackToken
Definition: room-model.hpp:224
immer::map< std::string, immer::map< std::string, immer::flex_vector< std::string > >> ReverseEventRelationshipMap
Definition: room-model.hpp:213
Event makeAddTagEvent(std::string tagId, std::optional< double > order) const
Definition: room-model.cpp:611
MegOlmSessionRotateDesc sessionRotateDesc() const
Definition: room-model.cpp:523
EventList heroMemberEvents() const
Definition: room-model.cpp:503
void regenerateRelationships()
Definition: room-model.cpp:642
EventList bannedMemberEvents() const
Definition: room-model.cpp:498
immer::map< std::string, Event > messages
Definition: room-model.hpp:221
void generateRelationships(EventList newEvents)
Fill in reverseEventRelationships by gathering the relationships specified in newEvents
Definition: room-model.cpp:630
std::size_t localNotificationCount
The local unread notification count for this room.
Definition: room-model.hpp:260
std::size_t joinedMemberCount
Definition: room-model.hpp:250
void addToUndecryptedEvents(EventList newEvents)
Fill in undecryptedEvents by gathering the session ids specified in newEvents.
Definition: room-model.cpp:649
std::size_t localUnreadCount
The local unread count for this room.
Definition: room-model.hpp:257
std::string localDraft
Definition: room-model.hpp:232
immer::flex_vector< std::string > knockedMemberIds() const
Definition: room-model.cpp:463
immer::map< std::string, immer::flex_vector< std::string > > eventReadUsers
A map from event id to a list of users that has read receipt at that point.
Definition: room-model.hpp:267
EventList leftMemberEvents() const
Definition: room-model.cpp:493
immer::flex_vector< std::string > heroIds
Definition: room-model.hpp:242
std::optional< PendingRoomKeyEvent > getPendingRoomKeyEventByTxnId(std::string txnId) const
Definition: room-model.cpp:561
std::variant< AddStateEventsAction, MaybeAddStateEventsAction, AddToTimelineAction, AddAccountDataAction, ChangeMembershipAction, ChangeInviteStateAction, AddEphemeralAction, SetLocalDraftAction, SetRoomEncryptionAction, MarkMembersFullyLoadedAction, SetHeroIdsAction, AddLocalEchoAction, RemoveLocalEchoAction, AddPendingRoomKeyAction, RemovePendingRoomKeyAction, UpdateJoinedMemberCountAction, UpdateInvitedMemberCountAction, AddLocalNotificationsAction, RemoveReadLocalNotificationsAction, UpdateLocalReadMarkerAction > Action
Definition: room-model.hpp:344
immer::flex_vector< LocalEchoDesc > localEchoes
Definition: room-model.hpp:244
std::optional< LocalEchoDesc > getLocalEchoByTxnId(std::string txnId) const
Definition: room-model.cpp:549
std::string roomId
Definition: room-model.hpp:215
EventList joinedMemberEvents() const
Definition: room-model.cpp:478
bool membersFullyLoaded
Definition: room-model.hpp:241
std::size_t invitedMemberCount
Definition: room-model.hpp:251
immer::flex_vector< std::string > invitedMemberIds() const
Definition: room-model.cpp:458
ReverseEventRelationshipMap reverseEventRelationships
Definition: room-model.hpp:248
bool hasUser(std::string userId) const
Definition: room-model.cpp:536
immer::map< std::string, immer::flex_vector< std::string > > undecryptedEvents
A map from the session id to a list of event ids of events that cannot (yet) be decrypted.
Definition: room-model.hpp:273
immer::flex_vector< std::string > bannedMemberIds() const
Definition: room-model.cpp:473
immer::flex_vector< PendingRoomKeyEvent > pendingRoomKeyEvents
Definition: room-model.hpp:246
friend bool operator==(const RoomModel &a, const RoomModel &b)=default
immer::map< std::string, Event > accountData
Definition: room-model.hpp:222
void recalculateUndecryptedEvents()
Definition: room-model.cpp:673
immer::map< std::string, ReadReceipt > readReceipts
Read receipts for all users.
Definition: room-model.hpp:262
bool shouldRotateSessionKey
a marker to indicate whether we need to rotate the session key earlier than it expires (e....
Definition: room-model.hpp:239
immer::flex_vector< std::string > joinedMemberIds() const
Definition: room-model.cpp:453
Membership membership
Definition: room-model.hpp:223
std::string localReadMarker
The local read marker for this room.
Definition: room-model.hpp:255
immer::map< KeyOfState, Event > inviteState
Definition: room-model.hpp:217
immer::flex_vector< std::string > leftMemberIds() const
Definition: room-model.cpp:468
static RoomModel update(RoomModel r, Action a)
Definition: room-model.cpp:61
Definition: room-model.hpp:121
immer::flex_vector< std::string > heroIds
Definition: room-model.hpp:122
Definition: room-model.hpp:108
std::string localDraft
Definition: room-model.hpp:109
Definition: room-model.hpp:113
Definition: room-model.hpp:151
std::size_t invitedMemberCount
Definition: room-model.hpp:152
Definition: room-model.hpp:146
std::size_t joinedMemberCount
Definition: room-model.hpp:147
Update the local read marker, removing any read notifications before it.
Definition: room-model.hpp:173
std::string myUserId
Definition: room-model.hpp:175
std::string localReadMarker
Definition: room-model.hpp:174
Definition: room-model.hpp:354
RoomAction roomAction
Definition: room-model.hpp:356
std::string roomId
Definition: room-model.hpp:355