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()
def receive_command_stc(self, command_type, *args): command_type, *args = Constants.decode_ao_packet([command_type] + list(args)) self.received_packets.append([command_type, tuple(args)]) buffer = '' if command_type == 'decryptor': # Hi buffer = 'HI#FAKEHDID#%' elif command_type == 'ID': # Server ID buffer = "ID#DRO#1.0.0#%" err = ('Wrong client ID for {}.\nExpected {}\nGot {}' .format(self, args[0], self.id)) assert args[0] == str(self.id), err elif command_type == 'FL': # AO 2.2.5 configs pass elif command_type == 'PN': # Player count pass elif command_type == 'SI': # Counts for char/evi/music pass elif command_type == 'SC': # Character list # TODO: RC!!! pass elif command_type == 'SM': # First timer music/area list pass elif command_type == 'CharsCheck': # Available characters pass elif command_type == 'HP': # Def/pro bar pass elif command_type == 'BN': # Background file pass elif command_type == 'LE': # Evidence list pass elif command_type == 'MM': # ????????????? pass elif command_type == 'OPPASS': # Guard pass pass elif command_type == 'DONE': # Done setting up courtroom pass elif command_type == 'CT': # OOC message self.received_ooc.append((args[0], args[1])) elif command_type == 'FM': # Updated music/area list pass elif command_type == 'PV': # Current character pass elif command_type == 'MS': # IC message # 0 = msg_type # 1 = pre # 2 = folder # 3 = anim # 4 = msg # 5 = pos # 6 = sfx # 7 = anim_type # 8 = char_id # 9 = sfx_delay # 10 = button # 11 = self.client.evi_list[evidence] # 12 = flip # 13 = ding # 14 = color # 15 = showname if not (len(args) == 16): raise ValueError('Malformed MS packet for an IC message {}'.format(args)) self.received_ic.append(args) elif command_type == 'MC': # Start playing track pass elif command_type == 'ZZ': # Mod call pass elif command_type == 'GM': # Gamemode switch pass elif command_type == 'TOD': # Time of day switch pass elif command_type == 'ackMS': # Acknowledge MS packet pass elif command_type == 'SN': # Showname change pass else: raise KeyError('Unrecognized STC argument `{}` {}'.format(command_type, args)) if buffer: self.send_command_cts(buffer)
def data_received(self, data): """ Handles any data received from the network. Receives data, parses them into a command and passes it to the command handler. :param data: bytes of data """ buf = data if buf is None: buf = b'' # try to decode as utf-8, ignore any erroneous characters self.buffer += buf.decode('utf-8', 'ignore') self.buffer = self.buffer.translate({ord(c): None for c in '\0'}) if len(self.buffer) > 8192: msg = self.buffer if len(self.buffer) < 512 else self.buffer[:512] + '...' logger.log_server('Terminated {} (packet too long): sent {} ({} bytes)' .format(self.client.get_ipreal(), msg, len(self.buffer))) self.client.disconnect() return found_message = False for msg in self.get_messages(): found_message = True if len(msg) < 2: # This immediatelly kills any client that does not even try to follow the proper # client protocol msg = self.buffer if len(self.buffer) < 512 else self.buffer[:512] + '...' logger.log_server('Terminated {} (packet too short): sent {} ({} bytes)' .format(self.client.get_ipreal(), msg, len(self.buffer))) self.client.disconnect() return # general netcode structure is not great if msg[0] in ('#', '3', '4'): if msg[0] == '#': msg = msg[1:] raw_parameters = msg.split('#') raw_parameters[0] = fanta_decrypt(raw_parameters[0]) msg = '#'.join(raw_parameters) logger.log_debug('[INC][RAW]{}'.format(msg), self.client) try: if self.server.print_packets: print(f'> {self.client.id}: {msg}') self.server.log_packet(self.client, msg, True) # Decode AO clients' encoding cmd, *args = Constants.decode_ao_packet(msg.split('#')) try: dispatched = self.net_cmd_dispatcher[cmd] except KeyError: logger.log_pserver(f'Client {self.client.id} sent abnormal packet {msg} ' f'(client version: {self.client.version}).') else: dispatched(self, args) except AOProtocolError.InvalidInboundPacketArguments: pass except Exception as ex: self.server.send_error_report(self.client, cmd, args, ex) if not found_message: # This immediatelly kills any client that does not even try to follow the proper # client protocol msg = self.buffer if len(self.buffer) < 512 else self.buffer[:512] + '...' logger.log_server('Terminated {} (packet syntax unrecognized): sent {} ({} bytes)' .format(self.client.get_ipreal(), msg, len(self.buffer))) self.client.disconnect()
def convert_word_to_symbol(mes): if mes is None: return None return Constants.decode_ao_packet([mes])[0]