summaryrefslogtreecommitdiff
path: root/src/Controllers/SyncController.php
blob: acebb11e8084266e16cf4b0e412f251dea34a1d5 (plain)
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([]),
    ));
  }
}