async def _handle_message(self, message: str) -> None: """Handle received messages. :param message: The message to parse. :type message: str """ try: # Showdown websocket messages are pipe-separated sequences split_messages = [m.split("|") for m in message.split("\n")] # The type of message is determined by the first entry in the message # For battles, this is the zero-th entry # Otherwise it is the one-th entry if split_messages[0][0].startswith(">battle"): # Battle update await self._handle_battle_message(split_messages) elif split_messages[0][1] == "challstr": # Confirms connection to the server: we can login await self._log_in(split_messages[0]) elif split_messages[0][1] == "updateuser": if split_messages[0][2] == " " + self._username: # Confirms successful login self.logged_in.set() elif not split_messages[0][2].startswith(" Guest "): self.logger.warning( """Trying to login as %s, showdown returned %s """ """- this might prevent future actions from this agent. """ """Changing the agent's username might solve this problem.""", self.username, split_messages[0][2], ) elif "updatechallenges" in split_messages[0][1]: # Contain information about current challenge await self._update_challenges(split_messages[0]) elif split_messages[0][1] == "updatesearch": pass elif split_messages[0][1] == "popup": self.logger.warning("Popup message received: %s", message) elif split_messages[0][1] in ["nametaken"]: self.logger.critical("Error message received: %s", message) raise ShowdownException("Error message received: %s", message) elif split_messages[0][1] == "pm": assert len(split_messages) == 1 if split_messages[0][4].startswith("/challenge"): await self._handle_challenge_request(split_messages[0]) elif split_messages[0][4].startswith("/text"): self.logger.info("Received pm with text: %s", message) else: self.logger.warning("Received pm: %s", message) else: self.logger.warning("Unhandled message: %s", message) except CancelledError as e: self.logger.critical("CancelledError intercepted: %s", e) except Exception as exception: self.logger.exception( "Unhandled exception raised while handling message:\n%s", message) raise exception
def accuracy(self) -> float: """ :return: The move's accuracy (0 to 1 scale). :rtype: float """ accuracy = self.entry["accuracy"] if isinstance(accuracy, int): return accuracy / 100 if accuracy is True: return 1 raise ShowdownException("Unmanaged accuracy: %s", accuracy)
def from_request_details(gender: str) -> "PokemonGender": """Returns the PokemonGenre object corresponding to the gender received in a message. :param gender: The received gender to convert. :type gender: str :return: The corresponding PokemonGenre object. :rtype: PokemonGenre """ if gender == "M": return PokemonGender.MALE elif gender == "F": return PokemonGender.FEMALE raise ShowdownException("Unmanaged request gender: '%s'", gender)
async def _create_battle(self, split_message: List[str]) -> AbstractBattle: """Returns battle object corresponding to received message. :param split_message: The battle initialisation message. :type split_message: List[str] :return: The corresponding battle object. :rtype: AbstractBattle """ # We check that the battle has the correct format if split_message[1] == self._format and len(split_message) >= 2: # Battle initialisation battle_tag = "-".join(split_message)[1:] if battle_tag in self._battles: return self._battles[battle_tag] else: if self.format_is_doubles: battle = DoubleBattle( battle_tag=battle_tag, username=self.username, logger=self.logger, save_replays=self._save_replays, ) else: battle = Battle.from_format( format_=self._format, battle_tag=battle_tag, username=self.username, logger=self.logger, save_replays=self._save_replays, ) await self._battle_count_queue.put(None) if battle_tag in self._battles: self._battle_count_queue.get() return self._battles[battle_tag] async with self._battle_start_condition: self._battle_semaphore.release() self._battle_start_condition.notify_all() self._battles[battle_tag] = battle if self._start_timer_on_battle_start: await self._send_message("/timer on", battle.battle_tag) return battle return self._battles[battle_tag] else: self.logger.critical( "Unmanaged battle initialisation message received: %s", split_message ) raise ShowdownException()
async def _create_battle(self, split_message: List[str]) -> Battle: """Returns battle object corresponding to received message. :param split_message: The battle initialisation message. :type split_message: List[str] :return: The corresponding battle object. :rtype: Battle """ # We check that the battle has the correct format if split_message[1] == self._format and len(split_message) >= 2: # Battle initialisation battle_tag = "-".join(split_message) if battle_tag.startswith(">"): battle_tag = battle_tag[1:] if battle_tag.endswith("\n"): battle_tag = battle_tag[:-1] if battle_tag in self._battles: return self._battles[battle_tag] else: battle = Battle(battle_tag=battle_tag, username=self.username, logger=self.logger) await self._battle_started_callback(battle) await self._battle_count_queue.put(None) if battle_tag in self._battles: self._battle_count_queue.get() return self._battles[battle_tag] async with self._battle_start_condition: self._battle_semaphore.release() self._battle_start_condition.notify_all() self._battles[battle_tag] = battle return battle return self._battles[battle_tag] else: self.logger.critical( "Unmanaged battle initialisation message received: %s", split_message) raise ShowdownException()
async def _handle_message(self, message: str) -> None: """Handle received messages. :param message: The message to parse. :type message: str """ try: self.logger.debug("Received message to handle: %s", message) # Showdown websocket messages are pipe-separated sequences split_message = message.split("|") assert len(split_message) > 1 # The type of message is determined by the first entry in the message # For battles, this is the zero-th entry # Otherwise it is the one-th entry if split_message[1] == "challstr": # Confirms connection to the server: we can login await self._log_in(split_message) elif (split_message[1] == "updateuser" and split_message[2] == " " + self._username): # Confirms successful login self.logged_in.set() elif "updatechallenges" in split_message[1]: # Contain information about current challenge await self._update_challenges(split_message) elif split_message[0].startswith(">battle"): # Battle update await self._handle_battle_message(message) elif split_message[1] in ["updatesearch", "popup", "updateuser"]: self.logger.debug("Ignored message: %s", message) pass elif split_message[1] in ["nametaken"]: self.logger.critical("Error message received: %s", message) raise ShowdownException("Error message received: %s", message) elif split_message[1] == "pm": self.logger.info("Received pm: %s", split_message) else: self.logger.critical("Unhandled message: %s", message) raise NotImplementedError("Unhandled message: %s" % message) except CancelledError: pass