def test_character_from_content(self): """Testing parsing a character's HTML content""" character = Character.from_content(self.load_resource(FILE_CHARACTER_RESOURCE)) self._compare_character(Character("Tschas", "Gladera", Vocation.ELDER_DRUID, 522, Sex.FEMALE), character) self.assertIsNotNone(character.guild_membership) self.assertEqual("Bald Dwarfs", character.guild_membership.name) self.assertEqual("Emperor", character.guild_membership.rank) self.assertIsNotNone(character.guild_url) self.assertIsNone(character.married_to_url) self.assertEqual(character.guild_name, character.guild_membership.name) self.assertEqual(character.guild_rank, character.guild_membership.rank) self.assertEqual(AccountStatus.PREMIUM_ACCOUNT, character.account_status) self.assertEqual(304, character.achievement_points) self.assertIsNone(character.deletion_date) self.assertIsNotNone(character.deaths) self.assertEqual(2, character.deaths.__len__()) self.assertEqual(parse_tibia_datetime("Aug 02 2021, 17:32:07 CEST"), character.last_login) self.assertEqual(character.url, Character.get_url(character.name)) self.assertEqual(5, len(character.other_characters)) self.assertFalse(character.hidden) # Badges self.assertEqual(3, len(character.account_badges)) badge = character.account_badges[0] self.assertEqual("Ancient Hero", badge.name) self.assertEqual("The account is older than 15 years.", badge.description)
def test_character_from_content(self): """Testing parsing a character's HTML content""" character = Character.from_content( self._load_resource(FILE_CHARACTER_RESOURCE)) self._compare_character( Character("Tschas", "Gladera", Vocation.DRUID, 260, Sex.FEMALE), character) self.assertIsNotNone(character.guild_membership) self.assertEqual("Atlantis", character.guild_membership.name) self.assertEqual("Gaia", character.guild_membership.rank) self.assertIsNotNone(character.guild_url) self.assertIsNone(character.married_to_url) self.assertEqual(character.guild_name, character.guild_membership.name) self.assertEqual(character.guild_rank, character.guild_membership.rank) self.assertEqual(AccountStatus.FREE_ACCOUNT, character.account_status) self.assertEqual(182, character.achievement_points) self.assertIsNone(character.house) self.assertIsNone(character.deletion_date) self.assertIsNotNone(character.deaths) self.assertEqual(0, character.deaths.__len__()) self.assertEqual(parse_tibia_datetime("Aug 04 2019, 13:56:59 CEST"), character.last_login) self.assertEqual(character.url, Character.get_url(character.name)) self.assertEqual(5, len(character.other_characters)) self.assertFalse(character.hidden)
def get_character(name): """Fetch a character using requests instead of aiohttp.""" url = Character.get_url(name) r = requests.get(url) content = r.text character = Character.from_content(content) return character
def test_character_from_tibiadata_deleted(self): """Testing parsing a deleted character""" content = self._load_resource(FILE_CHARACTER_TIBIADATA_DELETED) char = Character.from_tibiadata(content) self.assertEqual(char.url_tibiadata, Character.get_url_tibiadata(char.name)) self.assertIsInstance(char, Character) self.assertTrue(char.deleted) self.assertIsInstance(char.deletion_date, datetime.datetime) self.assertIsNone(char.guild_name) self.assertIsNone(char.last_login)
def test_character_from_content_complex_deaths(self): """Testing parsing a character with complex deaths (summons, assists, etc)""" content = self.load_resource(FILE_CHARACTER_DEATHS_COMPLEX) char = Character.from_content(content) self.assertEqual(5, len(char.deaths)) death1, death2, death3, death4, death5 = char.deaths self.assertIsInstance(death1, Death) self.assertEqual(23, len(death1.killers)) self.assertEqual(1, len(death1.assists)) self.assertIsInstance(death2, Death) self.assertEqual(1, len(death2.killers)) self.assertEqual(0, len(death2.assists)) self.assertIsInstance(death3, Death) self.assertEqual(11, len(death3.killers)) self.assertEqual(0, len(death3.assists)) self.assertEqual("a paladin familiar", death3.killers[-1].summon) self.assertEqual("Alloy Hat", death3.killers[-1].name) self.assertTrue(death3.killers[-1].traded) self.assertIsInstance(death4, Death) self.assertEqual(12, len(death4.killers)) self.assertEqual(0, len(death4.assists)) self.assertEqual("Cliff Lee Burton", death4.killers[-1].name) self.assertTrue(death4.killers[-1].traded)
def test_character_from_content_with_position(self): """Testing parsing a character with a position""" content = self._load_resource(FILE_CHARACTER_SPECIAL_POSITION) char = Character.from_content(content) self.assertEqual(char.name, "Steve") self.assertEqual(char.position, "CipSoft Member") self.assertEqual(char.account_information.position, "CipSoft Member")
def test_character_from_content_truncated_deaths(self): """Testing parsing a character with truncated daths""" content = self._load_resource(FILE_CHARACTER_TRUNCATED_DEATHS) char = Character.from_content(content) self.assertEqual("Godlike Terror", char.name) self.assertEqual(51, len(char.deaths)) self.assertTrue(char.deaths_truncated)
async def test_client_fetch_character(self, mock): """Testing fetching a character""" name = "Tschas" content = self.load_resource(FILE_CHARACTER_RESOURCE) mock.get(Character.get_url(name), status=200, body=content) character = await self.client.fetch_character(name) self.assertIsInstance(character.data, Character)
def test_character_from_content_deleted_character(self): """Testing parsing a character scheduled for deletion""" content = self.load_resource(FILE_CHARACTER_DELETION) char = Character.from_content(content) self.assertEqual("Expendable Dummy", char.name) self.assertIsNotNone(char.deletion_date) self.assertIsInstance(char.deletion_date, datetime.datetime) self.assertEqual(parse_tibia_datetime("Oct 08 2018 22:17:00 CEST"), char.deletion_date)
async def test_client_fetch_character_not_found(self, mock): """Testing fetching a non existent character""" name = "Nezune" content = self.load_resource(FILE_CHARACTER_NOT_FOUND) mock.get(Character.get_url(name), status=200, body=content) character = await self.client.fetch_character(name) self.assertIsNone(character.data)
def test_character_from_tibiadata(self): """Testing parsing TibiaData content""" content = self._load_resource(FILE_CHARACTER_TIBIADATA) char = Character.from_tibiadata(content) self.assertEqual(char.url_tibiadata, Character.get_url_tibiadata(char.name)) self.assertIsInstance(char, Character) self.assertIsNotNone(char.guild_name) self.assertIsInstance(char.last_login, datetime.datetime) self.assertIsInstance(char.house, CharacterHouse) self.assertEqual(char.house.owner, char.name) self.assertEqual(char.house.town, "Ankrahmun") self.assertEqual(char.house.world, char.world) self.assertIsInstance(char.house.paid_until_date, datetime.date) self.assertTrue(char.deaths[3].by_player)
def test_character_from_content_complex_deaths(self): """Testing parsing a character with complex deaths (summons, assists, etc)""" content = self._load_resource(FILE_CHARACTER_DEATHS_COMPLEX) char = Character.from_content(content) self.assertTrue(char.deaths) self.assertIsInstance(char.deaths[0], Death) self.assertEqual(len(char.deaths), 19) oldest_death = char.deaths[-1] self.assertEqual(oldest_death.killer.summon, "a fire elemental")
def test_character_from_tibiadata_summon_deaths(self): """Testing parsing a character with summon deaths""" content = self._load_resource(FILE_CHARACTER_TIBIADATA_DEATHS_SUMMON) char = Character.from_tibiadata(content) self.assertTrue(char.deaths) summon_death = char.deaths[2] self.assertTrue(summon_death.killers[2].summon, "a fire elemental") self.assertTrue(summon_death.killers[2].name, "Hasi Pupsi")
def test_character_from_content_no_selected_badges(self): """Testing parsing a character with visible badges but none selected.""" content = self._load_resource(FILE_CHARACTER_NO_BADGES_SELECTED) char = Character.from_content(content) self.assertEqual("Cozzackirycerz", char.name) self.assertEqual(25, char.achievement_points) self.assertIsNone(char.title) self.assertEqual(3, char.unlocked_titles) self.assertEqual(0, len(char.account_badges)) self.assertEqual(0, len(char.former_names))
def test_character_changes(self): content = self.load_resource( "website_changes/2_community_characters_bobeek.txt") character = Character.from_content(content) self.assertEqual("Bobeek", character.name) self.assertIsNotNone(character.guild_membership) self.assertEqual("Hill", character.guild_membership.name) self.assertEqual("King", character.guild_membership.rank) self.assertEqual("Goraca", character.married_to) self.assertEqual(character.guild_name, character.guild_membership.name) self.assertEqual(character.guild_rank, character.guild_membership.rank) self.assertEqual(AccountStatus.PREMIUM_ACCOUNT, character.account_status) self.assertEqual(1038, character.achievement_points) self.assertIsNone(character.deletion_date) self.assertIsNotNone(character.deaths) self.assertEqual(1, character.deaths.__len__()) self.assertEqual(character.url, Character.get_url(character.name)) self.assertEqual(3, len(character.other_characters)) self.assertFalse(character.hidden)
def test_character_from_content_multiple_houses(self): """Testing parsing a character with multiple houses.""" content = self.load_resource(FILE_CHARACTER_MULTIPLE_HOUSES) char = Character.from_content(content) self.assertEqual("Sayuri Nowan", char.name) self.assertEqual(2, len(char.houses)) first_house = char.houses[0] second_house = char.houses[1] self.assertEqual("Cormaya 10", first_house.name) self.assertEqual("Old Heritage Estate", second_house.name) self.assertEqual("Edron", first_house.town) self.assertEqual("Rathleton", second_house.town)
def test_character_from_content_with_former_names(self): """Testing parsing a character that has former names""" content = self._load_resource(FILE_CHARACTER_FORMER_NAMES) char = Character.from_content(content) self.assertIsInstance(char.former_names, list) self.assertTrue(char.former_names) self.assertEqual(len(char.former_names), 2) self.assertIsInstance(char.house, CharacterHouse) self.assertEqual(char.house.owner, char.name) self.assertEqual(char.house.town, "Darashia") self.assertEqual(char.house.world, char.world) self.assertIsInstance(char.house.paid_until_date, datetime.date)
def test_character_from_content_with_position(self): """Testing parsing a character with a position""" content = self.load_resource(FILE_CHARACTER_SPECIAL_POSITION) position = "CipSoft Member" char = Character.from_content(content) self.assertEqual("Steve", char.name) self.assertEqual(position, char.position) self.assertEqual(position, char.account_information.position) steve_other = char.other_characters[2] self.assertEqual("Steve", steve_other.name) self.assertEqual("CipSoft Member", steve_other.position)
def test_character_from_tibiadata_unhidden(self): """Testing parsing an unhidden character""" content = self._load_resource(FILE_CHARACTER_TIBIADATA_UNHIDDEN) char = Character.from_tibiadata(content) self.assertIsNotNone(char.account_information) self.assertTrue(char.other_characters) self.assertFalse(char.hidden) self.assertIsInstance(char.house, CharacterHouse) self.assertEqual(char.house.owner, char.name) self.assertEqual(char.house.town, "Kazordoon") self.assertEqual(char.house.world, char.world) self.assertIsInstance(char.house.paid_until_date, datetime.date)
async def get_character(bot, name, *, tries=5) -> Optional[NabChar]: """Fetches a character from TibiaData, parses and returns a Character object The character object contains all the information available on Tibia.com Information from the user's database is also added, like owner and highscores. If the character can't be fetch due to a network error, an NetworkError exception is raised If the character doesn't exist, None is returned. """ if tries == 0: raise errors.NetworkError(f"get_character({name})") try: url = Character.get_url_tibiadata(name) except UnicodeEncodeError: return None if invalid_name.search(name): return None # Fetch website try: character = CACHE_CHARACTERS[name.lower()] except KeyError: try: async with bot.session.get(url) as resp: content = await resp.text(encoding='ISO-8859-1') character = NabChar.from_tibiadata(content) except (aiohttp.ClientError, asyncio.TimeoutError, tibiapy.TibiapyException): await asyncio.sleep(config.network_retry_delay) return await get_character(bot, name, tries=tries - 1) CACHE_CHARACTERS[name.lower()] = character if character is None: return None if character.house: house_id = get_house_id(character.house.name) if house_id: character.house.id = house_id # If the character exists in the online list use data from there where possible try: for c in online_characters[character.world]: if c == character: character.level = c.level character.vocation = c.vocation break except KeyError: pass await bind_database_character(bot, character) return character
def test_character_from_content_badges_and_title(self): """Testing parsing a character with account badges and a title""" content = self._load_resource(FILE_CHARACTER_TITLE_BADGES) char = Character.from_content(content) self.assertEqual("Galarzaa Fidera", char.name) self.assertEqual(406, char.achievement_points) self.assertEqual("Gold Hoarder", char.title) self.assertEqual(8, char.unlocked_titles) self.assertEqual(6, len(char.account_badges)) for badge in char.account_badges: self.assertIsInstance(badge, AccountBadge) self.assertIsInstance(badge.name, str) self.assertIsInstance(badge.icon_url, str) self.assertIsInstance(badge.description, str)
async def get_character(bot, name, *, tries=5) -> Optional[NabChar]: """Fetches a character from TibiaData, parses and returns a Character object The character object contains all the information available on Tibia.com Information from the user's database is also added, like owner and highscores. If the character can't be fetch due to a network error, an NetworkError exception is raised If the character doesn't exist, None is returned. """ if tries == 0: raise errors.NetworkError(f"get_character({name})") try: url = Character.get_url_tibiadata(name) except UnicodeEncodeError: return None if invalid_name.search(name): return None # Fetch website try: character = CACHE_CHARACTERS[name.lower()] except KeyError: try: async with bot.session.get(url) as resp: content = await resp.text(encoding='ISO-8859-1') character = NabChar.from_tibiadata(content) except (aiohttp.ClientError, asyncio.TimeoutError, tibiapy.TibiapyException): await asyncio.sleep(config.network_retry_delay) return await get_character(bot, name, tries=tries - 1) CACHE_CHARACTERS[name.lower()] = character if character is None: return None if character.house: house_id = get_house_id(character.house.name) if house_id: character.house.id = house_id # If the character exists in the online list use data from there where possible try: for c in online_characters[character.world]: if c == character: character.level = c.level character.vocation = c.vocation break except KeyError: pass await bind_database_character(bot, character) return character
async def fetch_character(self, name): """Fetches a character by its name from Tibia.com Parameters ---------- name: :class:`str` The name of the character. Returns ------- :class:`Character` The character if found, else ``None``. Raises ------ Forbidden If a 403 Forbidden error was returned. This usually means that Tibia.com is rate-limiting the client because of too many requests. NetworkError If there's any connection errors during the request. """ content = await self._get(Character.get_url(name.strip())) char = Character.from_content(content) return char
def test_character_from_content_not_found(self): """Testing parsing a character not found page""" content = self._load_resource(FILE_CHARACTER_NOT_FOUND) char = Character.from_content(content) self.assertIsNone(char)
def test_character_from_content_unrelated(self): """Testing parsing an unrelated tibia.com section""" content = self._load_resource(self.FILE_UNRELATED_SECTION) with self.assertRaises(InvalidContent): Character.from_content(content)
def test_character_from_tibiadata_unrelated_json(self): """Testing parsing an unrelated TibiaData section""" with self.assertRaises(InvalidContent): Character.from_tibiadata( self._load_resource(tests.tests_guild.FILE_GUILD_TIBIADATA))
def test_character_from_tibiadata_invalid_json(self): """Testing parsing an invalid JSON string""" with self.assertRaises(InvalidContent): Character.from_tibiadata("<html><b>Not a json string</b></html>")
def test_character_from_tibiadata_not_found(self): """Testing parsing a not found character""" content = self._load_resource(FILE_CHARACTER_TIBIADATA_NOT_FOUND) char = Character.from_tibiadata(content) self.assertIsNone(char)