dokuwiki-matrixnotifierwas-plugin – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 <?php
2  
3 namespace MatrixPhp;
4  
5 use MatrixPhp\Exceptions\MatrixRequestException;
6 use function GuzzleHttp\default_ca_bundle;
7 use http\Exception;
8 use phpDocumentor\Reflection\DocBlock\Tags\Param;
9  
10 /**
11 * Call room-specific functions after joining a room from the client.
12 *
13 * NOTE: This should ideally be called from within the Client.
14 * NOTE: This does not verify the room with the Home Server.
15 *
16 * @package MatrixPhp
17 */
18 class Room {
19  
20 /** @var MatrixClient */
21 protected $client;
22 protected $roomId;
23 protected $listeners = [];
24 protected $stateListeners = [];
25 protected $ephemeralListeners = [];
26 protected $events = [];
27 protected $eventHistoryLimit = 20;
28 protected $name;
29 protected $canonicalAlias;
30 protected $aliases = [];
31 protected $topic;
32 protected $inviteOnly = false;
33 protected $guestAccess;
34 public $prevBatch;
35 protected $_members = [];
36 protected $membersDisplaynames = [
37 // $userId: $displayname,
38 ];
39 protected $encrypted = false;
40  
41 public function __construct(MatrixClient $client, string $roomId) {
42 Util::checkRoomId($roomId);
43 $this->roomId = $roomId;
44 $this->client = $client;
45 }
46  
47 /**
48 * Set user profile within a room.
49 *
50 * This sets displayname and avatar_url for the logged in user only in a
51 * specific room. It does not change the user's global user profile.
52 *
53 * @param string|null $displayname
54 * @param string|null $avatarUrl
55 * @param string $reason
56 * @throws Exceptions\MatrixException
57 * @throws Exceptions\MatrixHttpLibException
58 * @throws Exceptions\MatrixRequestException
59 */
60 public function setUserProfile(?string $displayname = null, ?string $avatarUrl = null,
61 string $reason = "Changing room profile information") {
62 $member = $this->api()->getMembership($this->roomId, $this->client->userId());
63 if ($member['membership'] != 'join') {
64 throw new \Exception("Can't set profile if you have not joined the room.");
65 }
66 if (!$displayname) {
67 $displayname = $member["displayname"];
68 }
69 if (!$avatarUrl) {
70 $avatarUrl = $member["avatar_url"];
71 }
72 $this->api()->setMembership(
73 $this->roomId,
74 $this->client->userId(),
75 'join',
76 $reason,
77 [
78 "displayname" => $displayname,
79 "avatar_url" => $avatarUrl
80 ]
81 );
82 }
83  
84 /**
85 * Calculates the display name for a room.
86 *
87 * @return string
88 */
89 public function displayName() {
90 if ($this->name) {
91 return $this->name;
92 } elseif ($this->canonicalAlias) {
93 return $this->canonicalAlias;
94 }
95  
96 // Member display names without me
97 $members = array_reduce($this->getJoinedMembers(), function (array $all, User $u) {
98 if ($this->client->userId() != $u->userId()) {
99 $all[] = $u->getDisplayName($this);
100 }
101 return $all;
102 }, []);
103 sort($members);
104  
105 switch (count($members)) {
106 case 0:
107 return 'Empty room';
108 case 1:
109 return $members[0];
110 case 2:
111 return sprintf("%s and %s", $members[0], $members[1]);
112 default:
113 return sprintf("%s and %d others.", $members[0], count($members));
114 }
115 }
116  
117 /**
118 * Send a plain text message to the room.
119 *
120 * @param string $text
121 * @return array|string
122 * @throws Exceptions\MatrixException
123 * @throws Exceptions\MatrixHttpLibException
124 * @throws Exceptions\MatrixRequestException
125 */
126 public function sendText(string $text) {
127 return $this->api()->sendMessage($this->roomId, $text);
128 }
129  
130 public function getHtmlContent(string $html, ?string $body = null, string $msgType = 'm.text') {
131 return [
132 'body' => $body ?: strip_tags($html),
133 'msgtype' => $msgType,
134 'format' => "org.matrix.custom.html",
135 'formatted_body' => $html,
136 ];
137 }
138  
139 /**
140 * Send an html formatted message.
141 *
142 * @param string $html The html formatted message to be sent.
143 * @param string|null $body The unformatted body of the message to be sent.
144 * @param string $msgType
145 * @return array|string
146 * @throws Exceptions\MatrixException
147 * @throws Exceptions\MatrixHttpLibException
148 * @throws Exceptions\MatrixRequestException
149 */
150 public function sendHtml(string $html, ?string $body = null, string $msgType = 'm.text') {
151 $content = $this->getHtmlContent($html, $body, $msgType);
152  
153 return $this->api()->sendMessageEvent($this->roomId, 'm.room.message', $content);
154 }
155  
156 /**
157 * @param string $type
158 * @param array $data
159 * @return array|string
160 * @throws Exceptions\MatrixException
161 * @throws Exceptions\MatrixHttpLibException
162 * @throws Exceptions\MatrixRequestException
163 */
164 public function setAccountData(string $type, array $data) {
165 return $this->api()->setRoomAccountData($this->client->userId(), $this->roomId, $type, $data);
166 }
167  
168 /**
169 * @return array|string
170 * @throws Exceptions\MatrixException
171 * @throws Exceptions\MatrixHttpLibException
172 * @throws Exceptions\MatrixRequestException
173 */
174 public function getTags() {
175 return $this->api()->getUserTags($this->client->userId(), $this->roomId);
176 }
177  
178 /**
179 * @param string $tag
180 * @return array|string
181 * @throws Exceptions\MatrixException
182 * @throws Exceptions\MatrixHttpLibException
183 * @throws Exceptions\MatrixRequestException
184 */
185 public function removeTag(string $tag) {
186 return $this->api()->removeUserTag($this->client->userId(), $this->roomId, $tag);
187 }
188  
189 /**
190 * @param string $tag
191 * @param float|null $order
192 * @param array $content
193 * @return array|string
194 * @throws Exceptions\MatrixException
195 * @throws Exceptions\MatrixHttpLibException
196 * @throws Exceptions\MatrixRequestException
197 */
198 public function addTag(string $tag, ?float $order = null, array $content = []) {
199 return $this->api()->addUserTag($this->client->userId(), $this->roomId, $tag, $order, $content);
200 }
201  
202 /**
203 * Send an emote (/me style) message to the room.
204 *
205 * @param string $text
206 * @return array|string
207 * @throws Exceptions\MatrixException
208 * @throws Exceptions\MatrixHttpLibException
209 * @throws Exceptions\MatrixRequestException
210 */
211 public function sendEmote(string $text) {
212 return $this->api()->sendEmote($this->roomId, $text);
213 }
214  
215 /**
216 * Send a pre-uploaded file to the room.
217 *
218 * See http://matrix.org/docs/spec/r0.4.0/client_server.html#m-file for fileinfo.
219 *
220 * @param string $url The mxc url of the file.
221 * @param string $name The filename of the image.
222 * @param array $fileinfo Extra information about the file
223 * @return array|string
224 * @throws Exceptions\MatrixException
225 * @throws Exceptions\MatrixHttpLibException
226 * @throws Exceptions\MatrixRequestException
227 */
228 public function sendFile(string $url, string $name, array $fileinfo) {
229 return $this->api()->sendContent($this->roomId, $url, $name, 'm.file', $fileinfo);
230 }
231  
232 /**
233 * Send a notice (from bot) message to the room.
234 *
235 * @param string $text
236 * @return array|string
237 * @throws Exceptions\MatrixException
238 * @throws Exceptions\MatrixHttpLibException
239 * @throws Exceptions\MatrixRequestException
240 */
241 public function sendNotice(string $text) {
242 return $this->api()->sendNotice($this->roomId, $text);
243 }
244  
245 /**
246 * Send a pre-uploaded image to the room.
247 *
248 * See http://matrix.org/docs/spec/r0.0.1/client_server.html#m-image for imageinfo
249 *
250 * @param string $url The mxc url of the image.
251 * @param string $name The filename of the image.
252 * @param array $fileinfo Extra information about the image.
253 * @return array|string
254 * @throws Exceptions\MatrixException
255 * @throws Exceptions\MatrixHttpLibException
256 * @throws Exceptions\MatrixRequestException
257 */
258 public function sendImage(string $url, string $name, ?array $fileinfo) {
259 return $this->api()->sendContent($this->roomId, $url, $name, 'm.image', $fileinfo);
260 }
261  
262 /**
263 * Send a location to the room.
264 * See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-location for thumb_info
265 *
266 * @param string $geoUri The geo uri representing the location.
267 * @param string $name Description for the location.
268 * @param array $thumbInfo Metadata about the thumbnail, type ImageInfo.
269 * @param string|null $thumbUrl URL to the thumbnail of the location.
270 * @return array|string
271 * @throws Exceptions\MatrixException
272 * @throws Exceptions\MatrixHttpLibException
273 * @throws Exceptions\MatrixRequestException
274 */
275 public function sendLocation(string $geoUri, string $name, ?array $thumbInfo, ?string $thumbUrl = null) {
276 return $this->api()->sendLocation($this->roomId, $geoUri, $name, $thumbUrl, $thumbInfo);
277 }
278  
279 /**
280 * Send a pre-uploaded video to the room.
281 * See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video for videoinfo
282 *
283 * @param string $url The mxc url of the video.
284 * @param string $name The filename of the video.
285 * @param array $videoinfo Extra information about the video.
286 * @return array|string
287 * @throws Exceptions\MatrixException
288 * @throws Exceptions\MatrixHttpLibException
289 * @throws Exceptions\MatrixRequestException
290 */
291 public function sendVideo(string $url, string $name, ?array $videoinfo) {
292 return $this->api()->sendContent($this->roomId, $url, $name, 'm.video', $videoinfo);
293 }
294  
295 /**
296 * Send a pre-uploaded audio to the room.
297 * See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-audio for audioinfo
298 *
299 * @param string $url The mxc url of the video.
300 * @param string $name The filename of the video.
301 * @param array $audioinfo Extra information about the video.
302 * @return array|string
303 * @throws Exceptions\MatrixException
304 * @throws Exceptions\MatrixHttpLibException
305 * @throws Exceptions\MatrixRequestException
306 */
307 public function sendAudio(string $url, string $name, ?array $audioinfo) {
308 return $this->api()->sendContent($this->roomId, $url, $name, 'm.audio', $audioinfo);
309 }
310  
311 /**
312 * Redacts the message with specified event_id for the given reason.
313 *
314 * See https://matrix.org/docs/spec/r0.0.1/client_server.html#id112
315 *
316 * @param string $eventId
317 * @param string|null $reason
318 * @return array|string
319 * @throws Exceptions\MatrixException
320 * @throws Exceptions\MatrixHttpLibException
321 * @throws Exceptions\MatrixRequestException
322 */
323 public function redactMessage(string $eventId, ?string $reason = null) {
324 return $this->api()->redactEvent($this->roomId, $eventId, $reason);
325 }
326  
327 /**
328 * Add a callback handler for events going to this room.
329 *
330 * @param callable $cb (func(room, event)): Callback called when an event arrives.
331 * @param string|null $eventType The event_type to filter for.
332 * @return string Unique id of the listener, can be used to identify the listener.
333 */
334 public function addListener(callable $cb, ?string $eventType = null) {
335 $listenerId = uniqid();
336 $this->listeners[] = [
337 'uid' => $listenerId,
338 'callback' => $cb,
339 'event_type' => $eventType,
340 ];
341  
342 return $listenerId;
343 }
344  
345 /**
346 * Remove listener with given uid.
347 *
348 * @param string $uid
349 */
350 public function removeListener(string $uid) {
351 $this->listeners = array_filter($this->listeners, function ($l) use ($uid) {
352 return $l['uid'] != $uid;
353 });
354 }
355  
356 /**
357 * Add a callback handler for ephemeral events going to this room.
358 *
359 * @param callable $cb (func(room, event)): Callback called when an ephemeral event arrives.
360 * @param string|null $eventType The event_type to filter for.
361 * @return string Unique id of the listener, can be used to identify the listener.
362 */
363 public function addEphemeralListener(callable $cb, ?string $eventType = null) {
364 $listenerId = uniqid();
365 $this->ephemeralListeners[] = [
366 'uid' => $listenerId,
367 'callback' => $cb,
368 'event_type' => $eventType,
369 ];
370  
371 return $listenerId;
372 }
373  
374 /**
375 * Remove ephemeral listener with given uid.
376 *
377 * @param string $uid
378 */
379 public function removeEphemeralListener(string $uid) {
380 $this->ephemeralListeners = array_filter($this->ephemeralListeners, function ($l) use ($uid) {
381 return $l['uid'] != $uid;
382 });
383 }
384  
385 /**
386 * Add a callback handler for state events going to this room.
387 *
388 * @param callable $cb Callback called when an event arrives.
389 * @param string|null $eventType The event_type to filter for.
390 */
391 public function addStateListener(callable $cb, ?string $eventType = null) {
392 $this->stateListeners[] = [
393 'callback' => $cb,
394 'event_type' => $eventType,
395 ];
396 }
397  
398 public function putEvent(array $event) {
399 $this->events[] = $event;
400 if (count($this->events) > $this->eventHistoryLimit) {
401 array_pop($this->events);
402 }
403 if (array_key_exists('state_event', $event)) {
404 $this->processStateEvent($event);
405 }
406 // Dispatch for room-specific listeners
407 foreach ($this->listeners as $l) {
408 if (!$l['event_type'] || $l['event_type'] == $event['event_type']) {
409 $l['cb']($this, $event);
410 }
411 }
412 }
413  
414 public function putEphemeralEvent(array $event) {
415 // Dispatch for room-specific listeners
416 foreach ($this->ephemeralListeners as $l) {
417 if (!$l['event_type'] || $l['event_type'] == $event['event_type']) {
418 $l['cb']($this, $event);
419 }
420 }
421 }
422  
423 /**
424 * Get the most recent events for this room.
425 *
426 * @return array
427 */
428 public function getEvents(): array {
429 return $this->events;
430 }
431  
432 /**
433 * Invite a user to this room.
434 *
435 * @param string $userId
436 * @return bool Whether invitation was sent.
437 * @throws Exceptions\MatrixException
438 * @throws Exceptions\MatrixHttpLibException
439 */
440 public function inviteUser(string $userId): bool {
441 try {
442 $this->api()->inviteUser($this->roomId, $userId);
443 } catch (MatrixRequestException $e) {
444 return false;
445 }
446  
447 return true;
448 }
449  
450 /**
451 * Kick a user from this room.
452 *
453 * @param string $userId The matrix user id of a user.
454 * @param string $reason A reason for kicking the user.
455 * @return bool Whether user was kicked.
456 * @throws Exceptions\MatrixException
457 */
458 public function kickUser(string $userId, string $reason = ''): bool {
459 try {
460 $this->api()->kickUser($this->roomId, $userId, $reason);
461 } catch (MatrixRequestException $e) {
462 return false;
463 }
464  
465 return true;
466 }
467  
468 /**
469 * Ban a user from this room.
470 *
471 * @param string $userId The matrix user id of a user.
472 * @param string $reason A reason for banning the user.
473 * @return bool Whether user was banned.
474 * @throws Exceptions\MatrixException
475 */
476 public function banUser(string $userId, string $reason = ''): bool {
477 try {
478 $this->api()->banUser($this->roomId, $userId, $reason);
479 } catch (MatrixRequestException $e) {
480 return false;
481 }
482  
483 return true;
484 }
485  
486 /**
487 * Leave the room.
488 *
489 * @return bool Leaving the room was successful.
490 * @throws Exceptions\MatrixException
491 * @throws Exceptions\MatrixHttpLibException
492 */
493 public function leave() {
494 try {
495 $this->api()->leaveRoom($this->roomId);
496 $this->client->forgetRoom($this->roomId);
497 } catch (MatrixRequestException $e) {
498 return false;
499 }
500  
501 return true;
502 }
503  
504 /**
505 * Updates $this->name and returns true if room name has changed.
506 * @return bool
507 * @throws Exceptions\MatrixException
508 */
509 public function updateRoomName() {
510 try {
511 $response = $this->api()->getRoomName($this->roomId);
512 $newName = array_get($response, 'name', $this->name);
513 $this->name = $newName;
514 if ($this->name != $newName) {
515 $this->name = $newName;
516 return true;
517 }
518 } catch (MatrixRequestException $e) {
519 }
520  
521 return false;
522 }
523  
524 /**
525 * Return True if room name successfully changed.
526 *
527 * @param string $name
528 * @return bool
529 * @throws Exceptions\MatrixException
530 */
531 public function setRoomName(string $name) {
532 try {
533 $this->api()->setRoomName($this->roomId, $name);
534 $this->name = $name;
535 } catch (MatrixRequestException $e) {
536 return false;
537 }
538  
539 return true;
540 }
541  
542 /**
543 * Send a state event to the room.
544 *
545 * @param string $eventType The type of event that you are sending.
546 * @param array $content An object with the content of the message.
547 * @param string $stateKey Optional. A unique key to identify the state.
548 * @throws Exceptions\MatrixException
549 */
550 public function sendStateEvent(string $eventType, array $content, string $stateKey = '') {
551 $this->api()->sendStateEvent($this->roomId, $eventType, $content, $stateKey);
552 }
553  
554 /**
555 * Updates $this->topic and returns true if room topic has changed.
556 *
557 * @return bool
558 * @throws Exceptions\MatrixException
559 */
560 public function updateRoomTopic() {
561 try {
562 $response = $this->api()->getRoomTopic($this->roomId);
563 $oldTopic = $this->topic;
564 $this->topic = array_get($response, 'topic', $this->topic);
565 } catch (MatrixRequestException $e) {
566 return false;
567 }
568  
569 return $oldTopic == $this->topic;
570 }
571  
572 /**
573 * Return True if room topic successfully changed.
574 *
575 * @param string $topic
576 * @return bool
577 * @throws Exceptions\MatrixException
578 */
579 public function setRoomTopic(string $topic) {
580 try {
581 $this->api()->setRoomTopic($this->roomId, $topic);
582 $this->topic = $topic;
583 } catch (MatrixRequestException $e) {
584 return false;
585 }
586  
587 return true;
588 }
589  
590 /**
591 * Get aliases information from room state.
592 *
593 * @return bool True if the aliases changed, False if not
594 * @throws Exceptions\MatrixException
595 * @throws Exceptions\MatrixHttpLibException
596 */
597 public function updateAliases() {
598 try {
599 $response = $this->api()->getRoomState($this->roomId);
600 $oldAliases = $this->aliases;
601 foreach ($response as $chunk) {
602 if ($aliases = array_get($chunk, 'content.aliases')) {
603 $this->aliases = $aliases;
604 return $this->aliases == $oldAliases;
605 }
606 }
607 } catch (MatrixRequestException $e) {
608 return false;
609 }
610 }
611  
612 /**
613 * Add an alias to the room and return True if successful.
614 *
615 * @param string $alias
616 * @return bool
617 * @throws Exceptions\MatrixException
618 * @throws Exceptions\MatrixHttpLibException
619 */
620 public function addRoomAlias(string $alias) {
621 try {
622 $this->api()->setRoomAlias($this->roomId, $alias);
623 } catch (MatrixRequestException $e) {
624 return false;
625 }
626  
627 return true;
628 }
629  
630 public function getJoinedMembers() {
631 if ($this->_members) {
632 return array_values($this->_members);
633 }
634 $response = $this->api()->getRoomMembers($this->roomId);
635 foreach ($response['chunk'] as $event) {
636 if (array_get($event, 'event.membership') == 'join') {
637 $userId = $event['state_key'];
638 $this->addMember($userId, array_get($event, 'content.displayname'));
639 }
640 }
641  
642 return array_values($this->_members);
643 }
644  
645 protected function addMember(string $userId, ?string $displayname) {
646 if ($displayname) {
647 $this->membersDisplaynames[$userId] = $displayname;
648 }
649 if (array_key_exists($userId, $this->_members)) {
650 return;
651 }
652 if (array_key_exists($userId, $this->client->users)) {
653 $this->_members[$userId] = $this->client->users[$userId];
654 return;
655 }
656 $this->_members[$userId] = new User($this->api(), $userId, $displayname);
657 $this->client->users[$userId] = $this->_members[$userId];
658 }
659  
660 /**
661 * Backfill handling of previous messages.
662 *
663 * @param bool $reverse When false messages will be backfilled in their original
664 * order (old to new), otherwise the order will be reversed (new to old).
665 * @param int $limit Number of messages to go back.
666 * @throws Exceptions\MatrixException
667 * @throws Exceptions\MatrixHttpLibException
668 * @throws MatrixRequestException
669 */
670 public function backfillPreviousMessages(bool $reverse = false, int $limit = 10) {
671 $res = $this->api()->getRoomMessages($this->roomId, $this->prevBatch, 'b', $limit);
672 $events = $res['chunk'];
673 if (!$reverse) {
674 $events = array_reverse($events);
675 }
676 foreach ($events as $event) {
677 $this->putEvent($event);
678 }
679 }
680  
681 /**
682 * Modify the power level for a subset of users
683 *
684 * @param array $users Power levels to assign to specific users, in the form
685 * {"@name0:host0": 10, "@name1:host1": 100, "@name3:host3", None}
686 * A level of None causes the user to revert to the default level
687 * as specified by users_default.
688 * @param int $userDefault Default power level for users in the room
689 * @return bool
690 * @throws Exceptions\MatrixException
691 */
692 public function modifyUserPowerLevels(array $users = null, int $userDefault = null) {
693 try {
694 $content = $this->api()->getPowerLevels($this->roomId);
695 if ($userDefault) {
696 $content['user_default'] = $userDefault;
697 }
698  
699 if ($users) {
700 if (array_key_exists('users', $content)) {
701 $content['users'] = array_merge($content['users'], $content);
702 } else {
703 $content['users'] = $users;
704 }
705  
706 // Remove any keys with value null
707 foreach ($content['users'] as $user => $pl) {
708 if (!$pl) {
709 unset($content['users'][$user]);
710 }
711 }
712 }
713  
714 $this->api()->setPowerLevels($this->roomId, $content);
715 } catch (MatrixRequestException $e) {
716 return false;
717 }
718  
719 return true;
720 }
721  
722 /**
723 * Modifies room power level requirements.
724 *
725 * @param array $events Power levels required for sending specific event types,
726 * in the form {"m.room.whatever0": 60, "m.room.whatever2": None}.
727 * Overrides events_default and state_default for the specified
728 * events. A level of None causes the target event to revert to the
729 * default level as specified by events_default or state_default.
730 * @param array $extra Key/value pairs specifying the power levels required for
731 * various actions:
732 *
733 * - events_default(int): Default level for sending message events
734 * - state_default(int): Default level for sending state events
735 * - invite(int): Inviting a user
736 * - redact(int): Redacting an event
737 * - ban(int): Banning a user
738 * - kick(int): Kicking a user
739 * @return bool
740 * @throws Exceptions\MatrixException
741 */
742 public function modifyRequiredPowerLevels(array $events = [], array $extra = []) {
743 try {
744 $content = $this->api()->getPowerLevels($this->roomId);
745 $content = array_merge($content, $extra);
746 foreach ($content as $k => $v) {
747 if (!$v) {
748 unset($content[$k]);
749 }
750 }
751  
752 if ($events) {
753 if (array_key_exists('events', $content)) {
754 $content["events"] = array_merge($content["events"], $events);
755 } else {
756 $content["events"] = $events;
757 }
758  
759 // Remove any keys with value null
760 foreach ($content['event'] as $event => $pl) {
761 if (!$pl) {
762 unset($content['event'][$event]);
763 }
764 }
765 }
766  
767 $this->api()->setPowerLevels($this->roomId, $content);
768 } catch (MatrixRequestException $e) {
769 return false;
770 }
771  
772 return true;
773 }
774  
775 /**
776 * Set how the room can be joined.
777 *
778 * @param bool $inviteOnly If True, users will have to be invited to join
779 * the room. If False, anyone who knows the room link can join.
780 * @return bool True if successful, False if not
781 * @throws Exceptions\MatrixException
782 */
783 public function setInviteOnly(bool $inviteOnly) {
784 $joinRule = $inviteOnly ? 'invite' : 'public';
785 try {
786 $this->api()->setJoinRule($this->roomId, $joinRule);
787 $this->inviteOnly = $inviteOnly;
788 } catch (MatrixRequestException $e) {
789 return false;
790 }
791  
792 return true;
793 }
794  
795 /**
796 * Set whether guests can join the room and return True if successful.
797 *
798 * @param bool $allowGuest
799 * @return bool
800 * @throws Exceptions\MatrixException
801 */
802 public function setGuestAccess(bool $allowGuest) {
803 $guestAccess = $allowGuest ? 'can_join' : 'forbidden';
804 try {
805 $this->api()->setGuestAccess($this->roomId, $guestAccess);
806 $this->guestAccess = $allowGuest;
807 } catch (MatrixRequestException $e) {
808 return false;
809 }
810  
811 return true;
812 }
813  
814 /**
815 * Enables encryption in the room.
816 *
817 * NOTE: Once enabled, encryption cannot be disabled.
818 *
819 * @return bool True if successful, False if not
820 * @throws Exceptions\MatrixException
821 */
822 public function enableEncryption() {
823 try {
824 $this->sendStateEvent('m.room.encryption', ['algorithm' => 'm.megolm.v1.aes-sha2']);
825 $this->encrypted = true;
826 } catch (MatrixRequestException $e) {
827 return false;
828 }
829  
830 return true;
831 }
832  
833 public function processStateEvent(array $stateEvent) {
834 if (!array_key_exists('type', $stateEvent)) {
835 return;
836 }
837 $etype = $stateEvent['type'];
838 $econtent = $stateEvent['content'];
839 $clevel = $this->client->cacheLevel();
840  
841 // Don't keep track of room state if caching turned off
842 if ($clevel >= Cache::SOME) {
843 switch ($etype) {
844 case 'm.room.name':
845 $this->name = array_get($econtent, 'name');
846 break;
847 case 'm.room.canonical_alias':
848 $this->canonicalAlias = array_get($econtent, 'alias');
849 break;
850 case 'm.room.topic':
851 $this->topic = array_get($econtent, 'topic');
852 break;
853 case 'm.room.aliases':
854 $this->aliases = array_get($econtent, 'aliases');
855 break;
856 case 'm.room.join_rules':
857 $this->inviteOnly = $econtent["join_rule"] == "invite";
858 break;
859 case 'm.room.guest_access':
860 $this->guestAccess = $econtent["guest_access"] == "can_join";
861 break;
862 case 'm.room.encryption':
863 $this->encrypted = array_get($econtent, 'algorithm') ? true : $this->encrypted;
864 break;
865 case 'm.room.member':
866 // tracking room members can be large e.g. #matrix:matrix.org
867 if ($clevel == Cache::ALL) {
868 if ($econtent['membership'] == 'join') {
869 $userId = $stateEvent['state_key'];
870 $this->addMember($userId, array_get($econtent, 'displayname'));
871 } elseif (in_array($econtent["membership"], ["leave", "kick", "invite"])) {
872 unset($this->_members[array_get($stateEvent, 'state_key')]);
873 }
874 }
875 break;
876 }
877 }
878  
879 foreach ($this->stateListeners as $listener) {
880 if (!$listener['event_type'] || $listener['event_type'] == $stateEvent['type']) {
881 $listener['cb']($stateEvent);
882 }
883 }
884 }
885  
886 public function getMembersDisplayNames(): array {
887 return $this->membersDisplaynames;
888 }
889  
890 protected function api(): MatrixHttpApi {
891 return $this->client->api();
892 }
893  
894  
895 }