Exemplo n.º 1
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            room_alias = RoomAlias.create_local(
                config["room_alias_name"],
                self.hs
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias
            )

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                self.hs.parse_userid(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i,))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id, self.hs)
            if not room_id_obj.is_mine:
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(
                room_id=room_id,
                room_creator_user_id=user_id,
                is_public=is_public
            )
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create_local(random_string, self.hs)
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public
                    )
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        user = self.hs.parse_userid(user_id)
        creation_events = self._create_events_for_new_room(
            user, room_id, is_public=is_public
        )

        room_member_handler = self.hs.get_handlers().room_member_handler

        @defer.inlineCallbacks
        def handle_event(event):
            snapshot = yield self.store.snapshot_room(event)

            logger.debug("Event: %s", event)

            if event.type == RoomMemberEvent.TYPE:
                yield room_member_handler.change_membership(
                    event,
                    do_auth=True
                )
            else:
                yield self._on_new_room_event(
                    event, snapshot, extra_users=[user], suppress_auth=True
                )

        for event in creation_events:
            yield handle_event(event)

        if "name" in config:
            name = config["name"]
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                content={"name": name},
            )

            yield handle_event(name_event)

        if "topic" in config:
            topic = config["topic"]
            topic_event = self.event_factory.create_event(
                etype=RoomTopicEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                content={"topic": topic},
            )

            yield handle_event(topic_event)

        content = {"membership": Membership.INVITE}
        for invitee in invite_list:
            invite_event = self.event_factory.create_event(
                etype=RoomMemberEvent.TYPE,
                state_key=invitee,
                room_id=room_id,
                user_id=user_id,
                content=content
            )
            yield handle_event(invite_event)

        result = {"room_id": room_id}

        if room_alias:
            result["room_alias"] = room_alias.to_string()
            yield directory_handler.send_room_alias_update_event(
                user_id, room_id
            )

        defer.returnValue(result)
Exemplo n.º 2
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            room_alias = RoomAlias.create_local(
                config["room_alias_name"],
                self.hs
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias
            )

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                self.hs.parse_userid(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i,))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id, self.hs)
            if not room_id_obj.is_mine:
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(
                room_id=room_id,
                room_creator_user_id=user_id,
                is_public=is_public
            )
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create_local(random_string, self.hs)
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public
                    )
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        user = self.hs.parse_userid(user_id)
        creation_events = self._create_events_for_new_room(
            user, room_id, is_public=is_public
        )

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        @defer.inlineCallbacks
        def handle_event(event):
            snapshot = yield self.store.snapshot_room(
                room_id=room_id,
                user_id=user_id,
            )

            logger.debug("Event: %s", event)

            yield self.state_handler.handle_new_event(event, snapshot)
            yield self._on_new_room_event(event, snapshot, extra_users=[user])

        for event in creation_events:
            yield handle_event(event)

        if "name" in config:
            name = config["name"]
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"name": name},
            )

            yield handle_event(name_event)
        elif room_alias:
            name = room_alias.to_string()
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"name": name},
            )

            yield handle_event(name_event)

        if "topic" in config:
            topic = config["topic"]
            topic_event = self.event_factory.create_event(
                etype=RoomTopicEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"topic": topic},
            )

            yield handle_event(topic_event)

        content = {"membership": Membership.JOIN}
        join_event = self.event_factory.create_event(
            etype=RoomMemberEvent.TYPE,
            state_key=user_id,
            room_id=room_id,
            user_id=user_id,
            membership=Membership.JOIN,
            content=content
        )

        yield self.hs.get_handlers().room_member_handler.change_membership(
            join_event,
            do_auth=False
        )

        content = {"membership": Membership.INVITE}
        for invitee in invite_list:
            invite_event = self.event_factory.create_event(
                etype=RoomMemberEvent.TYPE,
                state_key=invitee,
                room_id=room_id,
                user_id=user_id,
                content=content
            )

            yield self.hs.get_handlers().room_member_handler.change_membership(
                invite_event,
                do_auth=False
            )

        yield self.hs.get_handlers().room_member_handler.change_membership(
            join_event,
            do_auth=False
        )
        result = {"room_id": room_id}
        if room_alias:
            result["room_alias"] = room_alias.to_string()

        defer.returnValue(result)