diff --git a/locales/eng.py b/locales/eng.py index 7c3d6a3..3344cc8 100644 --- a/locales/eng.py +++ b/locales/eng.py @@ -398,6 +398,7 @@ cmd_logs = "download current log-file" cmd_del_logs = "delete old log-files" cmd_about = "about current version" +cmd_old_orders = "sends a list of open orders that are more than 24 hours old" cmd_sys = "system load information" cmd_restart = "restart FPV" cmd_power_off = "shutdown FPV" diff --git a/locales/ru.py b/locales/ru.py index d3cd3fd..d0a719b 100644 --- a/locales/ru.py +++ b/locales/ru.py @@ -400,6 +400,7 @@ cmd_logs = "загрузить текущий лог-файл" cmd_del_logs = "удалить старые лог-файлы" cmd_about = "об текущей версии" +cmd_old_orders = "отправляет список открытых заказов, которым более 24 часов" cmd_sys = "информация о нагрузке на систему" cmd_restart = "перезапустить FPV" cmd_power_off = "выключить FPV" diff --git a/main.py b/main.py index 23e78a3..80a01c5 100644 --- a/main.py +++ b/main.py @@ -27,7 +27,7 @@ ╚═══╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝{Style.RESET_ALL} """ -VERSION = "0.1.3" +VERSION = "0.1.4" if getattr(sys, 'frozen', False): os.chdir(os.path.dirname(sys.executable)) diff --git a/tg_bot/bot.py b/tg_bot/bot.py index 56fd5ba..16c1da7 100644 --- a/tg_bot/bot.py +++ b/tg_bot/bot.py @@ -14,8 +14,8 @@ import psutil import telebot import logging - -from FunPayAPI.account import Account +import json +from os.path import exists from telebot.types import InlineKeyboardMarkup as K, InlineKeyboardButton as B, Message, CallbackQuery, BotCommand, ReplyKeyboardRemove from tg_bot import utils, static_keyboards as skb, keyboards as kb, CBT from Utils import vertex_tools @@ -74,6 +74,7 @@ def __init__(self, vertex: Vertex): "del_logs": _("cmd_del_logs"), "about": _("cmd_about"), "sys": _("cmd_sys"), + "old_orders": _("cmd_old_orders"), "keyboard": _("cmd_keyboard"), "restart": _("cmd_restart"), "power_off": _("cmd_power_off") @@ -297,33 +298,92 @@ def send_settings_menu(self, m: Message): """ Отправляет основное меню настроек (новым сообщением). """ + self.vertex.account.get() + self.vertex.balance = self.vertex.get_balance() self.bot.send_message(m.chat.id, _("desc_main"), reply_markup=kb.settings_sections(self.vertex)) def send_profile(self, m: Message): """ Отправляет статистику аккаунта. """ - new_msg = self.bot.send_message(m.chat.id, "Получаю статистику аккаунта (это может занять некоторое время)...") + new_msg = self.bot.send_message(m.chat.id, _("updating_profile")) try: - self.bot.edit_message_text(text=utils.generate_adv_profile(self.vertex.account), message_id=new_msg.id, chat_id=new_msg.chat.id, reply_markup=telebot.types.InlineKeyboardMarkup().add(telebot.types.InlineKeyboardButton("🔄 Обновить", callback_data="adv_profile_1"))) + self.vertex.account.get() + self.vertex.balance = self.vertex.get_balance() + self.bot.send_message(m.chat.id, utils.generate_profile_text(self.vertex), + reply_markup=telebot.types.InlineKeyboardMarkup() + .add(telebot.types.InlineKeyboardButton("🔄 Обновить", callback_data="update_profile")) + .add(telebot.types.InlineKeyboardButton("▶️ Еще", callback_data="update_adv_profile")) + ) + self.bot.delete_message(new_msg.chat.id, new_msg.id) except: - self.bot.edit_message_text(text="❌ Не удалось обновить статистику аккаунта.", message_id=new_msg.chat.id, chat_id=new_msg.id) + self.bot.edit_message_text(_("profile_updating_error"), new_msg.chat.id, new_msg.id) logger.debug("TRACEBACK", exc_info=True) + self.bot.answer_callback_query(m.id) return - + def update_profile(self, c: CallbackQuery): """ - Отправляет статистику аккаунта. + Обновляет статистику аккаунта. """ - self.bot.edit_message_reply_markup(message_id=c.message.id, chat_id=c.message.chat.id, reply_markup=None) - self.bot.edit_message_text(text="Обновляю статистику аккаунта (это может занять некоторое время)...", message_id=c.message.id, chat_id=c.message.chat.id) + new_msg = self.bot.send_message(c.message.chat.id, _("updating_profile")) try: - self.bot.edit_message_text(text=utils.generate_adv_profile(self.vertex.account), message_id=c.message.id, chat_id=c.message.chat.id, reply_markup=telebot.types.InlineKeyboardMarkup().add(telebot.types.InlineKeyboardButton("🔄 Обновить", callback_data="adv_profile_1"))) + self.vertex.account.get() + self.vertex.balance = self.vertex.get_balance() + self.bot.edit_message_text(utils.generate_profile_text(self.vertex), c.message.chat.id, + c.message.id, + reply_markup=telebot.types.InlineKeyboardMarkup() + .add(telebot.types.InlineKeyboardButton("🔄 Обновить", callback_data="update_profile")) + .add(telebot.types.InlineKeyboardButton("▶️ Еще", callback_data="update_adv_profile")) + ) + self.bot.delete_message(new_msg.chat.id, new_msg.id) except: - self.bot.edit_message_text(text="❌ Не удалось обновить статистику аккаунта.", message_id=c.message.id, chat_id=c.message.chat.id) + self.bot.edit_message_text(_("profile_updating_error"), new_msg.chat.id, new_msg.id) logger.debug("TRACEBACK", exc_info=True) + self.bot.answer_callback_query(c.id) return + + + def update_adv_profile(self, c: CallbackQuery): + """ + Обновляет дополнительную статистику аккаунта. + """ + new_msg = self.bot.send_message(c.message.chat.id, _("updating_profile")) + try: + self.vertex.account.get() + self.vertex.balance = self.vertex.get_balance() + self.bot.edit_message_text(utils.generate_adv_profile(self.vertex.account), c.message.chat.id, + c.message.id, + reply_markup=telebot.types.InlineKeyboardMarkup() + .add(telebot.types.InlineKeyboardButton("🔄 Обновить", callback_data="update_adv_profile")) + .add(telebot.types.InlineKeyboardButton("◀️ Назад", callback_data="update_profile")) + ) + self.bot.delete_message(new_msg.chat.id, new_msg.id) + except: + self.bot.edit_message_text(_("profile_updating_error"), new_msg.chat.id, new_msg.id) + logger.debug("TRACEBACK", exc_info=True) + self.bot.answer_callback_query(c.id) + return + + def send_orders(self, m: telebot.types.Message): + new_mes = self.bot.send_message(m.chat.id, "Сканирую заказы (это может занять какое-то время)...") + try: + orders = utils.get_all_old_orders(self.vertex.account) + except: + self.bot.edit_message_text("❌ Не удалось получить список заказов.", new_mes.chat.id, new_mes.id) + logger.debug("TRACEBACK", exc_info=True) + return + + if not orders: + self.bot.edit_message_text("❌ Просроченных заказов нет.", new_mes.chat.id, new_mes.id) + logger.debug("TRACEBACK", exc_info=True) + return + + orders_text = ", ".join(orders) + text = f"Здравствуйте!\n\nПрошу подтвердить выполнение следующих заказов:\n{orders_text}\n\nЗаранее благодарю,\nС уважением." + self.bot.edit_message_text(f"{utils.escape(text)}", new_mes.chat.id, new_mes.id) + def act_manual_delivery_test(self, m: Message): """ Активирует режим ввода названия лота для ручной генерации ключа теста автовыдачи. @@ -896,8 +956,6 @@ def switch_lang(self, c: CallbackQuery): "Thank you :)", show_alert=True) self.open_cp(c) - - def open_keyboard(self, m: Message): self.bot.send_message(m.chat.id, "Клавиатура появилась!", reply_markup=skb.OLD_KEYBOARD) @@ -915,8 +973,10 @@ def __register_handlers(self): self.msg_handler(self.run_file_handlers, content_types=["photo", "document"], func=lambda m: self.is_file_handler(m)) self.msg_handler(self.send_settings_menu, commands=["menu"]) - self.cbq_handler(self.update_profile, lambda c: c.data == "adv_profile_1") + self.cbq_handler(self.update_profile, lambda c: c.data == "update_profile") + self.cbq_handler(self.update_adv_profile, lambda c: c.data == "update_adv_profile") self.msg_handler(self.send_profile, commands=["profile"]) + self.msg_handler(self.send_orders, commands=["old_orders"]) self.cbq_handler(self.update_profile, lambda c: c.data == CBT.UPDATE_PROFILE) self.msg_handler(self.act_manual_delivery_test, commands=["test_lot"]) self.msg_handler(self.act_upload_image, commands=["upload_img"]) diff --git a/tg_bot/utils.py b/tg_bot/utils.py index 742d16d..23e6de8 100644 --- a/tg_bot/utils.py +++ b/tg_bot/utils.py @@ -18,6 +18,7 @@ from FunPayAPI.common.utils import RegularExpressions from bs4 import BeautifulSoup as bs import tg_bot.CBT +from bs4 import BeautifulSoup from FunPayAPI.account import Account from FunPayAPI.types import OrderStatuses from FunPayAPI.updater.events import * @@ -212,12 +213,28 @@ def add_navigation_buttons(keyboard_obj: K, curr_offset: int, B("▶️", callback_data=forward_cb), B("▶️▶️", callback_data=last_cb)) return keyboard_obj -ORDER_CONFIRMED = {} -if exists("storage/cache/advProfileStat.json"): - with open("storage/cache/advProfileStat.json", "r", encoding="utf-8") as f: - #global ORDER_CONFIRMED - ORDER_CONFIRMED = json.loads(f.read()) + +def generate_profile_text(vertex: Vertex) -> str: + """ + Генерирует текст с информацией об аккаунте. + + :return: сгенерированный текст с информацией об аккаунте. + """ + account = vertex.account + balance = vertex.balance + return f"""Статистика аккаунта {account.username} + +ID: {account.id} +Незавершенных заказов: {account.active_sales} +Баланс: + ₽: {balance.total_rub}₽, доступно для вывода {balance.available_rub}₽. + $: {balance.total_usd}$, доступно для вывода {balance.available_usd}$. + €: {balance.total_eur}€, доступно для вывода {balance.available_eur}€. + +Обновлено: {time.strftime('%H:%M:%S', time.localtime(account.last_update))}""" + +ORDER_CONFIRMED = {} def message_hook(vertex: Vertex, event: NewMessageEvent): if event.message.type not in [MessageTypes.ORDER_CONFIRMED, MessageTypes.ORDER_CONFIRMED_BY_ADMIN, MessageTypes.ORDER_REOPENED, MessageTypes.REFUND]: @@ -299,6 +316,10 @@ def get_sales(account: Account, start_from: str | None = None, include_paid: boo return next_order_id, sells def generate_adv_profile(account: Account) -> str: + if exists("storage/cache/advProfileStat.json"): + with open("storage/cache/advProfileStat.json", "r", encoding="utf-8") as f: + global ORDER_CONFIRMED + ORDER_CONFIRMED = json.loads(f.read()) sales = {"day": 0, "week": 0, "month": 0, "all": 0} salesPrice = {"day": 0.0, "week": 0.0, "month": 0.0, "all": 0.0} refunds = {"day": 0, "week": 0, "month": 0, "all": 0} @@ -410,6 +431,45 @@ def generate_adv_profile(account: Account) -> str: Обновлено: {time.strftime('%H:%M:%S', time.localtime(account.last_update))}""" +def get_orders(acc: Account, start_from: str) -> tuple[str | None, list[str]]: + """ + Получает список ордеров на аккаунте. + :return: Список с заказами. + """ + attempts = 3 + while attempts: + try: + result = acc.get_sells(start_from=start_from or None, state="paid") + break + except: + attempts -= 1 + time.sleep(1) + else: + raise Exception + orders = result[1] + old_orders = [] + for i in orders: + parser = BeautifulSoup(i.html, "html.parser") + time_text = parser.find("div", {"class": "tc-date-left"}).text + if any(map(time_text.__contains__, ["сек", "мин", "час", "тол"])): + continue + old_orders.append(parser.find("div", {"class": "tc-order"}).text) + return result[0], old_orders + +def get_all_old_orders(acc: Account) -> list[str]: + """ + Получает список все старых ордеров на аккаунте. + :param acc: экземпляр аккаунта. + :return: список старых заказов. + """ + start_from = "" + old_orders = [] + while start_from is not None: + result = get_orders(acc, start_from) + start_from = result[0] + old_orders.extend(result[1]) + time.sleep(1) + return old_orders def generate_lot_info_text(lot_obj: configparser.SectionProxy) -> str: """