Line data Source code
1 : import 'dart:convert';
2 :
3 : import 'package:http/http.dart' as http;
4 :
5 : import 'package:matrix/matrix.dart';
6 :
7 : enum DelayedEventAction { send, cancel, restart }
8 :
9 : extension DelayedEventsHandler on Client {
10 : static const _delayedEventsEndpoint =
11 : '_matrix/client/unstable/org.matrix.msc4140/delayed_events';
12 :
13 : /// State events can be sent using this endpoint. These events will be
14 : /// overwritten if `<room id>`, `<event type>` and `<state key>` all
15 : /// match.
16 : ///
17 : /// Requests to this endpoint **cannot use transaction IDs**
18 : /// like other `PUT` paths because they cannot be differentiated from the
19 : /// `state_key`. Furthermore, `POST` is unsupported on state paths.
20 : ///
21 : /// The body of the request should be the content object of the event; the
22 : /// fields in this object will vary depending on the type of event. See
23 : /// [Room Events](https://spec.matrix.org/unstable/client-server-api/#room-events) for the `m.` event specification.
24 : ///
25 : /// If the event type being sent is `m.room.canonical_alias` servers
26 : /// SHOULD ensure that any new aliases being listed in the event are valid
27 : /// per their grammar/syntax and that they point to the room ID where the
28 : /// state event is to be sent. Servers do not validate aliases which are
29 : /// being removed or are already present in the state event.
30 : ///
31 : ///
32 : /// [roomId] The room to set the state in
33 : ///
34 : /// [eventType] The type of event to send.
35 : ///
36 : /// [stateKey] The state_key for the state to send. Defaults to the empty string. When
37 : /// an empty string, the trailing slash on this endpoint is optional.
38 : ///
39 : /// [delayInMs] Optional number of milliseconds the homeserver should wait before sending the event.
40 : /// If no delay is provided, the event is sent immediately as normal.
41 : ///
42 : /// [body]
43 : ///
44 : /// returns `event_id`:
45 : /// A unique identifier for the event.
46 : /// If a delay is provided, the homeserver schedules the event to be sent with the specified delay
47 : /// and responds with an opaque delay_id field (omitting the event_id as it is not available)
48 0 : Future<String> setRoomStateWithKeyWithDelay(
49 : String roomId,
50 : String eventType,
51 : String stateKey,
52 : int? delayInMs,
53 : Map<String, Object?> body,
54 : ) async {
55 0 : final requestUri = Uri(
56 : path:
57 0 : '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}',
58 0 : queryParameters: {
59 0 : if (delayInMs != null) 'org.matrix.msc4140.delay': delayInMs.toString(),
60 : },
61 : );
62 :
63 0 : final request = http.Request('PUT', baseUri!.resolveUri(requestUri));
64 0 : request.headers['authorization'] = 'Bearer ${bearerToken!}';
65 0 : request.headers['content-type'] = 'application/json';
66 0 : request.bodyBytes = utf8.encode(jsonEncode(body));
67 0 : final response = await httpClient.send(request);
68 0 : final responseBody = await response.stream.toBytes();
69 0 : if (response.statusCode != 200) unexpectedResponse(response, responseBody);
70 0 : final responseString = utf8.decode(responseBody);
71 0 : final json = jsonDecode(responseString);
72 0 : return json['event_id'] ?? json['delay_id'] as String;
73 : }
74 :
75 0 : Future<void> manageDelayedEvent(
76 : String delayedId,
77 : DelayedEventAction delayedEventAction,
78 : ) async {
79 0 : final requestUri = Uri(
80 0 : path: '$_delayedEventsEndpoint/$delayedId',
81 : );
82 :
83 0 : final request = http.Request('POST', baseUri!.resolveUri(requestUri));
84 0 : request.headers['authorization'] = 'Bearer ${bearerToken!}';
85 0 : request.headers['content-type'] = 'application/json';
86 0 : request.bodyBytes = utf8.encode(
87 0 : jsonEncode({
88 0 : 'action': delayedEventAction.name,
89 : }),
90 : );
91 0 : final response = await httpClient.send(request);
92 0 : final responseBody = await response.stream.toBytes();
93 0 : if (response.statusCode != 200) unexpectedResponse(response, responseBody);
94 : }
95 :
96 : // This should use the /delayed_events/scheduled endpoint
97 : // but synapse implementation uses the /delayed_events
98 0 : Future<ScheduledDelayedEventsResponse> getScheduledDelayedEvents({
99 : String? from,
100 : }) async {
101 0 : final requestUri = Uri(
102 : path: _delayedEventsEndpoint,
103 0 : queryParameters: {if (from != null) 'from': from},
104 : );
105 :
106 0 : final request = http.Request('GET', baseUri!.resolveUri(requestUri));
107 0 : request.headers['authorization'] = 'Bearer ${bearerToken!}';
108 0 : request.headers['content-type'] = 'application/json';
109 0 : final response = await httpClient.send(request);
110 0 : final responseBody = await response.stream.toBytes();
111 0 : if (response.statusCode != 200) {
112 0 : return await _getScheduledDelayedEventsAccordingToSpec(from: from);
113 : }
114 0 : final responseString = utf8.decode(responseBody);
115 0 : final json = jsonDecode(responseString);
116 0 : final res = ScheduledDelayedEventsResponse.fromJson(json);
117 : return res;
118 : }
119 :
120 : // maybe the synapse impl changes, I don't want stuff to break
121 0 : Future<ScheduledDelayedEventsResponse>
122 : _getScheduledDelayedEventsAccordingToSpec({
123 : String? from,
124 : }) async {
125 0 : final requestUri = Uri(
126 : path: '$_delayedEventsEndpoint/scheduled',
127 0 : queryParameters: {if (from != null) 'from': from},
128 : );
129 :
130 0 : final request = http.Request('GET', baseUri!.resolveUri(requestUri));
131 0 : request.headers['authorization'] = 'Bearer ${bearerToken!}';
132 0 : request.headers['content-type'] = 'application/json';
133 0 : final response = await httpClient.send(request);
134 0 : final responseBody = await response.stream.toBytes();
135 0 : if (response.statusCode != 200) unexpectedResponse(response, responseBody);
136 0 : final responseString = utf8.decode(responseBody);
137 0 : final json = jsonDecode(responseString);
138 0 : final res = ScheduledDelayedEventsResponse.fromJson(json);
139 : return res;
140 : }
141 :
142 : /// TODO: implement the remaining APIs
143 : /// GET /_matrix/client/unstable/org.matrix.msc4140/delayed_events/finalised
144 : }
|