Skip to content

Commit

Permalink
v0.1.15.1 - get_lot_page корректно відображає продавця, якщо продавец…
Browse files Browse the repository at this point in the history
…ь - це ми;

об'єкт відгука має інформацію про те, чи залишений відгук та відповідь на відгук ботом,
об'єкт LotFields має інформацію про валюту, розділ, публічне та приватне посилання на лот
об'єкт повідомлення має інформацію про те, що це автовідповідь
бот не буде намагатися змінти назву консолі, якщо ОС - не Windows
@username має починатися з FunPay
Старий режим отримання повідомлень може маркувати повідомлення, що відправлені через кардинал
  • Loading branch information
sidor0912 committed Nov 30, 2024
1 parent 5f38d82 commit cf255ee
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 59 deletions.
44 changes: 37 additions & 7 deletions FunPayAPI/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,14 @@ def get_lot_page(self, lot_id: int, locale: Literal["ru", "en", "uk"] | None = N
return None

subcategory_id = int(parser.find("a", class_="js-back-link")['href'].split("/")[-2])

seller = parser.find("div", class_="media-user-name").find("a")
seller_id = int(seller["href"].split("/")[-2])
seller_username = seller.text
chat_header = parser.find("div", class_="chat-header")
if chat_header:
seller = chat_header.find("div", class_="media-user-name").find("a")
seller_id = int(seller["href"].split("/")[-2])
seller_username = seller.text
else:
seller_id = self.id
seller_username = self.username

short_description = None
detailed_description = None
Expand Down Expand Up @@ -663,7 +667,7 @@ def send_message(self, chat_id: int | str, text: Optional[str] = None, chat_name
message_obj = types.Message(int(mes["id"]), message_text, chat_id, chat_name, self.username, self.id,
mes["html"], image_link, image_name)
if self.runner and isinstance(chat_id, int):
if add_to_ignore_list:
if add_to_ignore_list and message_obj.id:
self.runner.mark_as_by_bot(chat_id, message_obj.id)
if update_last_saved_message:
self.runner.update_last_message(chat_id, message_obj.id, message_obj.text)
Expand Down Expand Up @@ -1193,7 +1197,8 @@ def get_order(self, order_id: str, locale: Literal["ru", "en", "uk"] | None = No
review = None
else:
review = types.Review(stars, text, reply, False, str(review_obj), hidden, order_id, buyer_username,
buyer_id)
buyer_id, bool(text and text.endswith(self.bot_character)),
bool(reply and reply.endswith(self.bot_character)))
order = types.Order(order_id, status, subcategory, params, short_description, full_description, sum_, currency,
buyer_id, buyer_username, seller_id, seller_username, chat_id, html_response, review,
order_secrets)
Expand Down Expand Up @@ -1437,7 +1442,21 @@ def request_chats(self) -> list[types.ChatShortcut]:
last_msg_text = msg.find("div", {"class": "contact-item-message"}).text
unread = True if "unread" in msg.get("class") else False
chat_with = msg.find("div", {"class": "media-user-name"}).text

by_bot = False
by_vertex = False
is_image = last_msg_text in ("Изображение", "Зображення", "Image")
if last_msg_text.startswith(self.bot_character):
last_msg_text = last_msg_text[1:]
by_bot = True
elif last_msg_text.startswith(self.old_bot_character):
last_msg_text = last_msg_text[1:]
by_vertex = True
chat_obj = types.ChatShortcut(chat_id, chat_with, last_msg_text, unread, str(msg))
if not is_image:
chat_obj.last_by_bot = by_bot
chat_obj.last_by_vertex = by_vertex

chats_objs.append(chat_obj)
return chats_objs

Expand Down Expand Up @@ -1567,7 +1586,11 @@ def get_lot_fields(self, lot_id: int) -> types.LotFields:
"hidden" not in field.find_parent(class_="form-group").get("class", [])
})
result.update({field["name"]: "on" for field in bs.find_all("input", {"type": "checkbox"}, checked=True)})
return types.LotFields(lot_id, result)
subcategory = self.get_subcategory(enums.SubCategoryTypes.COMMON, int(result.get("node_id", 0)))
currency = utils.parse_currency(bs.find("span", class_="form-control-feedback").text)
if self.currency != currency:
self.currency = currency
return types.LotFields(lot_id, result, subcategory, currency)

