Exemple #1
0
    def parse_magnet(self, row, row_tag='<tr'):
        magnet_links = []

        def build_magnet(matches):
            if len(matches) == 2:
                return [self.magnet_template % (matches[0], matches[1])]
            return []

        if row_tag == '<tr':
            magnet_links = re.findall(r'(magnet:\?.*?&dn=.*?)[&"]', row)
            if len(magnet_links) == 0:  # lime
                matches = safe_list_get(
                    re.findall(r'\/([0-9a-zA-Z]*).torrent\?title=(.*?)"', row),
                    0, [])
                magnet_links = build_magnet(matches)

        elif row_tag == '<dl':  # torrentz2
            matches = safe_list_get(
                re.findall(r'href=\/([0-9a-zA-Z]*)>(.*?)<', row), 0, [])
            magnet_links = build_magnet(matches)

        if len(magnet_links) > 0:
            return safe_list_get(magnet_links, 0)

        return None
Exemple #2
0
    def parse_seeds(self, row):
        seeds = safe_list_get(re.findall(r'Seeders:?\s*?(\d+)', row), 0)
        if seeds == '':
            seeds = safe_list_get(re.findall(r'Seed:?\s*?(\d+)', row), 0)
        if seeds == '':
            seeds = self._parse_number(row, -2)
        if seeds == 'N/A':
            seeds = '0'

        return seeds
Exemple #3
0
    def parse_size(self, row):
        size = safe_list_get(re.findall(r'(\d+\.?\d*\s*[GM]i?B)', row), 0) \
            .replace('GiB', 'GB') \
            .replace('MiB', 'MB')

        if size == '': # bitlord
            size = self._parse_number(row, -3)
            if size is not '':
                size += ' MB'

        return size
Exemple #4
0
    def _parse_torrent(self, row, row_tag):
        magnet_link = self.parse_magnet(row, row_tag)

        if magnet_link is not None:
            torrent = lambda: None
            torrent.magnet = magnet_link
            torrent.title = safe_list_get(torrent.magnet.split('dn='), 1)
            torrent.size = self.parse_size(row)
            torrent.seeds = self.parse_seeds(row)
            return torrent

        return None
Exemple #5
0
 def _parse_number(self, row, idx):
     number = safe_list_get(re.findall(r'>\s*?(\d+)\s*?<', row)[idx:], 0)
     return number
