async def started_typing(self, target_user: UserID, requester: Requester, room_id: str, timeout: int) -> None: target_user_id = target_user.to_string() auth_user_id = requester.user.to_string() if not self.is_mine_id(target_user_id): raise SynapseError(400, "User is not hosted on this homeserver") if target_user_id != auth_user_id: raise AuthError(400, "Cannot set another user's typing state") if requester.shadow_banned: # We randomly sleep a bit just to annoy the requester. await self.clock.sleep(random.randint(1, 10)) raise ShadowBanError() await self.auth.check_user_in_room(room_id, target_user_id) logger.debug("%s has started typing in %s", target_user_id, room_id) member = RoomMember(room_id=room_id, user_id=target_user_id) was_present = member.user_id in self._room_typing.get(room_id, set()) now = self.clock.time_msec() self._member_typing_until[member] = now + timeout self.wheel_timer.insert(now=now, obj=member, then=now + timeout) if was_present: # No point sending another notification return self._push_update(member=member, typing=True)
async def update_membership( self, requester: Requester, target: UserID, room_id: str, action: str, txn_id: Optional[str] = None, remote_room_hosts: Optional[List[str]] = None, third_party_signed: Optional[dict] = None, ratelimit: bool = True, content: Optional[dict] = None, require_consent: bool = True, ) -> Tuple[str, int]: """Update a user's membership in a room. Params: requester: The user who is performing the update. target: The user whose membership is being updated. room_id: The room ID whose membership is being updated. action: The membership change, see synapse.api.constants.Membership. txn_id: The transaction ID, if given. remote_room_hosts: Remote servers to send the update to. third_party_signed: Information from a 3PID invite. ratelimit: Whether to rate limit the request. content: The content of the created event. require_consent: Whether consent is required. Returns: A tuple of the new event ID and stream ID. Raises: ShadowBanError if a shadow-banned requester attempts to send an invite. """ if action == Membership.INVITE and requester.shadow_banned: # We randomly sleep a bit just to annoy the requester. await self.clock.sleep(random.randint(1, 10)) raise ShadowBanError() key = (room_id, ) with (await self.member_linearizer.queue(key)): result = await self.update_membership_locked( requester, target, room_id, action, txn_id=txn_id, remote_room_hosts=remote_room_hosts, third_party_signed=third_party_signed, ratelimit=ratelimit, content=content, require_consent=require_consent, ) return result
async def stopped_typing(self, target_user, requester, room_id): target_user_id = target_user.to_string() auth_user_id = requester.user.to_string() if not self.is_mine_id(target_user_id): raise SynapseError(400, "User is not hosted on this homeserver") if target_user_id != auth_user_id: raise AuthError(400, "Cannot set another user's typing state") if requester.shadow_banned: # We randomly sleep a bit just to annoy the requester. await self.clock.sleep(random.randint(1, 10)) raise ShadowBanError() await self.auth.check_user_in_room(room_id, target_user_id) logger.debug("%s has stopped typing in %s", target_user_id, room_id) member = RoomMember(room_id=room_id, user_id=target_user_id) self._stopped_typing(member)
async def do_3pid_invite( self, room_id: str, inviter: UserID, medium: str, address: str, id_server: str, requester: Requester, txn_id: Optional[str], id_access_token: Optional[str] = None, ) -> int: """Invite a 3PID to a room. Args: room_id: The room to invite the 3PID to. inviter: The user sending the invite. medium: The 3PID's medium. address: The 3PID's address. id_server: The identity server to use. requester: The user making the request. txn_id: The transaction ID this is part of, or None if this is not part of a transaction. id_access_token: The optional identity server access token. Returns: The new stream ID. Raises: ShadowBanError if the requester has been shadow-banned. """ if self.config.block_non_admin_invites: is_requester_admin = await self.auth.is_server_admin(requester.user ) if not is_requester_admin: raise SynapseError( 403, "Invites have been disabled on this server", Codes.FORBIDDEN) if requester.shadow_banned: # We randomly sleep a bit just to annoy the requester. await self.clock.sleep(random.randint(1, 10)) raise ShadowBanError() # We need to rate limit *before* we send out any 3PID invites, so we # can't just rely on the standard ratelimiting of events. await self.base_handler.ratelimit(requester) can_invite = await self.third_party_event_rules.check_threepid_can_be_invited( medium, address, room_id) if not can_invite: raise SynapseError( 403, "This third-party identifier can not be invited in this room", Codes.FORBIDDEN, ) if not self._enable_lookup: raise SynapseError( 403, "Looking up third-party identifiers is denied from this server" ) invitee = await self.identity_handler.lookup_3pid( id_server, medium, address, id_access_token) if invitee: # Note that update_membership with an action of "invite" can raise # a ShadowBanError, but this was done above already. _, stream_id = await self.update_membership( requester, UserID.from_string(invitee), room_id, "invite", txn_id=txn_id) else: stream_id = await self._make_and_store_3pid_invite( requester, id_server, medium, address, room_id, inviter, txn_id=txn_id, id_access_token=id_access_token, ) return stream_id