Example #1
0
    def _parse_current_war_information(cls, text):
        """Parse the guild's current war information.

        Parameters
        ----------
        text: :class:`str`
            The text describing the current war's information.

        Returns
        -------
        :class:`GuildWarEntry`
            The guild's war entry for the current war.
        """
        text = text.replace('\xa0', ' ').strip()
        names_match = war_guilds_regegx.search(text)
        guild_name, opposing_name = names_match.groups()
        scores_match = war_score_regex.findall(text)
        guild_score, opposing_score = scores_match
        fee_match = war_fee_regex.findall(text)
        guild_fee, opposing_fee = fee_match

        score_limit_match = war_score_limit_regex.search(text)
        score_limit = score_limit_match.group(1)

        end_date_match = war_end_regex.search(text)
        end_date_str = end_date_match.group(1)
        end_date = parse_tibia_date(end_date_str)

        return GuildWarEntry(guild_name=guild_name, opponent_name=opposing_name, guild_score=int(guild_score),
                             opponent_score=int(opposing_score), guild_fee=int(guild_fee),
                             opponent_fee=int(opposing_fee), score_limit=int(score_limit), end_date=end_date)
Example #2
0
    def _parse_guild_guildhall(self, info_container):
        """
        Parse the guild's guildhall info.

        Parameters
        ----------
        info_container: :class:`bs4.Tag`
            The parsed content of the information container.
        """
        m = guildhall_regex.search(info_container.text)
        if m:
            paid_until = parse_tibia_date(m.group("date").replace("\xa0", " "))
            self.guildhall = GuildHouse(m.group("name"), self.world, paid_until_date=paid_until)
Example #3
0
    def _parse_guild_disband_info(self, info_container):
        """
        Parse the guild's disband info, if available.

        Parameters
        ----------
        info_container: :class:`bs4.Tag`
            The parsed content of the information container.
        """
        m = disband_regex.search(info_container.text)
        if m:
            self.disband_condition = m.group(2)
            self.disband_date = parse_tibia_date(m.group(1).replace("\xa0", " "))
Example #4
0
    def _parse_guild_info(self, info_container):
        """
        Parse the guild's general information and applies the found values.

        Parameters
        ----------
        info_container: :class:`bs4.Tag`
            The parsed content of the information container.
        """
        m = founded_regex.search(info_container.text)
        if m:
            description = m.group("desc").strip()
            self.description = description if description else None
            self.world = m.group("world")
            self.founded = parse_tibia_date(m.group("date").replace("\xa0", " "))
            self.active = "currently active" in m.group("status")
Example #5
0
 def _parse_entry(cls, cols_raw):
     img = cols_raw[0].find('img')
     img_url = img["src"]
     category_name = ICON_PATTERN.search(img_url)
     category = try_enum(NewsCategory, category_name.group(1))
     for br in cols_raw[1].find_all("br"):
         br.replace_with("\n")
     date_str, news_type_str = cols_raw[1].text.splitlines()
     date = parse_tibia_date(date_str)
     news_type_str = news_type_str.replace('\xa0', ' ')
     news_type = try_enum(NewsType, news_type_str)
     title = cols_raw[2].text
     news_link = cols_raw[2].find('a')
     url = urllib.parse.urlparse(news_link["href"])
     query = urllib.parse.parse_qs(url.query)
     news_id = int(query["id"][0])
     return cls(news_id,
                title,
                news_type,
                category,
                date,
                category_icon=img_url)
Example #6
0
 def test_parse_tibia_date_invalid(self):
     date = utils.parse_tibia_date(TIBIA_DATETIME_INVALID)
     self.assertIsNone(date)
Example #7
0
 def test_parse_tibia_date(self):
     date = utils.parse_tibia_date(TIBIA_DATE)
     self.assertIsInstance(date, datetime.date)
     self.assertEqual(date.month, 6)
     self.assertEqual(date.day, 20)
     self.assertEqual(date.year, 2018)
Example #8
0
    def _parse_war_history_entry(cls, text):
        """Parses a guild's war information.

        Parameters
        ----------
        text: :class:`str`
            The text describing the war's information.

        Returns
        -------
        :class:`GuildWarEntry`
            The guild's war entry described in the text..
        """
        text = text.replace('\xa0', ' ').strip()
        header_match = war_history_header_regex.search(text)
        guild_name, opposing_name = header_match.groups()
        if "disbanded guild" in opposing_name:
            opposing_name = None
        start_duration_match = war_start_duration_regex.search(text)
        start_str, duration_str = start_duration_match.groups()
        start_date = parse_tibia_date(start_str)
        duration = datetime.timedelta(days=int(duration_str))
        kills_match = kills_needed_regex.search(text)
        kills_needed = int(kills_match.group(1))
        fee_match = war_history_fee_regex.search(text)
        guild_fee, opponent_fee = fee_match.groups()
        winner = None
        surrender = False
        end_date = None
        guild_score = opponent_score = 0
        surrender_match = surrender_regex.search(text)
        if surrender_match:
            surrending_guild = surrender_match.group(1)
            end_date = parse_tibia_date(surrender_match.group(2))
            winner = guild_name if surrending_guild != guild_name else opposing_name
            surrender = True

        war_score_match = war_score_regex.findall(text)
        if war_score_match and len(war_score_match) == 2:
            guild_score, opponent_score = war_score_match
            guild_score = int(guild_score)
            opponent_score = int(guild_score)

        war_end_match = war_ended_regex.search(text)
        if war_end_match:
            end_date = parse_tibia_date(war_end_match.group(1))
            winning_guild = war_end_match.group(2)
            if "disbanded guild" in winning_guild:
                winning_guild = None
            winner = guild_name if winning_guild == guild_name else opposing_name
            loser_score_match = war_score_end_regex.search(text)
            loser_score = int(
                loser_score_match.group(1)) if loser_score_match else 0
            guild_score = kills_needed if guild_name == winner else loser_score
            opponent_score = kills_needed if guild_name != winner else loser_score

        if "no guild had reached the needed kills" in text:
            winner = guild_name if guild_score > opponent_score else opposing_name

        entry = GuildWarEntry(guild_name=guild_name,
                              opponent_name=opposing_name,
                              start_date=start_date,
                              duration=duration,
                              score_limit=kills_needed,
                              guild_fee=int(guild_fee),
                              opponent_fee=int(opponent_fee),
                              surrender=surrender,
                              winner=winner,
                              end_date=end_date,
                              opponent_score=opponent_score,
                              guild_score=guild_score)
        return entry
