|
31 | 31 | "DisplayItem", |
32 | 32 | "DisplayMount", |
33 | 33 | "DisplayOutfit", |
| 34 | + "DisplayFamiliar", |
34 | 35 | "ItemSummary", |
35 | 36 | "ListedAuction", |
36 | 37 | "Outfits", |
37 | 38 | "OutfitImage", |
38 | 39 | "Mounts", |
| 40 | + "Familiars", |
39 | 41 | "SalesArgument", |
40 | 42 | "SkillEntry", |
41 | 43 | ) |
@@ -599,6 +601,41 @@ def _parse_image_box(cls, item_box): |
599 | 601 | return outfit |
600 | 602 |
|
601 | 603 |
|
| 604 | +class DisplayFamiliar(DisplayImage): |
| 605 | + """Represents a familiar owned or unlocked by the character. |
| 606 | +
|
| 607 | + Attributes |
| 608 | + ---------- |
| 609 | + image_url: :class:`str` |
| 610 | + The URL to the image. |
| 611 | + name: :class:`str` |
| 612 | + The familiar's name. |
| 613 | + familiar_id: :class:`int` |
| 614 | + The internal ID of the familiar. |
| 615 | + """ |
| 616 | + def __init__(self, **kwargs): |
| 617 | + super().__init__(**kwargs) |
| 618 | + self.familiar_id: int = kwargs.get("familiar_id", 0) |
| 619 | + |
| 620 | + __slots__ = ( |
| 621 | + "familiar_id", |
| 622 | + ) |
| 623 | + |
| 624 | + def __repr__(self): |
| 625 | + return f"<{self.__class__.__name__} name={self.name!r} familiar_id={self.familiar_id} " \ |
| 626 | + f"image_url={self.image_url!r}>" |
| 627 | + |
| 628 | + @classmethod |
| 629 | + def _parse_image_box(cls, item_box): |
| 630 | + familiar = super()._parse_image_box(item_box) |
| 631 | + name = familiar.name.split("(")[0].strip() |
| 632 | + familiar.name = name |
| 633 | + m = id_regex.search(familiar.image_url) |
| 634 | + if m: |
| 635 | + familiar.familiar_id = int(m.group(1)) |
| 636 | + return familiar |
| 637 | + |
| 638 | + |
602 | 639 | class ListedAuction(BaseCharacter, abc.Serializable): |
603 | 640 | """Represents an auction in the list, containing the summary. |
604 | 641 |
|
@@ -863,6 +900,8 @@ class AuctionDetails(ListedAuction): |
863 | 900 | The outfits the character has unlocked. |
864 | 901 | store_outfits: :class:`Outfits` |
865 | 902 | The outfits the character has purchased from the store. |
| 903 | + familiars: :class:`Familiars` |
| 904 | + The familiars the character has purchased or unlocked. |
866 | 905 | blessings: :class:`list` of :class:`BlessingEntry` |
867 | 906 | The blessings the character has. |
868 | 907 | imbuements: :class:`list` of :class:`str` |
@@ -953,6 +992,7 @@ def __init__(self, **kwargs): |
953 | 992 | "store_mounts", |
954 | 993 | "outfits", |
955 | 994 | "store_outfits", |
| 995 | + "familiars", |
956 | 996 | "blessings", |
957 | 997 | "imbuements", |
958 | 998 | "charms", |
@@ -1032,6 +1072,8 @@ def from_content(cls, content, auction_id=0, skip_details=False): |
1032 | 1072 | auction.outfits = Outfits._parse_table(details_tables["Outfits"]) |
1033 | 1073 | if "StoreOutfits" in details_tables: |
1034 | 1074 | auction.store_outfits = Outfits._parse_table(details_tables["StoreOutfits"]) |
| 1075 | + if "Familiars" in details_tables: |
| 1076 | + auction.familiars = Familiars._parse_table(details_tables["Familiars"]) |
1035 | 1077 | if "Blessings" in details_tables: |
1036 | 1078 | auction._parse_blessings_table(details_tables["Blessings"]) |
1037 | 1079 | if "Imbuements" in details_tables: |
@@ -1508,6 +1550,66 @@ def _parse_table(cls, table): |
1508 | 1550 | return summary |
1509 | 1551 |
|
1510 | 1552 |
|
| 1553 | +class Familiars(PaginatedSummary): |
| 1554 | + """The familiars the character has unlocked or purchased. |
| 1555 | +
|
| 1556 | + Attributes |
| 1557 | + ---------- |
| 1558 | + page: :class:`int` |
| 1559 | + The current page being displayed. |
| 1560 | + total_pages: :class:`int` |
| 1561 | + The total number of pages. |
| 1562 | + results: :class:`int` |
| 1563 | + The total number of results. |
| 1564 | + entries: :class:`list` of :class:`DisplayFamiliar` |
| 1565 | + The familiars the character has unlocked or purchased. |
| 1566 | + fully_fetched: :class:`bool` |
| 1567 | + Whether the summary was fetched completely, including all other pages. |
| 1568 | + """ |
| 1569 | + entries: List[DisplayFamiliar] |
| 1570 | + entry_class = DisplayFamiliar |
| 1571 | + |
| 1572 | + def __init__(self, **kwargs): |
| 1573 | + super().__init__(**kwargs) |
| 1574 | + |
| 1575 | + def get_by_id(self, entry_id): |
| 1576 | + """Gets an outfit by its familiar id. |
| 1577 | +
|
| 1578 | + Parameters |
| 1579 | + ---------- |
| 1580 | + entry_id: :class:`int` |
| 1581 | + The ID of the outfit. |
| 1582 | +
|
| 1583 | + Returns |
| 1584 | + ------- |
| 1585 | + :class:`DisplayOutfit` |
| 1586 | + The outfit matching the id. |
| 1587 | + """ |
| 1588 | + return next((e for e in self.entries if e.familiar_id == entry_id), None) |
| 1589 | + |
| 1590 | + @classmethod |
| 1591 | + def _parse_table(cls, table): |
| 1592 | + """Parses the outfits table. |
| 1593 | +
|
| 1594 | + Parameters |
| 1595 | + ---------- |
| 1596 | + table: :class:`bs4.Tag` |
| 1597 | + The table containing the character outfits. |
| 1598 | +
|
| 1599 | + Returns |
| 1600 | + ------- |
| 1601 | + :class:`Outfits` |
| 1602 | + The outfits contained in the table. |
| 1603 | + """ |
| 1604 | + summary = cls() |
| 1605 | + summary._parse_pagination(table) |
| 1606 | + item_boxes = table.find_all("div", attrs={"class": "CVIcon"}) |
| 1607 | + for item_box in item_boxes: |
| 1608 | + item = DisplayFamiliar._parse_image_box(item_box) |
| 1609 | + if item: |
| 1610 | + summary.entries.append(item) |
| 1611 | + return summary |
| 1612 | + |
1511 | 1613 | class Outfits(PaginatedSummary): |
1512 | 1614 | """The outfits the character has unlocked or purchased. |
1513 | 1615 |
|
|
0 commit comments