Пример #1
0
    def net_cmd_ct(self, args):
        """ OOC Message

        CT#<name:string>#<message:string>#%

        """
        if self.client.is_ooc_muted:  # Checks to see if the client has been muted by a mod
            self.client.send_ooc("You have been muted by a moderator.")
            return
        if not self.validate_net_cmd(
                args, ArgType.STR, ArgType.STR, needs_auth=False):
            return
        if self.client.name != args[0] and self.client.fake_name != args[0]:
            if self.client.is_valid_name(args[0]):
                self.client.name = args[0]
                self.client.fake_name = args[0]
            else:
                self.client.fake_name = args[0]
                self.client.name = ''
        if self.client.name == '':
            self.client.send_ooc(
                'You must insert a name with at least one letter.')
            return
        if self.client.name.startswith(' '):
            self.client.send_ooc(
                'You must insert a name that starts with a letter.')
            return
        if self.server.config[
                'hostname'] in self.client.name or '<dollar>G' in self.client.name:
            self.client.send_ooc('That name is reserved.')
            return
        if args[1].startswith('/'):
            spl = args[1][1:].split(' ', 1)
            cmd = spl[0]
            arg = ''
            if len(spl) == 2:
                arg = spl[1][:1024]
            try:
                called_function = 'ooc_cmd_{}'.format(cmd)
                function = None  # Double assignment to check if it matched to a function later
                function = getattr(self.server.commands, called_function)
            except AttributeError:
                try:
                    function = getattr(self.server.commands_alt,
                                       called_function)
                except AttributeError:
                    logger.log_print('Attribute error with ' + called_function)
                    self.client.send_ooc('Invalid command.')

            if function:
                try:
                    function(self.client, arg)
                except TsuserverException as ex:
                    self.client.send_ooc(ex)
        else:
            # Censor passwords if accidentally said without a slash in OOC
            for password in self.server.all_passwords:
                for login in ['login ', 'logincm ', 'loginrp ', 'logingm ']:
                    if login + password in args[1]:
                        args[1] = args[1].replace(password, '[CENSORED]')
            if self.client.disemvowel:  #If you are disemvoweled, replace string.
                args[1] = Constants.disemvowel_message(args[1])
            if self.client.disemconsonant:  #If you are disemconsonanted, replace string.
                args[1] = Constants.disemconsonant_message(args[1])
            if self.client.remove_h:  #If h is removed, replace string.
                args[1] = Constants.remove_h_message(args[1])

            self.client.area.send_command('CT', self.client.name, args[1])
            self.client.last_ooc_message = args[1]
            logger.log_server(
                '[OOC][{}][{}][{}]{}'.format(self.client.area.id,
                                             self.client.get_char_name(),
                                             self.client.name, args[1]),
                self.client)
        self.client.last_active = Constants.get_time()
