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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
=begin pod
=TITLE class Matrix::Client
=SUBTITLE matrix.org client
=head1 NAME
Matrix::Client — Client API for Matrix.org
=head1 SYNOPSIS
use Matrix::Client;
my Matrix::Client $client .= new(
:home-server<https://matrix.org>,
:access-token<access-token>
);
my $room = $client.joined-rooms.first;
$room.send("Hello from Matrix::Client");
my $sync = $client.sync;
for $response.joined-rooms -> $room {
say "Messages from {$room.name}"
for $room.timeline
.events
.grep(*.type eq 'm.room.message') -> $msg {
say $msg.content<body>;
}
}
=head1 DESCRIPTION
Class Matrix::Client does Matrix::Client::Requester {}
The main object in the module. The C<Matrix::Client> is used to talk to a
Matrix home server abstracting the HTTP requests.
The client is used for example to join rooms, receive/send messages, etc.
On server errors, all methods will throw a L<X::Matrix::Response|x-matrix-response.html> exception.
=head1 METHODS
=head2 new
sub new(Str :$home-server, Str :$access-token?, Str :$device-id?)
Creates a C<Matrix::Client> pointing to a home server. If no C<$access-token> is
passed to the constructor, the client needs to call L<#login> to make authorized
calls to the API.
=head2 login
multi method login(Str $username, Str $password)
multi method login(Str :$username, Str :$password)
Logs in with the C<$username> and C<password>. If C<device-id> is setted
before the C<login> call, it will register that C<device-id> in the server
invalidating any previously associated access token to this C<device-id>.
Otherwise the home server will auto-generate one.
On a failed login attempt, a L<X::Matrix::Response|x-matrix-response.html> is raised with a code
of C<“M_FORBIDDEN”>
=head2 logout
method logout()
Invalidates the access token, so that it can no longer be used for authorization.
=head2 register
method register($username, $password, Bool :$bind-email? = False)
Register a B<user> account in the home server.
If C<$bind-email> is true, the server binds the email used for authentication
to the Matrix ID with the ID Server.
In case there's an error with the registration, a L<X::Matrix::Response|x-matrix-response.html> is raised
with one of the following C<code>s:
=item C<M_USER_IN_USE> The desired user ID is already taken.
=item C<M_INVALID_USERNAME>: The desired user ID is not a valid user name.
=item C<M_EXCLUSIVE>: The desired user ID is in the exclusive namespace claimed by an application service.
=head2 profile
method profile(Str :$user-id?)
Get the combined profile information for this user. With no C<$user-id>
L<#profile> will provide the profile data associated with the client
account.
It returns a C<Hash> that can contains C<avatar_url> and/or C<displayname>.
=head2 display-name
method display-name(Str :$user-id?)
Get the display-name of the C<$user-id>. With no C<$user-id> it will return
the display name associated with the client account.
=head2 change-display-name
method change-display-name(Str:D $display-name!)
Change the client account display name.
=head2 avatar-url
method avatar-url(Str :$user-id?)
Get the avatar url for a given C<$user-id>. With no C<$user-id> it will return
the avatar url associated with the client account.
=head2 change-avatar
multi method change-avatar(IO::Path $avatar)
multi method change-avatar(Str:D $mxc-url!)
Changes the avatar for the client account.
Passing a C<IO::Path> to the method will upload the image to the server
and then set that uploaded image as avatar.
=head2 whoami
method whoami
Returns the user id of the client account.
=head2 presence
method presence(Matrix::Client:D: $user-id? --> Matrix::Response::Presence)
Query the presence status for an user. if no C<$user-id> is passed as argument,
it will return the presence of the user associated with the client.
=head2 set-presence
method set-presence(Matrix::Client:D: Str $presence, Str :$status-message = "")
Sets the manually the presence of the client account. The C<$presence> argument
must be C<“online”>, C<“offline”> or C<“unavailable”>.
=head2 sync
multi method sync(:$since = "")
multi method sync(Str :$sync-filter, Str :$since = "")
multi method sync(Hash :$sync-filter is copy, :$since = "")
Gets the client's state with the latest state on the server. It returns
a L<Matrix::Response::Sync|responses.html#Sync> with the initial snapshot or delta.
C<$since> is necessary to get the incremental deltas to the states. The C<$since>
value is retrieved from the C<next-batch> in the L<Matrix::Response::Sync|responses.html#sync>.
The C<sync-filter> is the filter that will be applied to the sync. It will encode
it to a JSON string if it isn't a C<Str> already. For more information about
filters you can check the L<official spec|https://matrix.org/docs/spec/client_server/r0.3.0.html#filtering>
# Filter to apply to the sync.
my $sync-filter = { room => timeline => limit => 1 };
my $sync = $client.sync(:$sync-filter);
# Get the next batch to get a delta on the sync.
my $since = $sync.next-batch;
# This will return the same $sync as above.
my $same-sync = $client.sync(:$sync-filter);
# This won't
my $new-sync = $client.sync(:$sync-filter, :$since);
=head2 create-room
method create-room(
Bool :$public = False,
*%args --> Matrix::Client::Room
)
Create a room in the home server. Possible arguments for C<*%args> are:
=item visibility: C<“public”> or C<“private”>.
=item room_alias_name: A C<Str> for a room alias.
=item name: A C<Str> for the room name.
=item topic: A C<Str> for the room topic.
=item invite: A list of C<Str> of user ids to invite to the room.
=item preset: C<“private_chat”>, C<“trusted_private_chat”> or C<“public_chat”>.
=item is_direct: A C<Bool> to make the room as a direct chat.
The parameters can be typed with C<-> instead C<_> for style purposes, the method
will change those characters to match the Matrix API. The list can be found
L<here|https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-createroom>
The C<$public> argument sets the C<visibility> to “public”, giving precedence to the C<visibility>
in C<%*args>.
=head2 join-room
method join-room($room-id!)
Joins a room.
The C<$room-id> can be either a room id (!superhash:server) or an alias (#alias:server)
since it uses the L</join/{roomIdOrAlias}|https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-join-roomidoralias>
endpoint.
=head2 leave-room
method leave-room($room-id)
Leaves a room.
The C<$room-id> must be a room id (!superhash:server).
=head2 joined-rooms
method joined-rooms(--> Seq)
Returns a C<Seq> with the joined rooms within the client.
=head2 public-rooms
method public-rooms()
Lists the public rooms on the server.
B<Note>: Right now this is returning the parsed JSON from the response.
=head2 send
method send(Str $room-id, Str $body, :$type? = "m.text")
Send a message event to a room.
C<$room-id> must be a room id with the form “!hast:server”. As for now the C<send> method
only sends C<“m.text”> events. In the future it will be extended to support all the
L<Room events|https://matrix.org/docs/spec/client_server/r0.3.0.html#room-events>.
=head2 get-room-id
method get-room-id($room-alias)
Get the room id for an C<$room-alias>. The room alias must be in the form
C<localname:domain>, otherwise it will raise a L<X::Matrix::Response|x-matrix-response.html> with
the proper message and C<M_UNKNOWN> error code.
If there's no room with the C<$room-alias> in the server directory, it will
raise a L<X::Matrix::Response|x-matrix-response.html> with a C<M_NOT_FOUND> code.
=head2 add-room-alias
method add-room-alias($room-id, $room-alias)
Add the C<$room-alias> to the C<$room-id>.
=head2 remove-room-alias
method remove-room-alias($room-alias)
Remove a mapping of C<$room-alias> to room ID. The room ID isn't a must and
the servers may choose to implement additional access control for this endpoint.
=head2 upload
method upload(IO::Path $path, Str $filename?)
Uploads a file to the server. It returns the MXC URI to the uploaded content.
=head2 run
method run(Int :$sleep = 10, :$sync-filter? --> Supply)
Returns a C<Supply> that emits L<Matrix::Response::StateEvent> with the last
events. The C<$sleep> parameter is to sleep for that amount of seconds before
making a L<#sync> request again. The C<$sync-filter> is the same parameter that
will be passed to L<#sync> method to filter out the useful events.
This can be useful to turn something like:
my $since;
loop {
$response = $client.sync(:$since);
$since = $response.next-batch;
for $response.joined-rooms -> $room {
for $room.timeline.event -> $event {
# Do something useful with $event
}
}
}
into:
my $sup = $client.run();
react whenever $sup -> $event {
# Do something useful with $event
}
=end pod
|