1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
<?php
namespace App\Controllers;
use App\Database;
use App\Models\RoomEvent;
use App\Models\User;
use Matrix\Data\AccountData;
use Matrix\Data\DeviceLists;
use Matrix\Data\Presence;
use Matrix\Data\Room\Ephemeral;
use Matrix\Data\Room\JoinedRoom;
use Matrix\Data\Room\RoomSummary;
use Matrix\Data\Room\Rooms;
use Matrix\Data\Room\State;
use Matrix\Data\Room\Timeline;
use Matrix\Data\Room\UnreadNotificationCounts;
use Matrix\Data\ToDevice;
use Matrix\Enums\MembershipState;
use Matrix\Enums\PresenceState;
use Matrix\Events\PresenceEvent;
use Matrix\Responses\ClientSyncGetResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
class SyncController
{
/**
* GET /_matrix/client/v3/sync
*
* @see https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv3sync
* @see https://spec.matrix.org/v1.15/client-server-api/#extensions-to-sync
*/
public function sync(Request $request): Response
{
$user = User::authenticateWithRequest($request);
$filter = $request->query->get("filter", "");
$syncFullState = $request->query->get("full_state", false);
$setPresence = PresenceState::tryFrom($request->query->get("set_presence") ?? "") ?? PresenceState::ONLINE;
$since = $request->query->get("since", "");
$timeout = $request->query->get("timeout", 0);
$useStateAfter = $request->query->get("use_state_after", false);
if (! empty($filter)) {
if (str_starts_with($filter, "{")) {
$filter = json_decode($filter, true);
} else {
$filter = Database::getInstance()->query("select * from filters where id=:id", ["id" => $filter])->fetch();
}
}
$rooms = Database::getInstance()->query(<<<SQL
select * from rooms
left join room_memberships
on rooms.id = room_memberships.room_id
where room_memberships.user_id = :user_id
SQL, [
"user_id" => $user->getId(),
])->fetchAll();
$invitedRooms = [];
$joinedRooms = [];
$knockedRooms = [];
$leftRooms = [];
foreach ($rooms as $room) {
$events = Database::getInstance()->query(<<<SQL
select * from room_events
where room_id = :room_id
SQL, [
"room_id" => $room["room_id"],
#"limit" => ($filter["room"]["timeline"]["limit"] ?? false) ? "limit " . $filter["room"]["timeline"]["limit"] : "",
])->fetchAll();
if ($since === "" && MembershipState::tryFrom($room["state"]) === MembershipState::JOIN) {
$joinedRooms[$room["room_id"]] = new JoinedRoom(
accountData: new AccountData([]),
ephemeral: new Ephemeral([]),
state: new State([]),
summary: new RoomSummary(
heroes: [],
invitedMemberCount: 0,
joinedMemberCount: 1,
),
timeline: new Timeline(
events: array_map([RoomEvent::class, "transformEvent"], $events),
limited: false,# $filter["room"]["timeline"]["limit"] ?? false,
previousBatch: null,
),
unreadNotifications: new UnreadNotificationCounts(0, 0),
unreadThreadNotifications: [],
);
}
}
return new JsonResponse(new ClientSyncGetResponse(
nextBatch: "1",
accountData: new AccountData([]),
deviceLists: new DeviceLists([], []),
deviceOneTimeKeysCount: [
"signed_curve25519" => 10,
],
presence: new Presence([
new PresenceEvent(
sender: $user->getId(),
presence: $setPresence,
),
]),
rooms: new Rooms(
$invitedRooms,
$joinedRooms,
$knockedRooms,
$leftRooms,
),
toDevice: new ToDevice([]),
));
}
}
|