Пример #2
0
    def net_cmd_ct(self, args: List[str]):
        """ OOC Message

        CT#<name:string>#<message:string>#%

        """

        pargs = self.process_arguments('CT', args)
        username, message = pargs['username'], pargs['message']

        # Trim out any leading/trailing whitespace characters up to a chain of spaces
        username = Constants.trim_extra_whitespace(username)
        message = Constants.trim_extra_whitespace(message)

        if self.client.is_ooc_muted:  # Checks to see if the client has been muted by a mod
            self.client.send_ooc("You have been muted by a moderator.")
            return
        if username == '' or not self.client.is_valid_name(username):
            self.client.send_ooc('You must insert a name with at least one letter.')
            return
        if username.startswith(' '):
            self.client.send_ooc('You must insert a name that starts with a letter.')
            return
        if Constants.contains_illegal_characters(username):
            self.client.send_ooc('Your name contains an illegal character.')
            return
        if (Constants.decode_ao_packet([self.server.config['hostname']])[0] in username
            or '$G' in username):
            self.client.send_ooc('That name is reserved.')
            return

        # After this the name is validated
        self.client.publish_inbound_command('CT', pargs)
        self.client.name = username

        if message.startswith('/'):
            spl = message[1:].split(' ', 1)
            cmd = spl[0]
            arg = ''
            if len(spl) == 2:
                arg = spl[1][:1024]
            arg = Constants.trim_extra_whitespace(arg)  # Do it again because args may be weird
            try:
                called_function = 'ooc_cmd_{}'.format(cmd)
                function = None  # Double assignment to check if it matched to a function later
                function = getattr(self.server.commands, called_function)
            except AttributeError:
                try:
                    function = getattr(self.server.commands_alt, called_function)
                except AttributeError:
                    self.client.send_ooc(f'Invalid command `{cmd}`.')

            if function:
                try:
                    function(self.client, arg)
                except TsuserverException as ex:
                    if ex.message:
                        self.client.send_ooc(ex)
                    else:
                        self.client.send_ooc(type(ex).__name__)
        else:
            # Censor passwords if accidentally said without a slash in OOC
            for password in self.server.all_passwords:
                for login in ['login ', 'logincm ', 'loginrp ', 'logingm ']:
                    if login + password in args[1]:
                        message = message.replace(password, '[CENSORED]')
            if self.client.disemvowel:  # If you are disemvoweled, replace string.
                message = Constants.disemvowel_message(message)
            if self.client.disemconsonant:  # If you are disemconsonanted, replace string.
                message = Constants.disemconsonant_message(message)
            if self.client.remove_h:  # If h is removed, replace string.
                message = Constants.remove_h_message(message)

            for client in self.client.area.clients:
                client.send_ooc(message, username=self.client.name)
            self.client.last_ooc_message = args[1]
            logger.log_server('[OOC][{}][{}][{}]{}'
                              .format(self.client.area.id, self.client.get_char_name(),
                                      self.client.name, message), self.client)
        self.client.last_active = Constants.get_time()
