ruff format

This commit is contained in:
serega 2024-12-25 04:30:33 +03:00
parent 2d0ddab976
commit 3b9bd19531
21 changed files with 294 additions and 186 deletions

View File

@ -8,10 +8,11 @@ from aiogram.enums import ParseMode
from aiogram.types import ErrorEvent from aiogram.types import ErrorEvent
from aiogram_dialog import setup_dialogs from aiogram_dialog import setup_dialogs
from environs import Env from environs import Env
from faststream.nats import NatsBroker
from bot.commands import command_router from shopbot.bot.commands import command_router
from bot.database import initialize_database from shopbot.bot.database import initialize_database
from bot.dialogs import ( from shopbot.bot.dialogs import (
admin_dialog, admin_dialog,
distribution_dialog, distribution_dialog,
gift_balance_dialog, gift_balance_dialog,
@ -24,6 +25,7 @@ from bot.dialogs import (
up_balance_dialog, up_balance_dialog,
up_balance_lolz_dialog, up_balance_lolz_dialog,
) )
from shopbot.consumers.new_account import router as new_account_router
async def on_error(event: ErrorEvent, bot: Bot): async def on_error(event: ErrorEvent, bot: Bot):
@ -39,6 +41,9 @@ async def main():
) )
dp = Dispatcher() dp = Dispatcher()
broker = NatsBroker()
broker.include_router(new_account_router)
await initialize_database() await initialize_database()
ROUTERS = [ ROUTERS = [
@ -62,6 +67,8 @@ async def main():
dp.error.register(on_error) dp.error.register(on_error)
setup_dialogs(dp) setup_dialogs(dp)
try: try:
async with broker:
await broker.start()
await dp.start_polling(bot) await dp.start_polling(bot)
finally: finally:
await bot.session.close() await bot.session.close()

View File

@ -1,14 +1,14 @@
import logging import logging
from aiogram import Router from aiogram import Router
from aiogram.filters import Command, CommandStart
from aiogram.types import Message from aiogram.types import Message
from aiogram.filters import CommandStart, Command
from aiogram_dialog import DialogManager, StartMode from aiogram_dialog import DialogManager, StartMode
from environs import Env
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database import register_user from shopbot.bot.database import register_user
from bot.states import StartSG, AdminSG from shopbot.bot.states import AdminSG, StartSG
from environs import Env
router = Router() router = Router()
@ -26,10 +26,7 @@ async def command_start_process(message: Message, dialog_manager: DialogManager)
return return
user_id = message.from_user.id user_id = message.from_user.id
username = message.from_user.username username = message.from_user.username
await register_user( await register_user(tg_id=user_id, username=username)
tg_id=user_id,
username=username
)
await dialog_manager.start(state=StartSG.start, mode=StartMode.RESET_STACK) await dialog_manager.start(state=StartSG.start, mode=StartMode.RESET_STACK)
except SQLAlchemyError as e: except SQLAlchemyError as e:
@ -37,6 +34,7 @@ async def command_start_process(message: Message, dialog_manager: DialogManager)
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True) logging.error(f"An unexpected error occurred: {e}", exc_info=True)
@router.message(Command("admin_panel")) @router.message(Command("admin_panel"))
async def command_admin_panel(message: Message, dialog_manager: DialogManager): async def command_admin_panel(message: Message, dialog_manager: DialogManager):
if not message.from_user or not message.from_user.id: if not message.from_user or not message.from_user.id:

View File

@ -1,14 +1,14 @@
import logging import logging
from typing import Optional from typing import Optional
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.future import select
from sqlalchemy.dialects.postgresql import insert
from bot.database.models import Base, UserModel
from environs import Env from environs import Env
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.future import select
from sqlalchemy.orm import sessionmaker
from shopbot.bot.database.models import Base, UserModel
env = Env() env = Env()
env.read_env() env.read_env()
@ -26,7 +26,9 @@ async def initialize_database():
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error during initialization: {e}", exc_info=True) logging.error(f"Database error during initialization: {e}", exc_info=True)
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred during initialization: {e}", exc_info=True) logging.error(
f"An unexpected error occurred during initialization: {e}", exc_info=True
)
async def register_user(tg_id: int, username: Optional[str] = None): async def register_user(tg_id: int, username: Optional[str] = None):
@ -43,7 +45,9 @@ async def register_user(tg_id: int, username: Optional[str] = None):
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error during user registration: {e}", exc_info=True) logging.error(f"Database error during user registration: {e}", exc_info=True)
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred during user registration: {e}", exc_info=True) logging.error(
f"An unexpected error occurred during user registration: {e}", exc_info=True
)
async def update_balance(tg_id: int, amount: int): async def update_balance(tg_id: int, amount: int):
@ -61,4 +65,6 @@ async def update_balance(tg_id: int, amount: int):
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error during balance update: {e}", exc_info=True) logging.error(f"Database error during balance update: {e}", exc_info=True)
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred during balance update: {e}", exc_info=True) logging.error(
f"An unexpected error occurred during balance update: {e}", exc_info=True
)

