Exemple #1
0
        def is_iniswap(self, client: ClientManager.Client, anim1: str,
                       anim2: str, char: str) -> bool:
            """
            Decide if a client is iniswapping or using files outside their claimed character folder.

            Assumes that server permitted iniswaps do not count as iniswaps.

            Parameters
            ----------
            client: ClientManager.Client
                Client to test.
            anim1: str
                Location of the preanimation the client used.
            anim2: str
                Location of the main animation the client used.
            char: str
                Name of the folder the client claims their files are.

            Returns
            -------
            bool
                True if either anim1 or anim2 point to an external location through '../../' or
                their claimed character folder does not match the expected server name and the
                performed iniswap is not in the list of allowed iniswaps by the server.
            """

            if char == client.get_char_name():
                return False

            if '..' in anim1 or '..' in anim2:
                return True
            for char_link in self.server.allowed_iniswaps:
                if client.get_char_name() in char_link and char in char_link:
                    return False
            return True
Exemple #2
0
        def play_track(self,
                       name: str,
                       client: ClientManager.Client,
                       raise_if_not_found: bool = False,
                       reveal_sneaked: bool = False,
                       pargs: Dict[str, Any] = None):
            """
            Wrapper function to play a music track in an area.

            Parameters
            ----------
            name : str
                Name of the track to play
            client : ClientManager.Client
                Client who initiated the track change request.
            effect : int, optional
                Accompanying effect to the track (only used by AO 2.8.4+). Defaults to 0.
            raise_if_not_found : bool, optional
                If True, it will raise ServerError if the track name is not in the server's music
                list nor the client's music list. If False, it will not care about it. Defaults to
                False.
            reveal_sneaked : bool, optional
                If True, it will change the visibility status of the sender client to True (reveal
                them). If False, it will keep their visibility as it was. Defaults to False.
            pargs : dict of str to Any
                If given, they are arguments to an MC packet that was given when the track was
                requested, and will override any other arguments given. If not, this is ignored.
                Defaults to None (and converted to an empty dictionary).

            Raises
            ------
            ServerError.FileInvalidNameError:
                If `name` references parent or current directories (e.g. "../hi.mp3")
            ServerError.MusicNotFoundError:
                If `name` is not a music track in the server or client's music list and
                `raise_if_not_found` is True.
            ServerError (with code 'FileInvalidName')
                If `name` references parent or current directories (e.g. "../hi.mp3")
            """

            if not pargs:
                pargs = dict()
            if Constants.includes_relative_directories(name):
                info = f'Music names may not reference parent or current directories: {name}'
                raise ServerError.FileInvalidNameError(info)

            try:
                name, length, source = self.server.get_song_data(name,
                                                                 c=client)
            except ServerError.MusicNotFoundError:
                if raise_if_not_found:
                    raise
                name, length, source = name, -1, ''

            if 'name' not in pargs:
                pargs['name'] = name
            if 'char_id' not in pargs:
                pargs['char_id'] = client.char_id
            pargs['showname'] = client.showname  # Ignore AO shownames
            if 'loop' not in pargs:
                pargs['loop'] = -1
            if 'channel' not in pargs:
                pargs['channel'] = 0
            if 'effects' not in pargs:
                pargs['effects'] = 0

            def loop(char_id):
                for client in self.clients:
                    loop_pargs = pargs.copy()
                    # Overwrite in case char_id changed (e.g., server looping)
                    loop_pargs['char_id'] = char_id
                    client.send_music(**loop_pargs)

                if self.music_looper:
                    self.music_looper.cancel()
                if length > 0:
                    f = lambda: loop(-1)  # Server should loop now
                    self.music_looper = asyncio.get_event_loop().call_later(
                        length, f)

            loop(pargs['char_id'])

            # Record the character name and the track they played.
            self.current_music_player = client.displayname
            self.current_music = name
            self.current_music_source = source

            logger.log_server(
                '[{}][{}]Changed music to {}.'.format(self.id,
                                                      client.get_char_name(),
                                                      name), client)

            # Changing music reveals sneaked players, so do that if requested
            if not client.is_staff(
            ) and not client.is_visible and reveal_sneaked:
                client.change_visibility(True)
                client.send_ooc_others(
                    '(X) {} [{}] revealed themselves by playing music ({}).'.
                    format(client.displayname, client.id, client.area.id),
                    is_zstaff=True)