Example #9
0
    def _parse_character_information(self, rows):
        """
        Parses the character's basic information and applies the found values.

        Parameters
        ----------
        rows: :class:`list` of :class:`bs4.Tag`
            A list of all rows contained in the table.
        """
        int_rows = ["level", "achievement_points"]
        char = {}
        houses = []
        for row in rows:
            cols_raw = row.find_all('td')
            cols = [ele.text.strip() for ele in cols_raw]
            field, value = cols
            field = field.replace("\xa0",
                                  "_").replace(" ", "_").replace(":",
                                                                 "").lower()
            value = value.replace("\xa0", " ")
            # This is a special case cause we need to see the link
            if field == "house":
                house_text = value
                paid_until = house_regexp.search(house_text).group(1)
                paid_until_date = parse_tibia_date(paid_until)
                house_link = cols_raw[1].find('a')
                url = urllib.parse.urlparse(house_link["href"])
                query = urllib.parse.parse_qs(url.query)
                houses.append({
                    "id": int(query["houseid"][0]),
                    "name": house_link.text.strip(),
                    "town": query["town"][0],
                    "paid_until": paid_until_date
                })
                continue
            if field in int_rows:
                value = int(value)
            char[field] = value

        # If the character is deleted, the information is fouund with the name, so we must clean it
        m = deleted_regexp.match(char["name"])
        if m:
            char["name"] = m.group(1)
            char["deletion_date"] = parse_tibia_datetime(m.group(2))
        if "guild_membership" in char:
            m = guild_regexp.match(char["guild_membership"])
            char["guild_membership"] = GuildMembership(m.group(2), m.group(1))

        if "(traded)" in char["name"]:
            char["name"] = char["name"].replace("(traded)", "").strip()
            char["traded"] = True

        if "former_names" in char:
            former_names = [
                fn.strip() for fn in char["former_names"].split(",")
            ]
            char["former_names"] = former_names

        if "never" in char["last_login"]:
            char["last_login"] = None
        else:
            char["last_login"] = parse_tibia_datetime(char["last_login"])

        m = title_regexp.match(char.get("title", ""))
        if m:
            name = m.group(1).strip()
            unlocked = int(m.group(2))
            if name == "None":
                name = None
            char["title"] = name
            char["unlocked_titles"] = unlocked

        char["vocation"] = try_enum(Vocation, char["vocation"])
        char["sex"] = try_enum(Sex, char["sex"])
        char["account_status"] = try_enum(AccountStatus,
                                          char["account_status"])

        for k, v in char.items():
            try:
                setattr(self, k, v)
            except AttributeError:
                # This means that there is a attribute in the character's information table that does not have a
                # corresponding class attribute.
                pass
        self.houses = [
            CharacterHouse(h["id"], h["name"], self.world, h["town"],
                           self.name, h["paid_until"]) for h in houses
        ]
Example #10
0
    def from_content(cls, content, news_id=0):
        """
        Gets a news entry by its HTML content from Tibia.com

        Notes
        -----
        Since there's no way to obtain the entry's Id from the page contents, it will always be 0.
        A news_id can be passed to set the news_id of the resulting object.

        Parameters
        ----------
        content: :class:`str`
            The HTML content of the page.
        news_id: :class:`int`, optional
            The news_id belonging to the content being parsed.

        Returns
        -------
        :class:`News`
            The news article found in the page.

        Raises
        ------
        InvalidContent
            If content is not the HTML of a news' page.
        """
        if "(no news with id " in content:
            return None
        try:
            parsed_content = parse_tibiacom_content(content)
            # Read Information from the headline
            headline = parsed_content.find("div",
                                           attrs={"class": "NewsHeadline"})
            img = headline.find('img')
            img_url = img["src"]
            category_name = ICON_PATTERN.search(img_url)
            category = try_enum(NewsCategory, category_name.group(1))
            title_div = headline.find("div",
                                      attrs={"class": "NewsHeadlineText"})
            title = title_div.text.replace('\xa0', ' ')
            date_div = headline.find("div",
                                     attrs={"class": "NewsHeadlineDate"})
            date_str = date_div.text.replace('\xa0', ' ').replace('-',
                                                                  '').strip()
            date = parse_tibia_date(date_str)

            # Read the page's content.
            content_table = parsed_content.find("table")
            content_row = content_table.find("td")
            content = content_row.encode_contents().decode()
            thread_id = None
            thread_div = content_table.find("div")
            if thread_div:
                news_link = thread_div.find('a')
                url = urllib.parse.urlparse(news_link["href"])
                query = urllib.parse.parse_qs(url.query)
                thread_id = int(query["threadid"][0])

            return cls(news_id,
                       title,
                       content,
                       date,
                       category,
                       thread_id=thread_id,
                       category_icon=img_url)
        except AttributeError:
            raise InvalidContent(
                "content is not from the news archive section in Tibia.com")