View File

@ -1,14 +1,15 @@
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Row, Start, Next
from aiogram_dialog.widgets.text import Const, Format
from aiogram_dialog.widgets.input import TextInput
from bot.services import broadcast_message, get_admin_statistics
from bot.services.user import gift_balance_data, take_balance_user
from bot.states import AdminSG, DistributionSG, GiftBalanceSG, TakeBalanceSG
from bot.validations import error_number_handler
from typing import Any from typing import Any
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.input import TextInput
from aiogram_dialog.widgets.kbd import Next, Row, Start
from aiogram_dialog.widgets.text import Const, Format
from shopbot.bot.services import broadcast_message, get_admin_statistics
from shopbot.bot.services.user import gift_balance_data, take_balance_user
from shopbot.bot.states import AdminSG, DistributionSG, GiftBalanceSG, TakeBalanceSG
from shopbot.bot.validations import error_number_handler
ADMIN_PANEL_BACK_BUTTON = Start( ADMIN_PANEL_BACK_BUTTON = Start(
Const("🔙 Вернуться в админ-панель"), id="back", state=AdminSG.panel Const("🔙 Вернуться в админ-панель"), id="back", state=AdminSG.panel
) )
@ -16,7 +17,9 @@ ADMIN_PANEL_TEXT = "<b>🔧 Админ панель</b>"
class AdminDialogWindow(Window): class AdminDialogWindow(Window):
def __init__(self, text: str, state: Any, input_id: str, type_factory: Any, **kwargs): def __init__(
self, text: str, state: Any, input_id: str, type_factory: Any, **kwargs
):
super().__init__( super().__init__(
Const(text), Const(text),
TextInput( TextInput(
@ -27,7 +30,7 @@ class AdminDialogWindow(Window):
), ),
ADMIN_PANEL_BACK_BUTTON, ADMIN_PANEL_BACK_BUTTON,
state=state, state=state,
**kwargs **kwargs,
) )
@ -105,13 +108,13 @@ gift_balance_dialog = Dialog(
text="<b>💸 Выдача баланса</b>\n\nВведите ID пользователя:", text="<b>💸 Выдача баланса</b>\n\nВведите ID пользователя:",
state=GiftBalanceSG.gift_balance_user_id, state=GiftBalanceSG.gift_balance_user_id,
input_id="user_id_input", input_id="user_id_input",
type_factory=int type_factory=int,
), ),
AdminDialogWindow( AdminDialogWindow(
text="Введите сумму для пополнения баланса:", text="Введите сумму для пополнения баланса:",
state=GiftBalanceSG.gift_balance_amount, state=GiftBalanceSG.gift_balance_amount,
input_id="amount_input", input_id="amount_input",
type_factory=float type_factory=float,
), ),
Window( Window(
Format("{result}"), Format("{result}"),
@ -126,13 +129,13 @@ take_balance_dialog = Dialog(
text="<b>❌ Отнятие баланса</b>\n\nВведите ID пользователя:", text="<b>❌ Отнятие баланса</b>\n\nВведите ID пользователя:",
state=TakeBalanceSG.take_balance_user_id, state=TakeBalanceSG.take_balance_user_id,
input_id="user_id_input", input_id="user_id_input",
type_factory=int type_factory=int,
), ),
AdminDialogWindow( AdminDialogWindow(
text="Введите сумму для вычета из баланса:", text="Введите сумму для вычета из баланса:",
state=TakeBalanceSG.take_balance_amount, state=TakeBalanceSG.take_balance_amount,
input_id="amount_input", input_id="amount_input",
type_factory=float type_factory=float,
), ),
Window( Window(
Format("{result}"), Format("{result}"),

View File

@ -1,16 +1,21 @@
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Row, Start, Button
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.input import TextInput, ManagedTextInput
from aiogram_dialog import DialogManager
from aiogram.types import Message
from bot.services import check_pay_crypto_bot, check_pay_lolz
from bot.getters import getter_amount, getter_amount_cryptobot
from bot.states import UpBalanceCryptoSG, UpBalanceSG, UpBalanceLolzSG, ProfileSG
from bot.validations import error_number_handler
from typing import Any from typing import Any
from aiogram.types import Message
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.input import ManagedTextInput, TextInput
from aiogram_dialog.widgets.kbd import Button, Row, Start
from aiogram_dialog.widgets.text import Const, Format
from shopbot.bot.getters import getter_amount, getter_amount_cryptobot
from shopbot.bot.services import check_pay_crypto_bot, check_pay_lolz
from shopbot.bot.states import (
ProfileSG,
UpBalanceCryptoSG,
UpBalanceLolzSG,
UpBalanceSG,
)
from shopbot.bot.validations import error_number_handler
class UpBalanceWindow(Window): class UpBalanceWindow(Window):
def __init__(self, text: str, state: Any, on_error: Any, **kwargs): def __init__(self, text: str, state: Any, on_error: Any, **kwargs):
@ -23,10 +28,16 @@ class UpBalanceWindow(Window):
on_error=on_error, on_error=on_error,
), ),
state=state, state=state,
**kwargs **kwargs,
) )
async def _on_success_callback(self, message: Message, widget: ManagedTextInput, dialog_manager: DialogManager, data: str): async def _on_success_callback(
self,
message: Message,
widget: ManagedTextInput,
dialog_manager: DialogManager,
data: str,
):
if not dialog_manager.current_context().dialog_data.get("error"): if not dialog_manager.current_context().dialog_data.get("error"):
await dialog_manager.next() await dialog_manager.next()
@ -34,23 +45,32 @@ class UpBalanceWindow(Window):
class PaymentWindow(Window): class PaymentWindow(Window):
def __init__(self, state: Any, check_pay_function: Any, getter: Any, **kwargs): def __init__(self, state: Any, check_pay_function: Any, getter: Any, **kwargs):
super().__init__( super().__init__(
Format(text="{paylink}", when=lambda data, widget, manager: not data.get("error")), Format(
Format(text="{error}", when=lambda data, widget, manager: data.get("error") is not None), text="{paylink}",
when=lambda data, widget, manager: not data.get("error"),
),
Format(
text="{error}",
when=lambda data, widget, manager: data.get("error") is not None,
),
Button( Button(
Const("🔍 Проверить оплату"), Const("🔍 Проверить оплату"),
id="check_pay_button", id="check_pay_button",
on_click=check_pay_function, on_click=check_pay_function,
when=lambda data, widget, manager: not data.get("error") and data.get("paylink") is not None when=lambda data, widget, manager: not data.get("error")
and data.get("paylink") is not None,
), ),
Button( Button(
Const("🔙 Отмена"), Const("🔙 Отмена"),
id="cancel_button", id="cancel_button",
on_click=lambda callback, button, manager: manager.switch_to(ProfileSG.profile), on_click=lambda callback, button, manager: manager.switch_to(
when=lambda data, widget, manager: data.get("error") is not None ProfileSG.profile
),
when=lambda data, widget, manager: data.get("error") is not None,
), ),
state=state, state=state,
getter=getter, getter=getter,
**kwargs **kwargs,
) )
@ -85,8 +105,7 @@ up_balance_lolz_dialog = Dialog(
state=UpBalanceLolzSG.pay_link, state=UpBalanceLolzSG.pay_link,
check_pay_function=check_pay_lolz, check_pay_function=check_pay_lolz,
getter=getter_amount, getter=getter_amount,
) ),
) )
@ -94,7 +113,7 @@ up_balance_cryptobot_dialog = Dialog(
UpBalanceWindow( UpBalanceWindow(
text="💸 Введите сумму пополнения", text="💸 Введите сумму пополнения",
state=UpBalanceCryptoSG.up_balance_crypto, state=UpBalanceCryptoSG.up_balance_crypto,
on_error=error_number_handler on_error=error_number_handler,
), ),
PaymentWindow( PaymentWindow(
state=UpBalanceCryptoSG.pay_link, state=UpBalanceCryptoSG.pay_link,

View File

@ -1,11 +1,14 @@
from aiogram_dialog import Dialog, Window from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Row, Start, Back, Button from aiogram_dialog.widgets.kbd import Back, Button, Row, ScrollingGroup, Select, Start
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Const, Format
from aiogram_dialog.widgets.kbd import ScrollingGroup, Select
from bot.getters import get_history_account_details, get_purchase_history from shopbot.bot.getters import (
from bot.getters import username_getter get_history_account_details,
from bot.services import on_history_account_selected get_purchase_history,
from bot.states import PurchaseHistorySG, UpBalanceSG, ProfileSG, StartSG username_getter,
)
from shopbot.bot.services import on_history_account_selected
from shopbot.bot.states import ProfileSG, PurchaseHistorySG, StartSG, UpBalanceSG
PROFILE_BACK_BUTTON = Start(Const("🔙 Назад"), id="back", state=StartSG.start) PROFILE_BACK_BUTTON = Start(Const("🔙 Назад"), id="back", state=StartSG.start)
HISTORY_BACK_BUTTON = Start(Const("🔙 Назад"), id="back", state=ProfileSG.profile) HISTORY_BACK_BUTTON = Start(Const("🔙 Назад"), id="back", state=ProfileSG.profile)

View File

@ -14,14 +14,18 @@ from aiogram_dialog.widgets.kbd import (
from aiogram_dialog.widgets.text import Const, Format, Multi from aiogram_dialog.widgets.text import Const, Format, Multi
from pydantic import NonNegativeInt from pydantic import NonNegativeInt
from bot.getters import ( from shopbot.bot.getters import (
get_account_details, get_account_details,
get_account_info, get_account_info,
get_accounts, get_accounts,
) )
from bot.getters.filters import get_filters_info, on_filter_selected, update_filters from shopbot.bot.getters.filters import (
from bot.services import on_account_selected, on_buy_button_click get_filters_info,
from bot.states import ( on_filter_selected,
update_filters,
)
from shopbot.bot.services import on_account_selected, on_buy_button_click
from shopbot.bot.states import (
PurchaseAccountsSG, PurchaseAccountsSG,
StartSG, StartSG,
) )

View File

@ -1,9 +1,9 @@
from aiogram_dialog import Dialog, Window from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Start, Row from aiogram_dialog.widgets.kbd import Row, Start
from aiogram_dialog.widgets.text import Const, Format from aiogram_dialog.widgets.text import Const, Format
from bot.getters import username_getter from shopbot.bot.getters import username_getter
from bot.states import StartSG, ProfileSG, PurchaseAccountsSG from shopbot.bot.states import ProfileSG, PurchaseAccountsSG, StartSG
start_dialog = Dialog( start_dialog = Dialog(
Window( Window(

View File

@ -5,9 +5,9 @@ from aiogram_dialog import DialogManager
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.db import async_session from shopbot.bot.database.db import async_session
from bot.database.models import Account from shopbot.bot.database.models import Account
from bot.getters.filters import FilterDTO, FilterType from shopbot.bot.getters.filters import FilterDTO, FilterType
def _format_account_short_info(account: Account) -> str: def _format_account_short_info(account: Account) -> str:

View File

@ -6,7 +6,7 @@ from aiogram.types import CallbackQuery, Message
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from pydantic import NonNegativeInt from pydantic import NonNegativeInt
from bot.states.states import PurchaseAccountsSG from shopbot.bot.states.states import PurchaseAccountsSG
class FilterType(Enum): class FilterType(Enum):

View File

@ -1,21 +1,21 @@
import logging import logging
from typing import Any, Dict
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.models import Account from shopbot.bot.database.db import async_session
from bot.database.db import async_session from shopbot.bot.database.models import Account
from typing import Dict, Any
def _format_account_short_info(account: Account) -> str: def _format_account_short_info(account: Account) -> str:
return ( return f"🌍 {account.region} | 🎮 {account.current_rank} | 💰 {account.price:.2f}"
f"🌍 {account.region} | 🎮 {account.current_rank} | 💰 {account.price:.2f}"
)
async def get_purchase_history(dialog_manager: DialogManager, **kwargs) -> Dict[str, Any]: async def get_purchase_history(
dialog_manager: DialogManager, **kwargs
) -> Dict[str, Any]:
user_tg_id = dialog_manager.event.from_user.id user_tg_id = dialog_manager.event.from_user.id
try: try:
async with async_session() as session: async with async_session() as session:
@ -35,17 +35,22 @@ async def get_purchase_history(dialog_manager: DialogManager, **kwargs) -> Dict[
(_format_account_short_info(account), account.id) (_format_account_short_info(account), account.id)
for account in purchased_accounts for account in purchased_accounts
], ],
"text": text "text": text,
} }
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error: {e}", exc_info=True) logging.error(f"Database error: {e}", exc_info=True)
return {"purchased_accounts": [], "text": "❌ Произошла ошибка при работе с базой данных."} return {
"purchased_accounts": [],
"text": "❌ Произошла ошибка при работе с базой данных.",
}
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True) logging.error(f"An unexpected error occurred: {e}", exc_info=True)
return {"purchased_accounts": [], "text": "❌ Произошла непредвиденная ошибка."} return {"purchased_accounts": [], "text": "❌ Произошла непредвиденная ошибка."}
async def get_history_account_details(dialog_manager: DialogManager, **kwargs) -> Dict[str, str]: async def get_history_account_details(
dialog_manager: DialogManager, **kwargs
) -> Dict[str, str]:
account_info = dialog_manager.current_context().dialog_data.get("account_info") account_info = dialog_manager.current_context().dialog_data.get("account_info")
if not account_info: if not account_info:

View File

@ -1,10 +1,10 @@
import logging import logging
from typing import Dict, Any from typing import Any, Dict
from urllib.parse import urlparse, parse_qs from urllib.parse import parse_qs, urlparse
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from bot.services import create_paylink_lolz, create_paylink_cryptobot from shopbot.bot.services import create_paylink_cryptobot, create_paylink_lolz
async def getter_amount(dialog_manager: DialogManager, **kwargs) -> Dict[str, Any]: async def getter_amount(dialog_manager: DialogManager, **kwargs) -> Dict[str, Any]:
@ -21,10 +21,14 @@ async def getter_amount(dialog_manager: DialogManager, **kwargs) -> Dict[str, An
return pay_data return pay_data
except Exception as e: except Exception as e:
logging.error(f"Error creating Lolz paylink: {e}", exc_info=True) logging.error(f"Error creating Lolz paylink: {e}", exc_info=True)
return {"error": "Произошла ошибка при создании ссылки для оплаты Lolz. Пожалуйста, попробуйте позже."} return {
"error": "Произошла ошибка при создании ссылки для оплаты Lolz. Пожалуйста, попробуйте позже."
}
async def getter_amount_cryptobot(dialog_manager: DialogManager, **kwargs) -> Dict[str, Any]: async def getter_amount_cryptobot(
dialog_manager: DialogManager, **kwargs
) -> Dict[str, Any]:
dialog_manager.current_context().dialog_data.pop("pay_data", None) dialog_manager.current_context().dialog_data.pop("pay_data", None)
count = dialog_manager.find("count").get_value() count = dialog_manager.find("count").get_value()
@ -39,4 +43,6 @@ async def getter_amount_cryptobot(dialog_manager: DialogManager, **kwargs) -> Di
return pay_data return pay_data
except Exception as e: except Exception as e:
logging.error(f"Error creating CryptoBot paylink: {e}", exc_info=True) logging.error(f"Error creating CryptoBot paylink: {e}", exc_info=True)
return {"error": "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Пожалуйста, проверьте настройки и попробуйте снова."} return {
"error": "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Пожалуйста, проверьте настройки и попробуйте снова."
}

View File

@ -1,13 +1,13 @@
import logging import logging
from typing import Dict, Any from typing import Any, Dict
from aiogram.types import User from aiogram.types import User
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.models import UserModel from shopbot.bot.database.db import async_session
from bot.database.db import async_session from shopbot.bot.database.models import UserModel
async def username_getter( async def username_getter(
@ -26,7 +26,9 @@ async def username_getter(
"purchased": user.purchased, "purchased": user.purchased,
} }
else: else:
logging.warning(f"User with tg_id {event_from_user.id} not found in database.") logging.warning(
f"User with tg_id {event_from_user.id} not found in database."
)
return { return {
"username": event_from_user.username, "username": event_from_user.username,
"balance": 0, "balance": 0,

View File

@ -1,22 +1,30 @@
import asyncio import asyncio
import logging import logging
from aiogram.exceptions import (
TelegramAPIError,
TelegramForbiddenError,
TelegramRetryAfter,
)
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from aiogram.exceptions import TelegramRetryAfter, TelegramForbiddenError, TelegramAPIError
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.db import async_session from shopbot.bot.database.db import async_session
from bot.database.models import UserModel from shopbot.bot.database.models import UserModel
async def _send_message_with_retry(bot, user_id: int, message_text: str, max_retries=3, delay=1) -> bool: async def _send_message_with_retry(
bot, user_id: int, message_text: str, max_retries=3, delay=1
) -> bool:
for attempt in range(max_retries): for attempt in range(max_retries):
try: try:
await bot.send_message(user_id, message_text) await bot.send_message(user_id, message_text)
return True return True
except TelegramRetryAfter as e: except TelegramRetryAfter as e:
logging.warning(f"Retry after {e.retry_after} for user {user_id}, attempt {attempt + 1}") logging.warning(
f"Retry after {e.retry_after} for user {user_id}, attempt {attempt + 1}"
)
await asyncio.sleep(e.retry_after) await asyncio.sleep(e.retry_after)
except TelegramForbiddenError: except TelegramForbiddenError:
logging.warning(f"User {user_id} blocked bot") logging.warning(f"User {user_id} blocked bot")
@ -49,14 +57,10 @@ async def broadcast_message(dialog_manager: DialogManager, **kwargs):
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error: {e}") logging.error(f"Database error: {e}")
return { return {"progress": f"❌ Ошибка при работе с базой данных: {e}"}
"progress": f"❌ Ошибка при работе с базой данных: {e}"
}
except Exception as e: except Exception as e:
logging.error(f"An unexpected error occurred: {e}") logging.error(f"An unexpected error occurred: {e}")
return { return {"progress": f"❌ Непредвиденная ошибка: {e}"}
"progress": f"❌ Непредвиденная ошибка: {e}"
}
return { return {
"progress": f"✅ Рассылка завершена!\n" "progress": f"✅ Рассылка завершена!\n"

View File

@ -7,9 +7,9 @@ from aiogram_dialog.widgets.kbd import Select
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.db import async_session from shopbot.bot.database.db import async_session
from bot.database.models import Account, UserModel from shopbot.bot.database.models import Account, UserModel
from bot.states import PurchaseAccountsSG from shopbot.bot.states import PurchaseAccountsSG
ACCOUNT_INFO_TEMPLATE = ( ACCOUNT_INFO_TEMPLATE = (
"<b>Подробная информация об аккаунте:</b>\n\n" "<b>Подробная информация об аккаунте:</b>\n\n"

View File

@ -1,14 +1,13 @@
import logging import logging
from aiogram_dialog import DialogManager
from aiogram.types import CallbackQuery from aiogram.types import CallbackQuery
from aiogram_dialog import DialogManager
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.db import async_session from shopbot.bot.database.db import async_session
from bot.database.models import Account from shopbot.bot.database.models import Account
from bot.states import PurchaseHistorySG from shopbot.bot.states import PurchaseHistorySG
ACCOUNT_INFO_TEMPLATE = ( ACCOUNT_INFO_TEMPLATE = (
"<b>Подробная информация об аккаунте:</b>\n\n" "<b>Подробная информация об аккаунте:</b>\n\n"
@ -43,7 +42,9 @@ async def _format_account_info(account: Account) -> str:
) )
async def on_history_account_selected(callback: CallbackQuery, selecte, manager: DialogManager, item_id: int): async def on_history_account_selected(
callback: CallbackQuery, selecte, manager: DialogManager, item_id: int
):
try: try:
if not isinstance(item_id, int): if not isinstance(item_id, int):
item_id = int(item_id) item_id = int(item_id)
@ -52,18 +53,22 @@ async def on_history_account_selected(callback: CallbackQuery, selecte, manager:
async with async_session() as session: async with async_session() as session:
async with session.begin(): async with session.begin():
account = await session.scalar(select(Account).where(Account.id == item_id)) account = await session.scalar(
select(Account).where(Account.id == item_id)
)
if account: if account:
manager.current_context().dialog_data["account_info"] = await _format_account_info(account) manager.current_context().dialog_data[
"account_info"
] = await _format_account_info(account)
else: else:
logging.warning(f"Account with id {item_id} not found") logging.warning(f"Account with id {item_id} not found")
manager.current_context().dialog_data["account_info"] = "Аккаунт не найден!" manager.current_context().dialog_data["account_info"] = (
"Аккаунт не найден!"
)
await manager.switch_to(PurchaseHistorySG.details) await manager.switch_to(PurchaseHistorySG.details)
except SQLAlchemyError as e: except SQLAlchemyError as e:
logging.error(f"Database error: {e}", exc_info=True) logging.error(f"Database error: {e}", exc_info=True)

View File

@ -1,15 +1,15 @@
import logging import logging
from typing import Tuple from typing import Tuple
from AsyncPayments.lolz import AsyncLolzteamMarketPayment
from AsyncPayments.cryptoBot import AsyncCryptoBot
from aiogram.types import CallbackQuery from aiogram.types import CallbackQuery
from aiogram_dialog import DialogManager, StartMode from aiogram_dialog import DialogManager, StartMode
from aiogram_dialog.widgets.kbd import Button from aiogram_dialog.widgets.kbd import Button
from AsyncPayments.cryptoBot import AsyncCryptoBot
from bot.database import update_balance from AsyncPayments.lolz import AsyncLolzteamMarketPayment
from environs import Env from environs import Env
from bot.states import ProfileSG
from shopbot.bot.database import update_balance
from shopbot.bot.states import ProfileSG
env = Env() env = Env()
env.read_env() env.read_env()
@ -28,15 +28,35 @@ async def create_paylink_lolz(amount: int) -> str:
async def create_paylink_cryptobot(amount: int) -> Tuple[str, str]: async def create_paylink_cryptobot(amount: int) -> Tuple[str, str]:
try: try:
invoice = await cryptobot_payment.create_invoice( invoice = await cryptobot_payment.create_invoice(
amount=float(amount),currency_type="fiat", fiat="RUB", description="Пополнение баланса", accepted_assets=["USDT", "TON", "SOL", "BTC", "LTC", "ETH", "BNB", "TRX", "USDC"] amount=float(amount),
currency_type="fiat",
fiat="RUB",
description="Пополнение баланса",
accepted_assets=[
"USDT",
"TON",
"SOL",
"BTC",
"LTC",
"ETH",
"BNB",
"TRX",
"USDC",
],
) )
return invoice.pay_url, str(invoice.invoice_id) return invoice.pay_url, str(invoice.invoice_id)
except Exception as e: except Exception as e:
if "AMOUNT_TOO_SMALL" in str(e): if "AMOUNT_TOO_SMALL" in str(e):
logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True) logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True)
return None, "Сумма для пополнения должна быть не менее 0.01 USD (примерно 1 руб). Пожалуйста, проверьте и попробуйте снова, либо выберите другой способ оплаты." return (
None,
"Сумма для пополнения должна быть не менее 0.01 USD (примерно 1 руб). Пожалуйста, проверьте и попробуйте снова, либо выберите другой способ оплаты.",
)
logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True) logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True)
return None, "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Попробуйте позже." return (
None,
"Произошла ошибка при создании ссылки для оплаты через CryptoBot. Попробуйте позже.",
)
async def check_pay_lolz( async def check_pay_lolz(
@ -44,14 +64,18 @@ async def check_pay_lolz(
): ):
pay_data = manager.current_context().dialog_data.get("pay_data") pay_data = manager.current_context().dialog_data.get("pay_data")
if not pay_data: if not pay_data:
await callback.message.answer("Ошибка: данные оплаты не найдены. Попробуйте еще раз. ❌") await callback.message.answer(
"Ошибка: данные оплаты не найдены. Попробуйте еще раз. ❌"
)
return return
order_id = pay_data.get("order_id") order_id = pay_data.get("order_id")
amount = pay_data.get("amount") amount = pay_data.get("amount")
if not order_id or not amount: if not order_id or not amount:
await callback.message.answer("Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌") await callback.message.answer(
"Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌"
)
return return
if manager.current_context().dialog_data.get("is_payment_processed", False): if manager.current_context().dialog_data.get("is_payment_processed", False):
await callback.answer("Оплата уже обработана.", show_alert=True) await callback.answer("Оплата уже обработана.", show_alert=True)
@ -65,13 +89,19 @@ async def check_pay_lolz(
if status: if status:
manager.current_context().dialog_data["is_payment_processed"] = True manager.current_context().dialog_data["is_payment_processed"] = True
await update_balance(callback.from_user.id, amount) await update_balance(callback.from_user.id, amount)
await callback.message.edit_text(f"Поздравляем, счет пополнен на {amount} руб 🎉") await callback.message.edit_text(
f"Поздравляем, счет пополнен на {amount} руб 🎉"
)
else: else:
await callback.message.answer("Счет не оплачен, проверьте оплату или проверьте еще раз! ⚠️") await callback.message.answer(
"Счет не оплачен, проверьте оплату или проверьте еще раз! ⚠️"
)
except Exception as e: except Exception as e:
logging.error(f"Error checking Lolz payment: {e}", exc_info=True) logging.error(f"Error checking Lolz payment: {e}", exc_info=True)
await callback.message.answer("Произошла ошибка при проверке оплаты Lolz. Попробуйте позже. ❌") await callback.message.answer(
"Произошла ошибка при проверке оплаты Lolz. Попробуйте позже. ❌"
)
async def check_pay_crypto_bot( async def check_pay_crypto_bot(
@ -80,14 +110,18 @@ async def check_pay_crypto_bot(
pay_data = manager.current_context().dialog_data.get("pay_data") pay_data = manager.current_context().dialog_data.get("pay_data")
if not pay_data: if not pay_data:
await callback.message.answer("Ошибка: данные для оплаты не найдены. Попробуйте позже. ❌") await callback.message.answer(
"Ошибка: данные для оплаты не найдены. Попробуйте позже. ❌"
)
return return
order_id = pay_data.get("order_id") order_id = pay_data.get("order_id")
amount = pay_data.get("amount") amount = pay_data.get("amount")
if not order_id or not amount: if not order_id or not amount:
await callback.message.answer("Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌") await callback.message.answer(
"Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌"
)
return return
if manager.current_context().dialog_data.get("is_payment_processed", False): if manager.current_context().dialog_data.get("is_payment_processed", False):
await callback.answer("Оплата уже обработана.", show_alert=True) await callback.answer("Оплата уже обработана.", show_alert=True)
@ -105,7 +139,9 @@ async def check_pay_crypto_bot(
if invoice.status == "paid": if invoice.status == "paid":
manager.current_context().dialog_data["is_payment_processed"] = True manager.current_context().dialog_data["is_payment_processed"] = True
await update_balance(callback.from_user.id, amount) await update_balance(callback.from_user.id, amount)
await callback.message.answer(f"Поздравляем, счет пополнен на {amount} руб 🎉") await callback.message.answer(
f"Поздравляем, счет пополнен на {amount} руб 🎉"
)
await callback.message.delete() await callback.message.delete()
await manager.start(state=ProfileSG.profile, mode=StartMode.RESET_STACK) await manager.start(state=ProfileSG.profile, mode=StartMode.RESET_STACK)
else: else:
@ -113,4 +149,6 @@ async def check_pay_crypto_bot(
await callback.message.answer("Оплата не найдена. Попробуйте позже. ⏳") await callback.message.answer("Оплата не найдена. Попробуйте позже. ⏳")
except Exception as e: except Exception as e:
logging.error(f"Error checking CryptoBot payment: {e}", exc_info=True) logging.error(f"Error checking CryptoBot payment: {e}", exc_info=True)
await callback.message.answer("Произошла ошибка при проверке оплаты через CryptoBot. Попробуйте позже. ❌") await callback.message.answer(
"Произошла ошибка при проверке оплаты через CryptoBot. Попробуйте позже. ❌"
)

View File

@ -6,8 +6,8 @@ from aiogram_dialog import DialogManager
from sqlalchemy import func, select from sqlalchemy import func, select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from bot.database.db import async_session from shopbot.bot.database.db import async_session
from bot.database.models import Account, UserModel from shopbot.bot.database.models import Account, UserModel
def _get_start_of_day(): def _get_start_of_day():

View File

@ -1,13 +1,13 @@
import logging import logging
from typing import Dict, Any from typing import Any, Dict
from aiogram_dialog import DialogManager from aiogram_dialog import DialogManager
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from bot.database.models import UserModel from shopbot.bot.database.db import async_session
from bot.database.db import async_session from shopbot.bot.database.models import UserModel
RESULT_MESSAGES = { RESULT_MESSAGES = {
"not_enough_funds": "❌ Недостаточно средств на балансе пользователя!", "not_enough_funds": "❌ Недостаточно средств на балансе пользователя!",

8
consumers/new_account.py Normal file
View File

@ -0,0 +1,8 @@
from faststream.nats import NatsRouter
router = NatsRouter()
@router.subscriber("shop.new_account")
async def new_account_proceed(msg: int):
print(msg)

View File

@ -1,4 +1,4 @@
from bot.getters.filters import FilterType from shopbot.bot.getters.filters import FilterType
for x in FilterType: for x in FilterType:
print(x.name, x.value) print(x.name, x.value)