Пример #3
0
    def net_cmd_ms(self, args):
        """ IC message.

        Refer to the implementation for details.

        """

        if self.client.is_muted:  # Checks to see if the client has been muted by a mod
            self.client.send_ooc("You have been muted by a moderator.")
            return
        if self.client.area.ic_lock and not self.client.is_staff():
            self.client.send_ooc(
                "IC chat in this area has been locked by a moderator.")
            return
        if not self.client.area.can_send_message():
            return
        pargs = self.process_arguments('ms', args)
        if not pargs:
            return

        # First, check if the player just sent the same message with the same character and did
        # not receive any other messages in the meantime.
        # This helps prevent record these messages and retransmit it to clients who may want to
        # filter these out
        if (pargs['text'] == self.client.last_ic_raw_message
                and self.client.last_ic_received_mine
                and self.client.get_char_name() == self.client.last_ic_char):
            return

        if not self.client.area.iniswap_allowed:
            if self.client.area.is_iniswap(self.client, pargs['pre'],
                                           pargs['anim'], pargs['folder']):
                self.client.send_ooc("Iniswap is blocked in this area.")
                return
        if pargs[
                'folder'] in self.client.area.restricted_chars and not self.client.is_staff(
                ):
            self.client.send_ooc('Your character is restricted in this area.')
            return
        if pargs['msg_type'] not in ('chat', '0', '1'):
            return
        if pargs['anim_type'] not in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10):
            return
        if pargs['cid'] != self.client.char_id:
            return
        if pargs['sfx_delay'] < 0:
            return
        if pargs['button'] not in (0, 1, 2, 3, 4, 5, 6, 7):  # Shouts
            return
        if pargs[
                'button'] > 0 and not self.client.area.bullet and not self.client.is_staff(
                ):
            self.client.send_ooc('Bullets are disabled in this area.')
            return
        if pargs['evidence'] < 0:
            return
        if pargs['ding'] not in (0, 1, 2, 3, 4, 5, 6, 7):  # Effects
            return
        if pargs['color'] not in (0, 1, 2, 3, 4, 5, 6):
            return
        if pargs[
                'color'] == 5 and not self.client.is_mod and not self.client.is_cm:
            pargs['color'] = 0
        if pargs['color'] == 6:
            # Remove all unicode to prevent now yellow text abuse
            pargs['text'] = re.sub(r'[^\x00-\x7F]+', ' ', pargs['text'])
            if len(pargs['text'].strip(' ')) == 1:
                pargs['color'] = 0
            else:
                if pargs['text'].strip(' ') in ('<num>', '<percent>',
                                                '<dollar>', '<and>'):
                    pargs['color'] = 0
        if self.client.pos:
            pargs['pos'] = self.client.pos
        else:
            if pargs['pos'] not in ('def', 'pro', 'hld', 'hlp', 'jud', 'wit'):
                return
        self.client.pos = pargs['pos']

        # At this point, the message is guaranteed to be sent
        # First, update last raw message sent *before* any transformations. That is so that the
        # server can accurately ignore client sending the same message over and over again
        self.client.last_ic_raw_message = pargs['text']
        self.client.last_ic_char = self.client.get_char_name()

        # Truncate and alter message if message effect is in place
        raw_msg = pargs['text'][:256]
        msg = raw_msg
        if self.client.gimp:  #If you are gimped, gimp message.
            msg = Constants.gimp_message()
        if self.client.disemvowel:  #If you are disemvoweled, replace string.
            msg = Constants.disemvowel_message(msg)
        if self.client.disemconsonant:  #If you are disemconsonanted, replace string.
            msg = Constants.disemconsonant_message(msg)
        if self.client.remove_h:  #If h is removed, replace string.
            msg = Constants.remove_h_message(msg)

        gag_replaced = False
        if self.client.is_gagged:
            allowed_starters = ('(', '*', '[')
            if msg != ' ' and not msg.startswith(allowed_starters):
                gag_replaced = True
                msg = Constants.gagged_message()
            if msg != raw_msg:
                self.client.send_ooc_others(
                    '(X) {} [{}] tried to say `{}` but is currently gagged.'.
                    format(self.client.displayname, self.client.id, raw_msg),
                    is_zstaff_flex=True,
                    in_area=True)

        # Censor passwords if login command accidentally typed in IC
        for password in self.server.all_passwords:
            for login in ['login ', 'logincm ', 'loginrp ', 'logingm ']:
                if login + password in msg:
                    msg = msg.replace(password, '[CENSORED]')

        if pargs['evidence']:
            evidence_position = self.client.evi_list[pargs['evidence']] - 1
            if self.client.area.evi_list.evidences[
                    evidence_position].pos != 'all':
                self.client.area.evi_list.evidences[
                    evidence_position].pos = 'all'
                self.client.area.broadcast_evidence_list()

        # If client has GlobalIC enabled, set area range target to intended range and remove
        # GlobalIC prefix if needed.
        if self.client.multi_ic is None or not msg.startswith(
                self.client.multi_ic_pre):
            area_range = range(self.client.area.id, self.client.area.id + 1)
        else:
            # As msg.startswith('') is True, this also accounts for having no required prefix.
            start, end = self.client.multi_ic[
                0].id, self.client.multi_ic[1].id + 1
            start_area = self.server.area_manager.get_area_by_id(start)
            end_area = self.server.area_manager.get_area_by_id(end - 1)
            area_range = range(start, end)

            truncated_msg = msg.replace(self.client.multi_ic_pre, '', 1)
            if start != end - 1:
                self.client.send_ooc(
                    'Sent global IC message "{}" to areas {} through {}.'.
                    format(truncated_msg, start_area.name, end_area.name))
            else:
                self.client.send_ooc(
                    'Sent global IC message "{}" to area {}.'.format(
                        truncated_msg, start_area.name))

        pargs['msg'] = msg
        pargs['evidence'] = self.client.evi_list[pargs['evidence']]
        pargs[
            'showname'] = ''  # Dummy value, actual showname is computed later

        # Compute pairs
        # Based on tsuserver3.3 code
        # Only do this if character is paired, which would only happen for AO 2.6+ clients

        # Handle AO 2.8 logic
        # AO 2.8 sends their charid_pair in slightly longer format (\d+\^\d+)
        # The first bit corresponds to the proper charid_pair, the latter one to whether
        # the character should appear in front or behind the pair. We still want to extract
        # charid_pair so pre-AO 2.8 still see the pair; but make it so that AO 2.6 can send pair
        # messages. Thus, we 'invent' the missing arguments based on available info.
        if 'charid_pair_pair_order' in pargs:
            # AO 2.8 sender
            pargs['charid_pair'] = int(
                pargs['charid_pair_pair_order'].split('^')[0])
        elif 'charid_pair' in pargs:
            # AO 2.6 sender
            pargs['charid_pair_pair_order'] = f'{pargs["charid_pair"]}^0'
        else:
            # E.g. DRO
            pargs['charid_pair'] = -1
            pargs['charid_pair_pair_order'] = -1

        self.client.charid_pair = pargs[
            'charid_pair'] if 'charid_pair' in pargs else -1
        self.client.offset_pair = pargs[
            'offset_pair'] if 'offset_pair' in pargs else 0
        self.client.flip = pargs['flip']
        self.client.char_folder = pargs['folder']

        if pargs['anim_type'] not in (5, 6):
            self.client.last_sprite = pargs['anim']

        pargs['other_offset'] = 0
        pargs['other_emote'] = 0
        pargs['other_flip'] = 0
        pargs['other_folder'] = ''
        if 'charid_pair' not in pargs or pargs['charid_pair'] < -1:
            pargs['charid_pair'] = -1
            pargs['charid_pair_pair_order'] = -1

        if pargs['charid_pair'] > -1:
            for target in self.client.area.clients:
                if target == self.client:
                    continue
                # Check pair has accepted pair
                if target.char_id != self.client.charid_pair:
                    continue
                if target.charid_pair != self.client.char_id:
                    continue
                # Check pair is in same position
                if target.pos != self.client.pos:
                    continue

                pargs['other_offset'] = target.offset_pair
                pargs['other_emote'] = target.last_sprite
                pargs['other_flip'] = target.flip
                pargs['other_folder'] = target.char_folder
                break
            else:
                # There are no clients who want to pair with this client
                pargs['charid_pair'] = -1
                pargs['offset_pair'] = 0
                pargs['charid_pair_pair_order'] = -1

        for area_id in area_range:
            target_area = self.server.area_manager.get_area_by_id(area_id)
            for c in target_area.clients:
                c.send_ic(params=pargs,
                          sender=self.client,
                          gag_replaced=gag_replaced)

            target_area.set_next_msg_delay(len(msg))

            # Deal with shoutlog
            if pargs['button'] > 0:
                info = 'used shout {} with the message: {}'.format(
                    pargs['button'], msg)
                target_area.add_to_shoutlog(self.client, info)

        self.client.area.set_next_msg_delay(len(msg))
        logger.log_server(
            '[IC][{}][{}]{}'.format(self.client.area.id,
                                    self.client.get_char_name(), msg),
            self.client)

        # Sending IC messages reveals sneaked players
        if not self.client.is_staff() and not self.client.is_visible:
            self.client.change_visibility(True)
            self.client.send_ooc_others(
                '(X) {} [{}] revealed themselves by talking ({}).'.format(
                    self.client.displayname, self.client.id,
                    self.client.area.id),
                is_zstaff=True)

        self.server.tasker.create_task(self.client, [
            'as_afk_kick', self.client.area.afk_delay,
            self.client.area.afk_sendto
        ])
        if self.client.area.is_recording:
            self.client.area.recorded_messages.append(args)

        self.client.last_ic_message = msg
        self.client.last_active = Constants.get_time()