def save_lot(self, lot_fields: types.LotFields):
"""
Expand Down Expand Up @@ -1816,6 +1839,9 @@ def __parse_messages(self, json_messages: dict, chat_id: int | str,
default_label = parser.find("div", {"class": "media-user-name"})
default_label = default_label.find("span", {
"class": "chat-msg-author-label label label-default"}) if default_label else None
if default_label:
if default_label.text in ("автовідповідь", "автоответ", "auto-reply"):
i.is_autoreply = True
i.badge = default_label.text if (i.badge is None and default_label is not None) else i.badge
if i.type != types.MessageTypes.NON_SYSTEM:
users = parser.find_all('a', href=lambda href: href and '/users/' in href)
Expand Down Expand Up @@ -1867,6 +1893,10 @@ def chat_id_private(chat_id: int | str):
def bot_character(self) -> str:
return self.__bot_character

@property
def old_bot_character(self) -> str:
return self.__old_bot_character

@property
def locale(self) -> Literal["ru", "en", "uk"] | None:
return self.__locale
Expand Down
93 changes: 68 additions & 25 deletions FunPayAPI/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ def __init__(self, id_: int, name: str, last_message_text: str,
"""Название чата (никнейм собеседника)."""
self.last_message_text: str = last_message_text
"""Текст последнего сообщения в чате (макс. 250 символов)."""
self.last_by_bot: bool | None = None
"""Отправлено ли последнее сообщение ботом?"""
self.last_by_vertex: bool | None = None
"""Отпралено ли последнее сообщение через Vertex?"""
self.unread: bool = unread
"""Флаг \"непрочитанности\" (если True - в чате есть непрочитанные сообщения)."""
self.last_message_type: MessageTypes | None = None if not determine_msg_type else self.get_last_message_type()
Expand Down Expand Up @@ -212,17 +216,27 @@ def __init__(self, id_: int, text: str | None, chat_id: int | str, chat_name: st
self.by_bot: bool = False
"""Отправлено ли сообщение с помощью :meth:`FunPayAPI.Account.send_message`?"""
self.by_vertex: bool = False
"""Отправлено ли сообщение через FunPay Vertex"""
"""Отправлено ли сообщение через FunPay Vertex?"""
self.badge: str | None = badge_text
"""Текст бэйджика тех. поддержки или автовыдачи FunPay."""
self.is_employee = False
self.is_support = False
self.is_moderation = False
self.is_arbitration = False
self.initiator_username = None
self.initiator_id = None
self.i_am_seller = None
self.i_am_buyer = None
self.is_employee: bool = False
"""Является ли пользователь сотрудником?"""
self.is_support: bool = False
"""Наличие бэйджика поддержки."""
self.is_moderation: bool = False
"""Наличие бэйджика модерации."""
self.is_arbitration: bool = False
"""Наличие бэйджика арбитража."""
self.is_autoreply: bool = False
"""Наличие бэйджика автоответа."""
self.initiator_username: str | None = None
"""Ник пользователя, который выполнил действие (для системных сообщений)."""
self.initiator_id: int | None = None
"""ID пользователя, который выполнил действие (для системных сообщений)."""
self.i_am_seller: bool | None = None
"""Являемся ли мы продавцом по заказу (для системных сообщений)."""
self.i_am_buyer: bool | None = None
"""Являемся ли мы покупателем по заказу (для системных сообщений)."""

BaseOrderInfo.__init__(self)

Expand Down Expand Up @@ -313,6 +327,9 @@ class OrderShortcut(BaseOrderInfo):
:param subcategory_name: название подкатегории, к которой относится заказ.
:type subcategory_name: :obj:`str`
:param subcategory: подкатегория, к которой относится заказ.
:type subcategory: :class:`FunPayAPI.types.SubCategory` or :obj:`None`
:param html: HTML код виджета заказа.
:type html: :obj:`str`
Expand Down Expand Up @@ -347,7 +364,7 @@ def __init__(self, id_: str, description: str, price: float, currency: Currency,
self.subcategory_name: str = subcategory_name
"""Название подкатегории, к которой относится заказ."""
self.subcategory: SubCategory | None = subcategory
"""Подкатегория, к которой относится заказ или None, если определить не удалось."""
"""Подкатегория, к которой относится заказ."""
self.html: str = html
"""HTML код виджета заказа."""
BaseOrderInfo.__init__(self)
Expand Down Expand Up @@ -380,7 +397,7 @@ class Order:
:type status: :class:`FunPayAPI.common.enums.OrderStatuses`
:param subcategory: подкатегория, к которой относится заказ.
:type subcategory: :class:`FunPayAPI.types.SubCategory`
:type subcategory: :class:`FunPayAPI.types.SubCategory` or :obj:`None`
:param params: параметры лота (значения некоторых полей заказа).
:type params: :obj:`str` or :obj:`None`
Expand Down Expand Up @@ -422,7 +439,7 @@ class Order:
:type order_secrets: :obj:`list` of :obj:`str`
"""

def __init__(self, id_: str, status: OrderStatuses, subcategory: SubCategory, params: str | None,
def __init__(self, id_: str, status: OrderStatuses, subcategory: SubCategory | None, params: str | None,
short_description: str | None,
full_description: str | None, sum_: float, currency: Currency,
buyer_id: int, buyer_username: str,
Expand All @@ -432,7 +449,7 @@ def __init__(self, id_: str, status: OrderStatuses, subcategory: SubCategory, pa
"""ID заказа."""
self.status: OrderStatuses = status
"""Статус заказа."""
self.subcategory: SubCategory = subcategory
self.subcategory: SubCategory | None = subcategory
"""Подкатегория, к которой относится заказ."""
self.params: str | None = params
"""Параметры лота (значения некоторых полей заказа)"""
Expand Down Expand Up @@ -584,9 +601,16 @@ class LotFields:
:param fields: словарь с полями.
:type fields: :obj:`dict`
:param subcategory: подкатегория, к которой относится лот.
:type subcategory: :class:`FunPayAPI.types.SubCategory` or :obj:`None`
:param currency: валюта лота.
:type currency: :class:`FunPayAPI.common.enums.Currency`
"""

def __init__(self, lot_id: int, fields: dict):
def __init__(self, lot_id: int, fields: dict, subcategory: SubCategory | None = None,
currency: Currency = Currency.UNKNOWN):
self.lot_id: int = lot_id
"""ID лота."""
self.__fields: dict = fields
Expand Down Expand Up @@ -618,6 +642,14 @@ def __init__(self, lot_id: int, fields: dict):
"""Активен ли лот."""
self.deactivate_after_sale: bool = self.__fields.get("deactivate_after_sale") == "on"
"""Деактивировать ли лот после продажи."""
self.subcategory: SubCategory | None = subcategory
"""Подкатегория лота"""
self.public_link: str = f"https://funpay.com/lots/offer?id={lot_id}"
"""Публичная ссылка на лот."""
self.private_link: str = f"https://funpay.com/lots/offerEdit?offer={lot_id}"
"""Приватная ссылка на лот (на изменение лота)."""
self.currency: Currency = currency
"""Валюта лота."""

@property
def fields(self) -> dict[str, str]:
Expand Down Expand Up @@ -681,7 +713,7 @@ class LotPage:
:type lot_id: :obj:`int`
:param subcategory: Подкатегория, к которой относится лот.
:type subcategory: :obj:`types.SubCategory`
:type subcategory: :obj:`types.SubCategory` or :obj:`None`
:param short_description: Краткое описание лота.
:type short_description: :obj:`str` or None
Expand All @@ -699,11 +731,11 @@ class LotPage:
:type seller_username: :obj:`str`
"""

def __init__(self, lot_id: int, subcategory: SubCategory, short_description: str | None,
def __init__(self, lot_id: int, subcategory: SubCategory | None, short_description: str | None,
full_description: str | None, image_urls: list[str], seller_id: int, seller_username: str, ) -> None:
self.lot_id: int = lot_id
"""ID лота"""
self.subcategory: SubCategory = subcategory
self.subcategory: SubCategory | None = subcategory
"""Подкатегория"""
self.short_description: str | None = short_description
"""Краткое описание"""
Expand Down Expand Up @@ -775,7 +807,7 @@ class LotShortcut:

def __init__(self, id_: int | str, server: str | None,
description: str | None, amount: int | None, price: float, currency: Currency,
subcategory: SubCategory,
subcategory: SubCategory | None,
seller: SellerShortcut | None, auto: bool, promo: bool | None, attributes: dict[str, int | str] | None,
html: str):
self.id: int | str = id_
Expand Down Expand Up @@ -984,10 +1016,17 @@ class Review:
:param author_id: ID автора отзыва.
:type author_id: :obj:`int` or :obj:`None`, опционально
:param by_bot: оставлен ли отзыв ботом?
:type by_bot: :obj:`bool`
:param reply_by_bot: оставлен ли ответ на отзыв ботом?
:type reply_by_bot: :obj:`bool`
"""

def __init__(self, stars: int | None, text: str | None, reply: str | None, anonymous: bool, html: str, hidden: bool,
order_id: str | None = None, author: str | None = None, author_id: int | None = None):
order_id: str | None = None, author: str | None = None, author_id: int | None = None,
by_bot: bool = False, reply_by_bot: bool = False):
self.stars: int | None = stars
"""Кол-во звезде в отзыве."""
self.text: str | None = text
Expand All @@ -1006,6 +1045,10 @@ def __init__(self, stars: int | None, text: str | None, reply: str | None, anony
"""Автор отзыва."""
self.author_id: int | None = author_id
"""ID автора отзыва."""
self.by_bot: bool = by_bot
"""Оставлен ли отзыв ботом?"""
self.reply_by_bot: bool = reply_by_bot
"""Оставлен ли ответ на отзыв ботом?"""


class Balance:
Expand Down Expand Up @@ -1062,7 +1105,7 @@ class CalcResult:
"""Класс, описывающий ответ на запрос о рассчете комиссии раздела."""

def __init__(self, subcategory_type: SubCategoryTypes, subcategory_id: int, methods: list[PaymentMethod],
price: float, min_price_with_commission: float, min_price_currency: Currency,
price: float, min_price_with_commission: float | None, min_price_currency: Currency,
account_currency: Currency):
self.subcategory_type: SubCategoryTypes = subcategory_type
"""Тип подкатегории."""
Expand All @@ -1072,16 +1115,16 @@ def __init__(self, subcategory_type: SubCategoryTypes, subcategory_id: int, meth
"""Список платежных средств."""
self.price: float = price
"""Цена без комиссии"""
self.min_price_with_commission: float = min_price_with_commission
self.min_price_with_commission: float | None = min_price_with_commission
"""Минимальная цена с комиссией из ответа FunPay, наличие не обязательно."""
self.min_price_currency: Currency = min_price_currency
"""Валюта минимальной цены"""
self.account_currency = account_currency
"""Валюта аккаунта"""

@property
def commission_coefficient(self) -> float:
"""Отношение цены с комиссией к цене без комиссии или None, если рассчитать не удалось."""
def commission_coefficient(self) -> float | None:
"""Отношение цены с комиссией к цене без комиссии."""
if self.min_price_with_commission:
return self.min_price_with_commission / self.price
else:
Expand All @@ -1090,6 +1133,6 @@ def commission_coefficient(self) -> float:
return None if not res else res.price / self.price

@property
def commission_percent(self) -> float:
"""Процент комиссии или None, если рассчитать не удалось."""
def commission_percent(self) -> float | None:
"""Процент комиссии."""
return (self.commission_coefficient - 1) * 100
Loading

0 comments on commit cf255ee

Please sign in to comment.