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)
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)