diff --git a/main.py b/__main__.py
similarity index 78%
rename from main.py
rename to __main__.py
index c7ab188..3ea28d6 100644
--- a/main.py
+++ b/__main__.py
@@ -8,10 +8,11 @@ from aiogram.enums import ParseMode
from aiogram.types import ErrorEvent
from aiogram_dialog import setup_dialogs
from environs import Env
+from faststream.nats import NatsBroker
-from bot.commands import command_router
-from bot.database import initialize_database
-from bot.dialogs import (
+from shopbot.bot.commands import command_router
+from shopbot.bot.database import initialize_database
+from shopbot.bot.dialogs import (
admin_dialog,
distribution_dialog,
gift_balance_dialog,
@@ -24,6 +25,7 @@ from bot.dialogs import (
up_balance_dialog,
up_balance_lolz_dialog,
)
+from shopbot.consumers.new_account import router as new_account_router
async def on_error(event: ErrorEvent, bot: Bot):
@@ -39,6 +41,9 @@ async def main():
)
dp = Dispatcher()
+ broker = NatsBroker()
+ broker.include_router(new_account_router)
+
await initialize_database()
ROUTERS = [
@@ -62,7 +67,9 @@ async def main():
dp.error.register(on_error)
setup_dialogs(dp)
try:
- await dp.start_polling(bot)
+ async with broker:
+ await broker.start()
+ await dp.start_polling(bot)
finally:
await bot.session.close()
diff --git a/bot/commands/command.py b/bot/commands/command.py
index 47115e2..0aaefec 100644
--- a/bot/commands/command.py
+++ b/bot/commands/command.py
@@ -1,14 +1,14 @@
import logging
from aiogram import Router
+from aiogram.filters import Command, CommandStart
from aiogram.types import Message
-from aiogram.filters import CommandStart, Command
from aiogram_dialog import DialogManager, StartMode
+from environs import Env
from sqlalchemy.exc import SQLAlchemyError
-from bot.database import register_user
-from bot.states import StartSG, AdminSG
-from environs import Env
+from shopbot.bot.database import register_user
+from shopbot.bot.states import AdminSG, StartSG
router = Router()
@@ -26,10 +26,7 @@ async def command_start_process(message: Message, dialog_manager: DialogManager)
return
user_id = message.from_user.id
username = message.from_user.username
- await register_user(
- tg_id=user_id,
- username=username
- )
+ await register_user(tg_id=user_id, username=username)
await dialog_manager.start(state=StartSG.start, mode=StartMode.RESET_STACK)
except SQLAlchemyError as e:
@@ -37,6 +34,7 @@ async def command_start_process(message: Message, dialog_manager: DialogManager)
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
+
@router.message(Command("admin_panel"))
async def command_admin_panel(message: Message, dialog_manager: DialogManager):
if not message.from_user or not message.from_user.id:
@@ -45,4 +43,4 @@ async def command_admin_panel(message: Message, dialog_manager: DialogManager):
if str(message.from_user.id) == ADMIN_ID:
await dialog_manager.start(state=AdminSG.panel)
else:
- logging.warning(f"User with tg_id {message.from_user.id} is not admin")
\ No newline at end of file
+ logging.warning(f"User with tg_id {message.from_user.id} is not admin")
diff --git a/bot/database/db.py b/bot/database/db.py
index 51dbedc..fda0eba 100644
--- a/bot/database/db.py
+++ b/bot/database/db.py
@@ -1,14 +1,14 @@
import logging
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 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.read_env()
@@ -26,7 +26,9 @@ async def initialize_database():
except SQLAlchemyError as e:
logging.error(f"Database error during initialization: {e}", exc_info=True)
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):
@@ -43,7 +45,9 @@ async def register_user(tg_id: int, username: Optional[str] = None):
except SQLAlchemyError as e:
logging.error(f"Database error during user registration: {e}", exc_info=True)
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):
@@ -61,4 +65,6 @@ async def update_balance(tg_id: int, amount: int):
except SQLAlchemyError as e:
logging.error(f"Database error during balance update: {e}", exc_info=True)
except Exception as e:
- logging.error(f"An unexpected error occurred during balance update: {e}", exc_info=True)
\ No newline at end of file
+ logging.error(
+ f"An unexpected error occurred during balance update: {e}", exc_info=True
+ )
diff --git a/bot/dialogs/admin.py b/bot/dialogs/admin.py
index 8237922..f6717a3 100644
--- a/bot/dialogs/admin.py
+++ b/bot/dialogs/admin.py
@@ -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 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(
Const("🔙 Вернуться в админ-панель"), id="back", state=AdminSG.panel
)
@@ -16,7 +17,9 @@ ADMIN_PANEL_TEXT = "🔧 Админ панель"
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__(
Const(text),
TextInput(
@@ -27,7 +30,7 @@ class AdminDialogWindow(Window):
),
ADMIN_PANEL_BACK_BUTTON,
state=state,
- **kwargs
+ **kwargs,
)
@@ -105,13 +108,13 @@ gift_balance_dialog = Dialog(
text="💸 Выдача баланса\n\nВведите ID пользователя:",
state=GiftBalanceSG.gift_balance_user_id,
input_id="user_id_input",
- type_factory=int
+ type_factory=int,
),
AdminDialogWindow(
text="Введите сумму для пополнения баланса:",
state=GiftBalanceSG.gift_balance_amount,
input_id="amount_input",
- type_factory=float
+ type_factory=float,
),
Window(
Format("{result}"),
@@ -126,13 +129,13 @@ take_balance_dialog = Dialog(
text="❌ Отнятие баланса\n\nВведите ID пользователя:",
state=TakeBalanceSG.take_balance_user_id,
input_id="user_id_input",
- type_factory=int
+ type_factory=int,
),
AdminDialogWindow(
text="Введите сумму для вычета из баланса:",
state=TakeBalanceSG.take_balance_amount,
input_id="amount_input",
- type_factory=float
+ type_factory=float,
),
Window(
Format("{result}"),
@@ -140,4 +143,4 @@ take_balance_dialog = Dialog(
state=TakeBalanceSG.take_balance_confirmation,
getter=take_balance_user,
),
-)
\ No newline at end of file
+)
diff --git a/bot/dialogs/balance.py b/bot/dialogs/balance.py
index eb6ba07..cef955e 100644
--- a/bot/dialogs/balance.py
+++ b/bot/dialogs/balance.py
@@ -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 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):
def __init__(self, text: str, state: Any, on_error: Any, **kwargs):
@@ -23,10 +28,16 @@ class UpBalanceWindow(Window):
on_error=on_error,
),
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"):
await dialog_manager.next()
@@ -34,23 +45,32 @@ class UpBalanceWindow(Window):
class PaymentWindow(Window):
def __init__(self, state: Any, check_pay_function: Any, getter: Any, **kwargs):
super().__init__(
- Format(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),
+ Format(
+ 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(
Const("🔍 Проверить оплату"),
id="check_pay_button",
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(
Const("🔙 Отмена"),
id="cancel_button",
- on_click=lambda callback, button, manager: manager.switch_to(ProfileSG.profile),
- when=lambda data, widget, manager: data.get("error") is not None
+ on_click=lambda callback, button, manager: manager.switch_to(
+ ProfileSG.profile
+ ),
+ when=lambda data, widget, manager: data.get("error") is not None,
),
state=state,
getter=getter,
- **kwargs
+ **kwargs,
)
@@ -85,8 +105,7 @@ up_balance_lolz_dialog = Dialog(
state=UpBalanceLolzSG.pay_link,
check_pay_function=check_pay_lolz,
getter=getter_amount,
- )
-
+ ),
)
@@ -94,11 +113,11 @@ up_balance_cryptobot_dialog = Dialog(
UpBalanceWindow(
text="💸 Введите сумму пополнения",
state=UpBalanceCryptoSG.up_balance_crypto,
- on_error=error_number_handler
+ on_error=error_number_handler,
),
PaymentWindow(
state=UpBalanceCryptoSG.pay_link,
check_pay_function=check_pay_crypto_bot,
getter=getter_amount_cryptobot,
),
-)
\ No newline at end of file
+)
diff --git a/bot/dialogs/profile.py b/bot/dialogs/profile.py
index 2d14b1c..c43b8b9 100644
--- a/bot/dialogs/profile.py
+++ b/bot/dialogs/profile.py
@@ -1,11 +1,14 @@
from aiogram_dialog import Dialog, Window
-from aiogram_dialog.widgets.kbd import Row, Start, Back, Button
-from aiogram_dialog.widgets.text import Format, Const
-from aiogram_dialog.widgets.kbd import ScrollingGroup, Select
-from bot.getters import get_history_account_details, get_purchase_history
-from bot.getters import username_getter
-from bot.services import on_history_account_selected
-from bot.states import PurchaseHistorySG, UpBalanceSG, ProfileSG, StartSG
+from aiogram_dialog.widgets.kbd import Back, Button, Row, ScrollingGroup, Select, Start
+from aiogram_dialog.widgets.text import Const, Format
+
+from shopbot.bot.getters import (
+ get_history_account_details,
+ get_purchase_history,
+ 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)
HISTORY_BACK_BUTTON = Start(Const("🔙 Назад"), id="back", state=ProfileSG.profile)
@@ -59,4 +62,4 @@ history_dialog = Dialog(
state=PurchaseHistorySG.details,
getter=get_history_account_details,
),
-)
\ No newline at end of file
+)
diff --git a/bot/dialogs/purchase.py b/bot/dialogs/purchase.py
index a6d4221..0b2b69a 100644
--- a/bot/dialogs/purchase.py
+++ b/bot/dialogs/purchase.py
@@ -14,14 +14,18 @@ from aiogram_dialog.widgets.kbd import (
from aiogram_dialog.widgets.text import Const, Format, Multi
from pydantic import NonNegativeInt
-from bot.getters import (
+from shopbot.bot.getters import (
get_account_details,
get_account_info,
get_accounts,
)
-from bot.getters.filters import get_filters_info, on_filter_selected, update_filters
-from bot.services import on_account_selected, on_buy_button_click
-from bot.states import (
+from shopbot.bot.getters.filters import (
+ get_filters_info,
+ on_filter_selected,
+ update_filters,
+)
+from shopbot.bot.services import on_account_selected, on_buy_button_click
+from shopbot.bot.states import (
PurchaseAccountsSG,
StartSG,
)
diff --git a/bot/dialogs/start.py b/bot/dialogs/start.py
index aaf971f..94c5ea4 100644
--- a/bot/dialogs/start.py
+++ b/bot/dialogs/start.py
@@ -1,9 +1,9 @@
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 bot.getters import username_getter
-from bot.states import StartSG, ProfileSG, PurchaseAccountsSG
+from shopbot.bot.getters import username_getter
+from shopbot.bot.states import ProfileSG, PurchaseAccountsSG, StartSG
start_dialog = Dialog(
Window(
@@ -20,4 +20,4 @@ start_dialog = Dialog(
getter=username_getter,
state=StartSG.start,
)
-)
\ No newline at end of file
+)
diff --git a/bot/getters/accounts.py b/bot/getters/accounts.py
index a12acaa..50abd0d 100644
--- a/bot/getters/accounts.py
+++ b/bot/getters/accounts.py
@@ -5,9 +5,9 @@ from aiogram_dialog import DialogManager
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.db import async_session
-from bot.database.models import Account
-from bot.getters.filters import FilterDTO, FilterType
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import Account
+from shopbot.bot.getters.filters import FilterDTO, FilterType
def _format_account_short_info(account: Account) -> str:
diff --git a/bot/getters/filters.py b/bot/getters/filters.py
index 9a58729..930bb6d 100644
--- a/bot/getters/filters.py
+++ b/bot/getters/filters.py
@@ -6,7 +6,7 @@ from aiogram.types import CallbackQuery, Message
from aiogram_dialog import DialogManager
from pydantic import NonNegativeInt
-from bot.states.states import PurchaseAccountsSG
+from shopbot.bot.states.states import PurchaseAccountsSG
class FilterType(Enum):
diff --git a/bot/getters/history.py b/bot/getters/history.py
index a296f18..095ee14 100644
--- a/bot/getters/history.py
+++ b/bot/getters/history.py
@@ -1,31 +1,31 @@
import logging
+from typing import Any, Dict
from aiogram_dialog import DialogManager
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.models import Account
-from bot.database.db import async_session
-from typing import Dict, Any
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import Account
def _format_account_short_info(account: Account) -> str:
- return (
- f"🌍 {account.region} | 🎮 {account.current_rank} | 💰 {account.price:.2f}₽"
- )
+ return 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
try:
async with async_session() as session:
- result = await session.execute(
+ result = await session.execute(
select(Account).where(Account.buyer == user_tg_id)
)
- purchased_accounts = result.scalars().all()
+ purchased_accounts = result.scalars().all()
if purchased_accounts:
- text = "🛍️ Ваша история покупок:"
+ text = "🛍️ Ваша история покупок:"
else:
logging.warning(f"User with tg_id {user_tg_id} has no purchases")
text = "🛍️ У вас пока нет покупок, пора купить что-нибудь)"
@@ -35,20 +35,25 @@ async def get_purchase_history(dialog_manager: DialogManager, **kwargs) -> Dict[
(_format_account_short_info(account), account.id)
for account in purchased_accounts
],
- "text": text
+ "text": text,
}
except SQLAlchemyError as e:
logging.error(f"Database error: {e}", exc_info=True)
- return {"purchased_accounts": [], "text": "❌ Произошла ошибка при работе с базой данных."}
+ return {
+ "purchased_accounts": [],
+ "text": "❌ Произошла ошибка при работе с базой данных.",
+ }
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
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")
if not account_info:
logging.warning("No account info found in dialog data")
return {"account_info": "❌ Информация об аккаунте недоступна."}
- return {"account_info": account_info}
\ No newline at end of file
+ return {"account_info": account_info}
diff --git a/bot/getters/payment.py b/bot/getters/payment.py
index 68d89d6..63788ba 100644
--- a/bot/getters/payment.py
+++ b/bot/getters/payment.py
@@ -1,10 +1,10 @@
import logging
-from typing import Dict, Any
-from urllib.parse import urlparse, parse_qs
+from typing import Any, Dict
+from urllib.parse import parse_qs, urlparse
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]:
@@ -21,10 +21,14 @@ async def getter_amount(dialog_manager: DialogManager, **kwargs) -> Dict[str, An
return pay_data
except Exception as e:
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)
count = dialog_manager.find("count").get_value()
@@ -39,4 +43,6 @@ async def getter_amount_cryptobot(dialog_manager: DialogManager, **kwargs) -> Di
return pay_data
except Exception as e:
logging.error(f"Error creating CryptoBot paylink: {e}", exc_info=True)
- return {"error": "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Пожалуйста, проверьте настройки и попробуйте снова."}
\ No newline at end of file
+ return {
+ "error": "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Пожалуйста, проверьте настройки и попробуйте снова."
+ }
diff --git a/bot/getters/user.py b/bot/getters/user.py
index d99a7c5..b7cb26f 100644
--- a/bot/getters/user.py
+++ b/bot/getters/user.py
@@ -1,13 +1,13 @@
import logging
-from typing import Dict, Any
+from typing import Any, Dict
from aiogram.types import User
from aiogram_dialog import DialogManager
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.models import UserModel
-from bot.database.db import async_session
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import UserModel
async def username_getter(
@@ -26,12 +26,14 @@ async def username_getter(
"purchased": user.purchased,
}
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 {
"username": event_from_user.username,
"balance": 0,
"purchased": 0,
- }
+ }
except SQLAlchemyError as e:
logging.error(f"Database error: {e}", exc_info=True)
return {
@@ -42,7 +44,7 @@ async def username_getter(
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
return {
- "username": event_from_user.username,
- "balance": 0,
- "purchased": 0,
- }
\ No newline at end of file
+ "username": event_from_user.username,
+ "balance": 0,
+ "purchased": 0,
+ }
diff --git a/bot/services/broadcast.py b/bot/services/broadcast.py
index 8b2e568..e983be4 100644
--- a/bot/services/broadcast.py
+++ b/bot/services/broadcast.py
@@ -1,22 +1,30 @@
import asyncio
import logging
+from aiogram.exceptions import (
+ TelegramAPIError,
+ TelegramForbiddenError,
+ TelegramRetryAfter,
+)
from aiogram_dialog import DialogManager
-from aiogram.exceptions import TelegramRetryAfter, TelegramForbiddenError, TelegramAPIError
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.db import async_session
-from bot.database.models import UserModel
+from shopbot.bot.database.db import async_session
+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):
try:
await bot.send_message(user_id, message_text)
return True
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)
except TelegramForbiddenError:
logging.warning(f"User {user_id} blocked bot")
@@ -49,17 +57,13 @@ async def broadcast_message(dialog_manager: DialogManager, **kwargs):
except SQLAlchemyError as e:
logging.error(f"Database error: {e}")
- return {
- "progress": f"❌ Ошибка при работе с базой данных: {e}"
- }
+ return {"progress": f"❌ Ошибка при работе с базой данных: {e}"}
except Exception as e:
logging.error(f"An unexpected error occurred: {e}")
- return {
- "progress": f"❌ Непредвиденная ошибка: {e}"
- }
+ return {"progress": f"❌ Непредвиденная ошибка: {e}"}
return {
"progress": f"✅ Рассылка завершена!\n"
- f"📨 Всего отправлено: {total_sent}/{total_users}\n"
- f"❌ Ошибок: {total_failed}"
- }
\ No newline at end of file
+ f"📨 Всего отправлено: {total_sent}/{total_users}\n"
+ f"❌ Ошибок: {total_failed}"
+ }
diff --git a/bot/services/buy_account.py b/bot/services/buy_account.py
index 11e9f4d..37c6a39 100644
--- a/bot/services/buy_account.py
+++ b/bot/services/buy_account.py
@@ -7,9 +7,9 @@ from aiogram_dialog.widgets.kbd import Select
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.db import async_session
-from bot.database.models import Account, UserModel
-from bot.states import PurchaseAccountsSG
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import Account, UserModel
+from shopbot.bot.states import PurchaseAccountsSG
ACCOUNT_INFO_TEMPLATE = (
"Подробная информация об аккаунте:\n\n"
diff --git a/bot/services/history.py b/bot/services/history.py
index e574626..37ee405 100644
--- a/bot/services/history.py
+++ b/bot/services/history.py
@@ -1,14 +1,13 @@
import logging
-from aiogram_dialog import DialogManager
from aiogram.types import CallbackQuery
+from aiogram_dialog import DialogManager
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.db import async_session
-from bot.database.models import Account
-from bot.states import PurchaseHistorySG
-
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import Account
+from shopbot.bot.states import PurchaseHistorySG
ACCOUNT_INFO_TEMPLATE = (
"Подробная информация об аккаунте:\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:
if not isinstance(item_id, int):
item_id = int(item_id)
@@ -52,20 +53,24 @@ async def on_history_account_selected(callback: CallbackQuery, selecte, manager:
async with async_session() as session:
async with session.begin():
- account = await session.scalar(select(Account).where(Account.id == item_id))
-
- if account:
- manager.current_context().dialog_data["account_info"] = await _format_account_info(account)
- else:
- logging.warning(f"Account with id {item_id} not found")
- manager.current_context().dialog_data["account_info"] = "Аккаунт не найден!"
+ account = await session.scalar(
+ select(Account).where(Account.id == item_id)
+ )
+ if account:
+ manager.current_context().dialog_data[
+ "account_info"
+ ] = await _format_account_info(account)
+ else:
+ logging.warning(f"Account with id {item_id} not found")
+ manager.current_context().dialog_data["account_info"] = (
+ "Аккаунт не найден!"
+ )
await manager.switch_to(PurchaseHistorySG.details)
-
except SQLAlchemyError as e:
logging.error(f"Database error: {e}", exc_info=True)
except Exception as e:
- logging.error(f"An unexpected error occurred: {e}", exc_info=True)
\ No newline at end of file
+ logging.error(f"An unexpected error occurred: {e}", exc_info=True)
diff --git a/bot/services/payments.py b/bot/services/payments.py
index d7cdcc3..75ea465 100644
--- a/bot/services/payments.py
+++ b/bot/services/payments.py
@@ -1,15 +1,15 @@
import logging
from typing import Tuple
-from AsyncPayments.lolz import AsyncLolzteamMarketPayment
-from AsyncPayments.cryptoBot import AsyncCryptoBot
from aiogram.types import CallbackQuery
from aiogram_dialog import DialogManager, StartMode
from aiogram_dialog.widgets.kbd import Button
-
-from bot.database import update_balance
+from AsyncPayments.cryptoBot import AsyncCryptoBot
+from AsyncPayments.lolz import AsyncLolzteamMarketPayment
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.read_env()
@@ -28,15 +28,35 @@ async def create_paylink_lolz(amount: int) -> str:
async def create_paylink_cryptobot(amount: int) -> Tuple[str, str]:
try:
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)
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)
- return None, "Сумма для пополнения должна быть не менее 0.01 USD (примерно 1 руб). Пожалуйста, проверьте и попробуйте снова, либо выберите другой способ оплаты."
- logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True)
- return None, "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Попробуйте позже."
+ return (
+ None,
+ "Сумма для пополнения должна быть не менее 0.01 USD (примерно 1 руб). Пожалуйста, проверьте и попробуйте снова, либо выберите другой способ оплаты.",
+ )
+ logging.error(f"Error creating CryptoBot invoice: {e}", exc_info=True)
+ return (
+ None,
+ "Произошла ошибка при создании ссылки для оплаты через CryptoBot. Попробуйте позже.",
+ )
async def check_pay_lolz(
@@ -44,14 +64,18 @@ async def check_pay_lolz(
):
pay_data = manager.current_context().dialog_data.get("pay_data")
if not pay_data:
- await callback.message.answer("Ошибка: данные оплаты не найдены. Попробуйте еще раз. ❌")
+ await callback.message.answer(
+ "Ошибка: данные оплаты не найдены. Попробуйте еще раз. ❌"
+ )
return
order_id = pay_data.get("order_id")
amount = pay_data.get("amount")
if not order_id or not amount:
- await callback.message.answer("Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌")
+ await callback.message.answer(
+ "Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌"
+ )
return
if manager.current_context().dialog_data.get("is_payment_processed", False):
await callback.answer("Оплата уже обработана.", show_alert=True)
@@ -65,13 +89,19 @@ async def check_pay_lolz(
if status:
manager.current_context().dialog_data["is_payment_processed"] = True
await update_balance(callback.from_user.id, amount)
- await callback.message.edit_text(f"Поздравляем, счет пополнен на {amount} руб 🎉")
+ await callback.message.edit_text(
+ f"Поздравляем, счет пополнен на {amount} руб 🎉"
+ )
else:
- await callback.message.answer("Счет не оплачен, проверьте оплату или проверьте еще раз! ⚠️")
+ await callback.message.answer(
+ "Счет не оплачен, проверьте оплату или проверьте еще раз! ⚠️"
+ )
except Exception as e:
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(
@@ -80,14 +110,18 @@ async def check_pay_crypto_bot(
pay_data = manager.current_context().dialog_data.get("pay_data")
if not pay_data:
- await callback.message.answer("Ошибка: данные для оплаты не найдены. Попробуйте позже. ❌")
+ await callback.message.answer(
+ "Ошибка: данные для оплаты не найдены. Попробуйте позже. ❌"
+ )
return
order_id = pay_data.get("order_id")
amount = pay_data.get("amount")
if not order_id or not amount:
- await callback.message.answer("Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌")
+ await callback.message.answer(
+ "Ошибка: неверные данные оплаты. Попробуйте еще раз. ❌"
+ )
return
if manager.current_context().dialog_data.get("is_payment_processed", False):
await callback.answer("Оплата уже обработана.", show_alert=True)
@@ -105,7 +139,9 @@ async def check_pay_crypto_bot(
if invoice.status == "paid":
manager.current_context().dialog_data["is_payment_processed"] = True
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 manager.start(state=ProfileSG.profile, mode=StartMode.RESET_STACK)
else:
@@ -113,4 +149,6 @@ async def check_pay_crypto_bot(
await callback.message.answer("Оплата не найдена. Попробуйте позже. ⏳")
except Exception as e:
logging.error(f"Error checking CryptoBot payment: {e}", exc_info=True)
- await callback.message.answer("Произошла ошибка при проверке оплаты через CryptoBot. Попробуйте позже. ❌")
\ No newline at end of file
+ await callback.message.answer(
+ "Произошла ошибка при проверке оплаты через CryptoBot. Попробуйте позже. ❌"
+ )
diff --git a/bot/services/stats.py b/bot/services/stats.py
index 17df3e6..e787822 100644
--- a/bot/services/stats.py
+++ b/bot/services/stats.py
@@ -6,8 +6,8 @@ from aiogram_dialog import DialogManager
from sqlalchemy import func, select
from sqlalchemy.exc import SQLAlchemyError
-from bot.database.db import async_session
-from bot.database.models import Account, UserModel
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import Account, UserModel
def _get_start_of_day():
diff --git a/bot/services/user.py b/bot/services/user.py
index 27993fa..8c7c5c0 100644
--- a/bot/services/user.py
+++ b/bot/services/user.py
@@ -1,13 +1,13 @@
import logging
-from typing import Dict, Any
+from typing import Any, Dict
from aiogram_dialog import DialogManager
from sqlalchemy import select
-from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy.ext.asyncio import AsyncSession
-from bot.database.models import UserModel
-from bot.database.db import async_session
+from shopbot.bot.database.db import async_session
+from shopbot.bot.database.models import UserModel
RESULT_MESSAGES = {
"not_enough_funds": "❌ Недостаточно средств на балансе пользователя!",
@@ -23,7 +23,7 @@ async def _get_user_and_validate(
session: AsyncSession, user_id: str, amount: str
) -> Dict[str, Any]:
if not user_id or not amount:
- return {"result": RESULT_MESSAGES["no_user_id_or_amount"]}
+ return {"result": RESULT_MESSAGES["no_user_id_or_amount"]}
try:
user_id = int(user_id)
amount = float(amount)
@@ -59,14 +59,14 @@ async def take_balance_user(dialog_manager: DialogManager, **kwargs) -> Dict[str
await session.commit()
return {
"result": RESULT_MESSAGES["balance_decreased"].format(
- username=user.username, amount=amount
- )
+ username=user.username, amount=amount
+ )
}
else:
- return {"result": RESULT_MESSAGES["not_enough_funds"]}
+ return {"result": RESULT_MESSAGES["not_enough_funds"]}
except SQLAlchemyError as e:
- logging.error(f"Database error: {e}", exc_info=True)
- return {"result": "❌ Произошла ошибка при работе с базой данных."}
+ logging.error(f"Database error: {e}", exc_info=True)
+ return {"result": "❌ Произошла ошибка при работе с базой данных."}
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
return {"result": "❌ Произошла непредвиденная ошибка."}
@@ -83,16 +83,16 @@ async def gift_balance_data(dialog_manager: DialogManager, **kwargs) -> Dict[str
user = user_data["user"]
amount = user_data["amount"]
try:
- user.balance += amount
- await session.commit()
- return {
- "result": RESULT_MESSAGES["balance_increased"].format(
- username=user.username, amount=amount
- )
- }
+ user.balance += amount
+ await session.commit()
+ return {
+ "result": RESULT_MESSAGES["balance_increased"].format(
+ username=user.username, amount=amount
+ )
+ }
except SQLAlchemyError as e:
- logging.error(f"Database error: {e}", exc_info=True)
- return {"result": "❌ Произошла ошибка при работе с базой данных."}
+ logging.error(f"Database error: {e}", exc_info=True)
+ return {"result": "❌ Произошла ошибка при работе с базой данных."}
except Exception as e:
- logging.error(f"An unexpected error occurred: {e}", exc_info=True)
- return {"result": "❌ Произошла непредвиденная ошибка."}
\ No newline at end of file
+ logging.error(f"An unexpected error occurred: {e}", exc_info=True)
+ return {"result": "❌ Произошла непредвиденная ошибка."}
diff --git a/consumers/new_account.py b/consumers/new_account.py
new file mode 100644
index 0000000..e0c3127
--- /dev/null
+++ b/consumers/new_account.py
@@ -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)
diff --git a/hello.py b/hello.py
index 2c350d3..102f9d6 100644
--- a/hello.py
+++ b/hello.py
@@ -1,4 +1,4 @@
-from bot.getters.filters import FilterType
+from shopbot.bot.getters.filters import FilterType
for x in FilterType:
print(x.name, x.value)