Пример #4
0
    def net_cmd_ms(self, args):
        """ IC message.

        Refer to the implementation for details.

        """
        if self.client.is_muted:  # Checks to see if the client has been muted by a mod
            self.client.send_ooc("You have been muted by a moderator.")
            return
        if self.client.area.ic_lock and not self.client.is_staff():
            self.client.send_ooc(
                "IC chat in this area has been locked by a moderator.")
            return
        if not self.client.area.can_send_message():
            return

        pargs = self.process_arguments('ms', args)
        if not pargs:
            return

        if not self.client.area.iniswap_allowed:
            if self.client.area.is_iniswap(self.client, pargs['pre'],
                                           pargs['anim'], pargs['folder']):
                self.client.send_ooc("Iniswap is blocked in this area.")
                return
        if pargs[
                'folder'] in self.client.area.restricted_chars and not self.client.is_staff(
                ):
            self.client.send_ooc('Your character is restricted in this area.')
            return
        if pargs['msg_type'] not in ('chat', '0', '1'):
            return
        if pargs['anim_type'] not in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10):
            return
        if pargs['cid'] != self.client.char_id:
            return
        if pargs['sfx_delay'] < 0:
            return
        if pargs['button'] not in (0, 1, 2, 3, 4, 5, 6, 7):  # Shouts
            return
        if pargs[
                'button'] > 0 and not self.client.area.bullet and not self.client.is_staff(
                ):
            self.client.send_ooc('Bullets are disabled in this area.')
            return
        if pargs['evidence'] < 0:
            return
        if pargs['ding'] not in (0, 1, 2, 3, 4, 5, 6, 7):  # Effects
            return
        if pargs['color'] not in (0, 1, 2, 3, 4, 5, 6):
            return
        if pargs[
                'color'] == 5 and not self.client.is_mod and not self.client.is_cm:
            pargs['color'] = 0
        if pargs['color'] == 6:
            # Remove all unicode to prevent now yellow text abuse
            pargs['text'] = re.sub(r'[^\x00-\x7F]+', ' ', pargs['text'])
            if len(pargs['text'].strip(' ')) == 1:
                pargs['color'] = 0
            else:
                if pargs['text'].strip(' ') in ('<num>', '<percent>',
                                                '<dollar>', '<and>'):
                    pargs['color'] = 0
        if self.client.pos:
            pargs['pos'] = self.client.pos
        else:
            if pargs['pos'] not in ('def', 'pro', 'hld', 'hlp', 'jud', 'wit'):
                return
        self.client.pos = pargs['pos']

        # Truncate and alter message if message effect is in place
        raw_msg = pargs['text'][:256]
        msg = raw_msg
        if self.client.gimp:  #If you are gimped, gimp message.
            msg = Constants.gimp_message()
        if self.client.disemvowel:  #If you are disemvoweled, replace string.
            msg = Constants.disemvowel_message(msg)
        if self.client.disemconsonant:  #If you are disemconsonanted, replace string.
            msg = Constants.disemconsonant_message(msg)
        if self.client.remove_h:  #If h is removed, replace string.
            msg = Constants.remove_h_message(msg)

        gag_replaced = False
        if self.client.is_gagged:
            allowed_starters = ('(', '*', '[')
            if msg != ' ' and not msg.startswith(allowed_starters):
                gag_replaced = True
                msg = Constants.gagged_message()
            if msg != raw_msg:
                self.client.send_ooc_others(
                    '(X) {} tried to say `{}` but is currently gagged.'.format(
                        self.client.displayname, raw_msg),
                    is_zstaff_flex=True,
                    in_area=True)

        if pargs['evidence']:
            evidence_position = self.client.evi_list[pargs['evidence']] - 1
            if self.client.area.evi_list.evidences[
                    evidence_position].pos != 'all':
                self.client.area.evi_list.evidences[
                    evidence_position].pos = 'all'
                self.client.area.broadcast_evidence_list()

        # If client has GlobalIC enabled, set area range target to intended range and remove
        # GlobalIC prefix if needed.
        if self.client.multi_ic is None or not msg.startswith(
                self.client.multi_ic_pre):
            area_range = range(self.client.area.id, self.client.area.id + 1)
        else:
            # As msg.startswith('') is True, this also accounts for having no required prefix.
            start, end = self.client.multi_ic[
                0].id, self.client.multi_ic[1].id + 1
            start_area = self.server.area_manager.get_area_by_id(start)
            end_area = self.server.area_manager.get_area_by_id(end - 1)
            area_range = range(start, end)

            msg = msg.replace(self.client.multi_ic_pre, '', 1)
            if start != end - 1:
                self.client.send_ooc(
                    'Sent global IC message "{}" to areas {} through {}.'.
                    format(msg, start_area.name, end_area.name))
            else:
                self.client.send_ooc(
                    'Sent global IC message "{}" to area {}.'.format(
                        msg, start_area.name))

        pargs['msg'] = msg
        pargs['evidence'] = self.client.evi_list[pargs['evidence']]
        pargs[
            'showname'] = ''  # Dummy value, actual showname is computed later

        # Compute pairs
        # Based on tsuserver3.3 code
        # Only do this if character is paired, which would only happen for AO 2.6 clients

        self.client.charid_pair = pargs[
            'charid_pair'] if 'charid_pair' in pargs else -1
        self.client.offset_pair = pargs[
            'offset_pair'] if 'offset_pair' in pargs else 0
        self.client.flip = pargs['flip']
        self.client.char_folder = pargs['folder']

        if pargs['anim_type'] not in (5, 6):
            self.client.last_sprite = pargs['anim']

        pargs['other_offset'] = 0
        pargs['other_emote'] = 0
        pargs['other_flip'] = 0
        pargs['other_folder'] = ''
        if 'charid_pair' not in pargs or pargs['charid_pair'] < -1:
            pargs['charid_pair'] = -1

        if pargs['charid_pair'] > -1:
            for target in self.client.area.clients:
                if target == self.client:
                    continue
                # Check pair has accepted pair
                if target.char_id != self.client.charid_pair:
                    continue
                if target.charid_pair != self.client.char_id:
                    continue
                # Check pair is in same position
                if target.pos != self.client.pos:
                    continue

                pargs['other_offset'] = target.offset_pair
                pargs['other_emote'] = target.last_sprite
                pargs['other_flip'] = target.flip
                pargs['other_folder'] = target.char_folder
                break
            else:
                # There are no clients who want to pair with this client
                pargs['charid_pair'] = -1

        for area_id in area_range:
            target_area = self.server.area_manager.get_area_by_id(area_id)
            for c in target_area.clients:
                c.send_ic(params=pargs,
                          sender=self.client,
                          gag_replaced=gag_replaced)

            target_area.set_next_msg_delay(len(msg))

            # Deal with shoutlog
            if pargs['button'] > 0:
                info = 'used shout {} with the message: {}'.format(
                    pargs['button'], msg)
                target_area.add_to_shoutlog(self.client, info)

        self.client.area.set_next_msg_delay(len(msg))
        logger.log_server(
            '[IC][{}][{}]{}'.format(self.client.area.id,
                                    self.client.get_char_name(), msg),
            self.client)

        # Sending IC messages reveals sneaked players
        if not self.client.is_staff() and not self.client.is_visible:
            self.client.change_visibility(True)
            self.client.send_ooc_others(
                '(X) {} revealed themselves by talking ({}).'.format(
                    self.client.displayname, self.client.area.id),
                is_zstaff=True)

        self.server.tasker.create_task(self.client, [
            'as_afk_kick', self.client.area.afk_delay,
            self.client.area.afk_sendto
        ])
        if self.client.area.is_recording:
            self.client.area.recorded_messages.append(args)

        self.client.last_ic_message = msg
        self.client.last_active = Constants.get_time()