[ADD/WIP] Begin work on storing /sync diffs.
Some checks are pending
Compile Telodendria / Compile Telodendria (x86, alpine-v3.19) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86, debian-v12.4) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86, freebsd-v14.0) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86, netbsd-v9.3) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86_64, alpine-v3.19) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86_64, debian-v12.4) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86_64, freebsd-v14.0) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86_64, netbsd-v9.3) (push) Waiting to run
Compile Telodendria / Compile Telodendria (x86_64, openbsd-v7.4) (push) Waiting to run

This commit is contained in:
lda 2024-06-09 01:43:16 +02:00
parent bb3d15f2c9
commit a491a740d4
3 changed files with 207 additions and 21 deletions

View file

@ -1815,32 +1815,44 @@ RoomAddEventV1(Room *room, PduV1 pdu)
/* TODO: Store DAG relationships, somehow.
* Also keep track of PDU depth. */
if (StrEquals(pdu.type, "m.room.member"))
pdu_json = PduV1ToJson(&pdu);
{
CommonID *id = UserIdParse(pdu.state_key, NULL);
User *user = UserLock(room->db, id->local);
char *membership = JsonValueAsString(
HashMapGet(pdu.content, "membership")
);
CommonID *sid= UserIdParse(pdu.sender, NULL);
User *suser = UserLock(room->db, sid->local);
if (StrEquals(pdu.type, "m.room.member"))
{
CommonID *id = UserIdParse(pdu.state_key, NULL);
User *user = UserLock(room->db, id->local);
char *membership = JsonValueAsString(
HashMapGet(pdu.content, "membership")
);
if (StrEquals(membership, "join") && user)
{
UserAddJoin(user, room->id);
}
else if (StrEquals(membership, "invite") && user)
{
UserAddInvite(user, room->id);
}
else if ((StrEquals(membership, "leave") && user) ||
StrEquals(membership, "ban"))
{
UserRemoveInvite(user, room->id);
UserRemoveJoin(user, room->id);
if (StrEquals(membership, "join") && user)
{
UserAddJoin(user, room->id);
UserPushJoinSync(user, room->id);
}
else if (StrEquals(membership, "invite") && user)
{
UserAddInvite(user, room->id);
UserPushInviteSync(user, room->id);
}
else if ((StrEquals(membership, "leave") && user) ||
StrEquals(membership, "ban"))
{
UserRemoveInvite(user, room->id);
UserRemoveJoin(user, room->id);
}
UserIdFree(id);
UserUnlock(user);
}
UserIdFree(id);
UserUnlock(user);
UserPushEvent(suser, pdu_json);
UserIdFree(sid);
UserUnlock(suser);
}
JsonFree(pdu_json);
return true;
}

View file

@ -22,6 +22,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <Cytoplasm/Db.h>
#include <User.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Memory.h>
@ -1114,3 +1115,149 @@ UserFreeList(Array *arr)
ArrayFree(arr);
}
char *
UserInitSyncDiff(User *user)
{
char *nextBatch;
DbRef *syncRef;
HashMap *data;
if (!user)
{
return NULL;
}
nextBatch = StrRandom(16);
syncRef = DbCreate(user->db, 4, "users", user->name, "sync", nextBatch);
if (!syncRef)
{
Free(nextBatch);
return NULL;
}
data = DbJson(syncRef);
HashMapSet(data, "nextBatch", JsonValueString(nextBatch));
HashMapSet(data, "invites", JsonValueArray(ArrayCreate()));
HashMapSet(data, "leaves", JsonValueArray(ArrayCreate()));
HashMapSet(data, "joins", JsonValueObject(HashMapCreate()));
DbUnlock(user->db, syncRef);
return nextBatch;
}
void
UserPushInviteSync(User *user, char *roomId)
{
DbRef *syncRef;
HashMap *data;
Array *entries;
Array *invites;
size_t i;
if (!user || !roomId)
{
return;
}
entries = DbList(user->db, 3, "users", user->name, "sync");
for (i = 0; i < ArraySize(entries); i++)
{
char *entry = ArrayGet(entries, i);
syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry);
data = DbJson(syncRef);
invites = JsonValueAsArray(HashMapGet(data, "invites"));
ArrayAdd(invites, JsonValueString(roomId));
DbUnlock(user->db, syncRef);
}
DbListFree(entries);
}
void
UserPushJoinSync(User *user, char *roomId)
{
DbRef *syncRef;
HashMap *data;
Array *entries;
HashMap *join;
size_t i;
if (!user || !roomId)
{
return;
}
entries = DbList(user->db, 3, "users", user->name, "sync");
for (i = 0; i < ArraySize(entries); i++)
{
char *entry = ArrayGet(entries, i);
HashMap *joinEntry;
syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry);
data = DbJson(syncRef);
join = JsonValueAsObject(HashMapGet(data, "joins"));
/* TODO */
joinEntry = HashMapCreate();
HashMapSet(joinEntry, "timeline", JsonValueArray(ArrayCreate()));
if (!HashMapGet(join, roomId))
{
JsonFree(HashMapSet(join, roomId, JsonValueObject(joinEntry)));
}
else
{
JsonFree(joinEntry);
}
DbUnlock(user->db, syncRef);
}
DbListFree(entries);
}
void
UserPushEvent(User *user, HashMap *event)
{
DbRef *syncRef;
HashMap *data;
Array *entries;
HashMap *join;
size_t i;
char *roomId, *eventId;
if (!user || !event)
{
return;
}
roomId = JsonValueAsString(HashMapGet(event, "room_id"));
eventId = JsonValueAsString(HashMapGet(event, "event_id"));
UserPushJoinSync(user, roomId);
entries = DbList(user->db, 3, "users", user->name, "sync");
for (i = 0; i < ArraySize(entries); i++)
{
char *entry = ArrayGet(entries, i);
HashMap *joinEntry;
Array *timeline;
syncRef = DbLock(user->db, 4, "users", user->name, "sync", entry);
data = DbJson(syncRef);
join = JsonValueAsObject(HashMapGet(data, "joins"));
joinEntry = JsonValueAsObject(HashMapGet(join, roomId));
timeline = JsonValueAsArray(HashMapGet(joinEntry, "timeline"));
ArrayAdd(timeline, JsonValueString(eventId));
DbUnlock(user->db, syncRef);
}
DbListFree(entries);
}
void
UserDropSync(User *user, char *batch)
{
if (!user || !batch)
{
return;
}
DbDelete(user->db, 4, "users", user->name, "sync", batch);
}

View file

@ -314,6 +314,7 @@ extern HashMap * UserGetTransaction(User *, char *, char *);
*/
extern void UserSetTransaction(User *, char *, char *, HashMap *);
/**
* Puts a room (indexed by room ID) in a user's invite list.
*/
@ -361,4 +362,30 @@ extern void UserFreeList(Array *);
*/
extern void UserIdFree(CommonID *);
/**
* Initialises a sync diff table, and returns a next_batch parameter,
* which is stored on the heap.
*/
extern char * UserInitSyncDiff(User *);
/**
* Pushes an invite onto all sync diff tables.
*/
extern void UserPushInviteSync(User *, char *);
/**
* Pushes a join onto all sync diff tables.
*/
extern void UserPushJoinSync(User *, char *);
/**
* Pushes an event (ID) into every diff table of a user.
*/
extern void UserPushEvent(User *, HashMap *);
/**
* Drops a sync diff, denoted by it's previous batch ID, if it
* exists.
*/
extern void UserDropSync(User *, char *);
#endif /* TELODENDRIA_USER_H */