diff --git a/matrix_client/api.py b/matrix_client/api.py index 6c17f878..3348b038 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -744,3 +744,29 @@ def get_room_members(self, room_id): room_id (str): The room to get the member events for. """ return self._send("GET", "/rooms/{}/members".format(quote(room_id))) + + def set_join_rule(self, room_id, join_rule): + """Set the rule for users wishing to join the room. + + Args: + room_id(str): The room to set the rules for. + join_rule(str): The chosen rule. One of: ["public", "knock", + "invite", "private"] + """ + content = { + "join_rule": join_rule + } + return self.send_state_event(room_id, "m.room.join_rules", content) + + def set_guest_access(self, room_id, guest_access): + """Set the guest access policy of the room. + + Args: + room_id(str): The room to set the rules for. + guest_access(str): Wether guests can join. One of: ["can_join", + "forbidden"] + """ + content = { + "guest_access": guest_access + } + return self.send_state_event(room_id, "m.room.guest_access", content) diff --git a/matrix_client/client.py b/matrix_client/client.py index 3ea1dc03..0ef09b56 100644 --- a/matrix_client/client.py +++ b/matrix_client/client.py @@ -495,26 +495,31 @@ def _process_state_event(self, state_event, current_room): if "type" not in state_event: return # Ignore event etype = state_event["type"] + econtent = state_event["content"] # Don't keep track of room state if caching turned off if self._cache_level.value >= 0: if etype == "m.room.name": - current_room.name = state_event["content"].get("name", None) + current_room.name = econtent.get("name") elif etype == "m.room.canonical_alias": - current_room.canonical_alias = state_event["content"].get("alias") + current_room.canonical_alias = econtent.get("alias") elif etype == "m.room.topic": - current_room.topic = state_event["content"].get("topic", None) + current_room.topic = econtent.get("topic") elif etype == "m.room.aliases": - current_room.aliases = state_event["content"].get("aliases", None) + current_room.aliases = econtent.get("aliases") + elif etype == "m.room.join_rules": + current_room.invite_only = econtent["join_rule"] == "invite" + elif etype == "m.room.guest_access": + current_room.guest_access = econtent["guest_access"] == "can_join" elif etype == "m.room.member" and self._cache_level == CACHE.ALL: # tracking room members can be large e.g. #matrix:matrix.org - if state_event["content"]["membership"] == "join": + if econtent["membership"] == "join": current_room._mkmembers( User(self.api, state_event["state_key"], - state_event["content"].get("displayname", None)) + econtent.get("displayname")) ) - elif state_event["content"]["membership"] in ("leave", "kick", "invite"): + elif econtent["membership"] in ("leave", "kick", "invite"): current_room._rmmembers(state_event["state_key"]) for listener in current_room.state_listeners: diff --git a/matrix_client/room.py b/matrix_client/room.py index 7717bb14..20b8ca01 100644 --- a/matrix_client/room.py +++ b/matrix_client/room.py @@ -33,6 +33,8 @@ def __init__(self, client, room_id): self.canonical_alias = None self.aliases = [] self.topic = None + self.invite_only = None + self.guest_access = None self._prev_batch = None self._members = [] @@ -624,6 +626,41 @@ def modify_required_power_levels(self, events=None, **kwargs): except MatrixRequestError: return False + def set_invite_only(self, invite_only): + """Set how the room can be joined. + + Args: + invite_only(bool): If True, users will have to be invited to join + the room. If False, anyone who knows the room link can join. + + Returns: + True if successful, False if not + """ + join_rule = "invite" if invite_only else "public" + try: + self.client.api.set_join_rule(self.room_id, join_rule) + self.invite_only = invite_only + return True + except MatrixRequestError: + return False + + def set_guest_access(self, allow_guests): + """Set whether guests can join the room. + + Args: + allow_guests(bool): If True, guests can join. + + Returns: + True if successful, False if not + """ + guest_access = "can_join" if allow_guests else "forbidden" + try: + self.client.api.set_guest_access(self.room_id, guest_access) + self.guest_access = allow_guests + return True + except MatrixRequestError: + return False + @property def prev_batch(self): return self._prev_batch diff --git a/test/client_test.py b/test/client_test.py index 707d1850..72519bdd 100644 --- a/test/client_test.py +++ b/test/client_test.py @@ -116,6 +116,20 @@ def test_state_event(): client._process_state_event(ev, room) assert len(room._members) == 0 + # test join_rules + room.invite_only = False + ev["type"] = "m.room.join_rules" + ev["content"] = {"join_rule": "invite"} + client._process_state_event(ev, room) + assert room.invite_only + + # test guest_access + room.guest_access = False + ev["type"] = "m.room.guest_access" + ev["content"] = {"guest_access": "can_join"} + client._process_state_event(ev, room) + assert room.guest_access + def test_get_user(): client = MatrixClient("http://example.com") @@ -406,3 +420,35 @@ def test_cache(): assert m_none.rooms[room_id]._members == m_some.rooms[room_id]._members == [] assert len(m_all.rooms[room_id]._members) == 1 assert m_all.rooms[room_id]._members[0].user_id == "@alice:example.com" + + +@responses.activate +def test_room_join_rules(): + client = MatrixClient(HOSTNAME) + room_id = "!UcYsUzyxTGDxLBEvLz:matrix.org" + room = client._mkroom(room_id) + assert room.invite_only is None + join_rules_state_path = HOSTNAME + MATRIX_V2_API_PATH + \ + "/rooms/" + quote(room_id) + "/state/m.room.join_rules" + + responses.add(responses.PUT, join_rules_state_path, + json=response_examples.example_event_response) + + assert room.set_invite_only(True) + assert room.invite_only + + +@responses.activate +def test_room_guest_access(): + client = MatrixClient(HOSTNAME) + room_id = "!UcYsUzyxTGDxLBEvLz:matrix.org" + room = client._mkroom(room_id) + assert room.guest_access is None + guest_access_state_path = HOSTNAME + MATRIX_V2_API_PATH + \ + "/rooms/" + quote(room_id) + "/state/m.room.guest_access" + + responses.add(responses.PUT, guest_access_state_path, + json=response_examples.example_event_response) + + assert room.set_guest_access(True) + assert room.guest_access