From 97b1e4d723cbdd7fd9902894bed064b4e3a24bf3 Mon Sep 17 00:00:00 2001 From: LDA Date: Sun, 9 Jun 2024 11:46:44 +0200 Subject: [PATCH] [ADD/WIP] Push events into sync The code is still ugly(still waiting for j2s to support some things before I can actually get *somewhere* with the schemas, which is my main complaint), and it's definitely not spec-compliant, but it now means you can actually see diffs in rooms you joined from the timeline! --- src/Room.c | 26 +++++++++++++++++++++----- src/Routes/RouteSync.c | 24 +++++++++++++++++++----- src/User.c | 35 +++++++++++++++++++++++++++++++++++ src/include/User.h | 7 +++++++ 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/Room.c b/src/Room.c index 87d9056..2752c8a 100644 --- a/src/Room.c +++ b/src/Room.c @@ -1815,8 +1815,9 @@ RoomAddEventV1(Room *room, PduV1 pdu) /* TODO: Store DAG relationships, somehow. */ pdu_json = PduV1ToJson(&pdu); { - CommonID *sid= UserIdParse(pdu.sender, NULL); - User *suser = UserLock(room->db, sid->local); + HashMap *state = StateCurrent(room); + char *type, *state_key, *event_id; + if (StrEquals(pdu.type, "m.room.member")) { CommonID *id = UserIdParse(pdu.state_key, NULL); @@ -1846,9 +1847,24 @@ RoomAddEventV1(Room *room, PduV1 pdu) UserUnlock(user); } - UserPushEvent(suser, pdu_json); - UserIdFree(sid); - UserUnlock(suser); + while (StateIterate(state, &type, &state_key, (void **) &event_id)) + { + if (StrEquals(type, "m.room.member")) + { + /* Notify state_key about it. + * Does nothing if the user is not already in the room. */ + CommonID *id = UserIdParse(state_key, NULL); + User *user = UserLock(room->db, id->local); + + UserPushEvent(user, pdu_json); + + UserIdFree(id); + UserUnlock(user); + } + Free(type); + Free(state_key); + } + StateFree(state); } JsonFree(pdu_json); diff --git a/src/Routes/RouteSync.c b/src/Routes/RouteSync.c index 24791d0..2bf075a 100644 --- a/src/Routes/RouteSync.c +++ b/src/Routes/RouteSync.c @@ -121,14 +121,28 @@ ROUTE_IMPL(RouteSync, path, argp) { char *roomId = ArrayGet(joins, i); HashMap *room = HashMapCreate(); + Array *el = UserGetEvents(user, currBatch, roomId); + size_t j; + Room *r = RoomLock(db, roomId); + Array *timeline = ArrayCreate(); /* TODO: Add history. */ + for (j = 0; j < ArraySize(el); j++) + { + char *event = ArrayGet(el, j); + HashMap *e = RoomEventFetch(r, event); + HashMap *c = RoomEventClientify(e); - JsonSet( - rooms, - JsonValueObject(room), - 2, "join", roomId - ); + JsonFree(e); + JsonValueFree(HashMapDelete(c, "room_id")); + + ArrayAdd(timeline, JsonValueObject(c)); + } + RoomUnlock(r); + UserFreeList(el); + + JsonSet(room, JsonValueArray(timeline), 1, "timeline"); + JsonSet(rooms, JsonValueObject(room), 2, "join", roomId); } UserFreeList(joins); } diff --git a/src/User.c b/src/User.c index 8a37c6c..663b2ea 100644 --- a/src/User.c +++ b/src/User.c @@ -1360,3 +1360,38 @@ UserGetJoins(User *user, char *batch) DbUnlock(user->db, syncRef); return keys; } +Array * +UserGetEvents(User *user, char *batch, char *roomId) +{ + DbRef *syncRef; + HashMap *data; + HashMap *joins; + Array *keys, *ret; + size_t i; + if (!user || !batch || !roomId) + { + return NULL; + } + + syncRef = DbLock(user->db, 4, "users", user->name, "sync", batch); + if (!syncRef) + { + return NULL; + } + + data = DbJson(syncRef); + + joins = JsonValueAsObject(JsonGet(data, 2, "joins", roomId)); + + keys = (JsonValueAsArray(HashMapGet(joins, "timeline"))); + ret = ArrayCreate(); + for (i = 0; i < ArraySize(keys); i++) + { + char *str = JsonValueAsString(ArrayGet(keys, i)); + + ArrayAdd(ret, StrDuplicate(str)); + } + + DbUnlock(user->db, syncRef); + return ret; +} diff --git a/src/include/User.h b/src/include/User.h index e835205..d080d11 100644 --- a/src/include/User.h +++ b/src/include/User.h @@ -403,6 +403,13 @@ extern Array * UserGetInvites(User *, char *); */ extern Array * UserGetJoins(User *, char *); +/** + * Get a list of event IDs for a diff table(and room ID), + * to be freed by + * .Fn UserFreeList . + */ +extern Array * UserGetEvents(User *, char *, char *); + /** * Drops a sync diff, denoted by it's previous batch ID, if it * exists.