Exemple #6
0
    def __init__(self, *, player, raw_profile_data, load_all):
        self.player = player
        self.profile_data = raw_profile_data['members'][player.uuid]
        self.id = raw_profile_data['profile_id']
        self.name = raw_profile_data['cute_name'].lower()
        self.last_save = datetime.fromtimestamp(self.profile_data.get('last_save', 0) / 1000.0)
        self.join_date = datetime.fromtimestamp(self.profile_data.get('first_join', 0) / 1000.0)
        self.purse = float(f'{self.profile_data.get("coin_purse", 0.00):.2f}')

        # Get coop members uuid and coop crafted minions if there is
        self.coop_members = []
        if len(raw_profile_data['members']) > 1:
            minions = []
            for member in raw_profile_data['members'].keys():
                minions += raw_profile_data['members'][member].get('crafted_generators', [])

                if member != player.uuid:
                    self.coop_members.append(member)
            self.minions = self._parse_collection(minions)
        else:
            self.minions = self._parse_collection(self.profile_data.get('crafted_generators', []))

        self.enabled_api = {'skills': False, 'collection': False, 'inventory': False, 'banking': False}
        self.current_armor = {'helmet': None, 'chestplate': None, 'leggings': None, 'boots': None}
        self.armor = {'helmet': None, 'chestplate': None, 'leggings': None, 'boots': None}
        self.weapon = None
        self.pet = None

        # Dungeon skill level, will be set if there is a dungeon item
        self.dungeon_skill = 0

        # Load profile's bank data if banking api is enabled
        self.bank_balance = 0.00
        self.bank_transactions = None
        if 'banking' in raw_profile_data:
            self.enabled_api['banking'] = True
            self.bank_balance = float(f'{raw_profile_data["banking"].get("balance", 0.00):.2f}')
            self.bank_transactions = raw_profile_data['banking'].get('transactions', [])

        # Loads profile's skill skills api is enabled
        self.skills_xp = {}
        self.skills = {}
        for skill in SKILL_NAMES:
            if f'experience_skill_{skill}' in self.profile_data:
                self.enabled_api['skills'] = True
                xp = int(self.profile_data.get(f'experience_skill_{skill}', 0))
                self.skills_xp[skill] = xp
                self.skills[skill] = level_from_xp_table(
                    xp,
                    RUNECRAFTING_LEVEL_REQUIREMENT if skill == 'runecrafting' else SKILL_LEVEL_REQUIREMENT
                )
        self.skill_average = sum(
            skill_level for skill, skill_level in self.skills.items() if skill not in COSMETIC_SKILL_NAMES) / (
                                     len(SKILL_NAMES) - len(COSMETIC_SKILL_NAMES))

        # Load profile's slayer data
        self.slayers_xp = {}
        self.slayers = {}
        for slayer_name in SLAYER_NAMES:
            xp = self.profile_data.get('slayer_bosses', {}).get(slayer_name, {}).get('xp', 0)
            self.slayers_xp[slayer_name] = xp
            self.slayers[slayer_name] = level_from_xp_table(xp, SLAYER_LEVEL_REQUIREMENT[slayer_name])
        self.total_slayer_xp = sum(self.slayers_xp.values())

        # Loads profile's kills and deaths
        self.kills = int(self.profile_data.get('stats', {'kills': 0}).get('kills', 0))
        self.specifc_kills = {name.replace('kills_', '').replace('_', ' '): int(amount) for name, amount in
                              self.profile_data.get('stats', {}).items() if re.match('kills_', name)}

        self.deaths = int(self.profile_data.get('stats', {'deaths': 0}).get('deaths', 0))
        self.specifc_deaths = {name.replace('deaths_', '').replace('_', ' '): int(amount) for name, amount in
                               self.profile_data.get('stats', {}).items() if re.match('deaths_', name)}

        # Loads profile's collections if collection api is enabled
        try:
            # TODO: revise to get exactly collection name instead of collection's icon name
            self.collections = {collection.lower().replace('_', ' '): amount for collection, amount in
                                self.profile_data['collection'].items()}
            self.enabled_api['collection'] = True
        except KeyError:
            self.collections = {}

        # Load profile's minion slots
        self.unlocked_collections = self._parse_collection(self.profile_data.get('unlocked_coll_tiers', []))

        self.unique_minions = sum(self.minions.values())
        self.minion_slots = level_from_xp_table(self.unique_minions, MINION_SLOT_REQUIREMENT)

        # Load profile stats
        self.stats = ProfileStats(BASE_PLAYER_STATS.copy(), profile=self)

        self.stats.combat_bonus = self.skills.get('combat', 0) * 4

        self.fairy_souls = self.profile_data.get('fairy_souls_collected', 0)
        self.stats.add_stat('health', FAIRY_SOUL_HP_BONUS[self.fairy_souls // 5])
        self.stats.add_stat('defense', self.fairy_souls // 5 + self.fairy_souls // 25)
        self.stats.add_stat('strength', self.fairy_souls // 5 + self.fairy_souls // 25)
        self.stats.add_stat('speed', self.fairy_souls // 50)

        for slayer_name, slayer_level in self.slayers.items():
            self.stats += ProfileStats(SLAYER_REWARDS[slayer_name][slayer_level])

        for skill_name, skill_level in self.skills.items():
            self.stats += ProfileStats(SKILL_REWARDS[skill_name][skill_level])

        # Load profile's current equipped armor
        for armor in self._parse_inventory(self.profile_data, ['inv_armor', 'data']):
            # check for special type
            if armor.type == 'hatccessory':
                self.current_armor['helmet'] = armor
            else:
                self.current_armor[armor.type] = armor

        # Load profile's inventories
        self.inventory = self._parse_inventory(self.profile_data, ['inv_contents', 'data'])
        self.echest = self._parse_inventory(self.profile_data, ['ender_chest_contents', 'data'])
        self.talisman_bag = self._parse_inventory(self.profile_data, ['talisman_bag', 'data'])
        # Comment out unnecessary inventories for now
        # self.candy_bag = self._parse_inventory(self.profile_raw_data, ['candy_inventory_contents', 'data'])
        # self.potion_bag = self._parse_inventory(self.profile_raw_data, ['potion_bag', 'data'])
        # self.fish_bag = self._parse_inventory(self.profile_raw_data, ['fishing_bag', 'data'])
        # self.quiver = self._parse_inventory(self.profile_raw_data, ['quiver', 'data'])
        if self.inventory or self.echest or self.talisman_bag:
            self.enabled_api['inventory'] = True

        # Load profile's weapon from inventory and ender chest
        self.weapons = [item for item in self.inventory + self.echest if item.type in ('sword', 'bow')]

        # Load profile's wardrobe
        self.wardrobe = []
        wardrobe = self._parse_inventory(self.profile_data, ['wardrobe_contents', 'data'], index_empty=True)
        for wardrobe_page in range(0, 2 * 36, 36):  # 2 for current max 2 pages of wardrobe
            for i in range(wardrobe_page, wardrobe_page + 9):
                armor_set = {
                    'helmet': safe_list_get(wardrobe, i),
                    'chestplate': safe_list_get(wardrobe, i + 9),
                    'leggings': safe_list_get(wardrobe, i + 18),
                    'boots': safe_list_get(wardrobe, i + 27)
                }
                if all(item is None for item in armor_set.values()):
                    continue
                self.wardrobe.append(armor_set)

        # Check if player has dungeon armor/wep items
        self.has_dungeon_items = False
        for item in self.inventory + self.echest + wardrobe:
            if not item:
                continue
            if item.dungeon:
                self.has_dungeon_items = True
                break

        self.loaded_all = load_all
        if load_all:
            # Load profile's talismans from inventory + talisman bag and talisman counts
            self.talismans = [talisman for talisman in self.inventory + self.talisman_bag if
                              talisman.type in ('accessory', 'hatccessory')]
            self.talisman_counts = {'common': 0, 'uncommon': 0, 'rare': 0, 'epic': 0, 'legendary': 0, 'mythic': 0}
            talismans_dup = []

            for talisman in self.talismans:
                talisman.active = True
                # Check for talisman families
                if talisman.internal_name in TIERED_TALISMANS:
                    for other_fam_member in TIERED_TALISMANS[talisman.internal_name]:
                        if other_fam_member in self.talismans:
                            talisman.active = False
                            break

                if not talisman.active:
                    continue  # if talisman active already set to false due to families
                # Check for duplicate talismans
                if self.talismans.count(talisman) > 1:
                    talisman.active = False
                    if talisman not in talismans_dup:
                        talismans_dup.append(talisman)  # append the reference to a list to set active true later

            # Set one of the talisman dup to active true
            for talisman in talismans_dup:
                talisman.active = True

            # Load talisman stats
            self.stats.childrens.extend([talisman.stats for talisman in self.talismans if talisman.active])

            # Load talisman counts
            for taliman in self.talismans:
                if taliman.active:
                    # Check for hypixel language because it's most reliable here
                    try:
                        self.talisman_counts[taliman.rarity] += 1
                    except KeyError:
                        raise HypixelLanguageError from None

            # Loads profile's pets
            self.pets = []
            if 'pets' in self.profile_data:
                for pet_data in self.profile_data['pets']:
                    self.pets.append(Pet(pet_data, profile=self))