From 5c18e22b806ad22276678c1151e2fb73f1191de8 Mon Sep 17 00:00:00 2001 From: geekiot Date: Fri, 22 Aug 2025 21:11:08 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=80=D1=82=D1=84=D0=BE=D0=BB?= =?UTF-8?q?=D0=B8=D0=BE:=20=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mousey/Bot/Filters/chat_type.py | 8 +- Mousey/Bot/Filters/user_role.py | 22 +-- Mousey/Bot/Filters/utils.py | 13 +- Mousey/Bot/Handlers/Admin/__init__.py | 25 ++-- Mousey/Bot/Handlers/Admin/info.py | 7 +- Mousey/Bot/Handlers/Admin/menu.py | 12 +- Mousey/Bot/Handlers/Admin/news.py | 69 ++++++--- Mousey/Bot/Handlers/Admin/utils.py | 27 ++-- Mousey/Bot/Handlers/Private/__init__.py | 58 +++++--- Mousey/Bot/Handlers/Private/menu.py | 13 +- Mousey/Bot/Handlers/Private/news.py | 78 ++++++----- Mousey/Bot/Handlers/Private/utils.py | 19 +-- Mousey/Bot/Handlers/__init__.py | 9 +- Mousey/Bot/Keyboards/__init__.py | 1 - Mousey/Bot/Keyboards/inline.py | 27 ++-- Mousey/Bot/Keyboards/utils.py | 19 ++- Mousey/Bot/Middlewares/__init__.py | 6 +- Mousey/Bot/Middlewares/database.py | 8 +- Mousey/Bot/States/__init__.py | 1 - Mousey/Bot/States/offer_news.py | 1 - Mousey/Bot/__init__.py | 1 - Mousey/Bot/settings.py | 25 ++-- Mousey/Bot/start.py | 23 +-- Mousey/Database/Models/__init__.py | 1 - Mousey/Database/Models/base.py | 12 +- Mousey/Database/Models/news.py | 20 ++- Mousey/Database/Models/user.py | 20 ++- Mousey/Database/utils.py | 178 ++++++++++++++---------- Mousey/Misc/__init__.py | 16 ++- Mousey/Redis/__init__.py | 4 +- Mousey/__main__.py | 7 +- 31 files changed, 447 insertions(+), 283 deletions(-) diff --git a/Mousey/Bot/Filters/chat_type.py b/Mousey/Bot/Filters/chat_type.py index fafc01e..6f921d0 100644 --- a/Mousey/Bot/Filters/chat_type.py +++ b/Mousey/Bot/Filters/chat_type.py @@ -6,12 +6,15 @@ from aiogram.types import Message, CallbackQuery class ChatTypeFilter(BaseFilter): """ - Фильтрация обновлений в зависимости от чата. + Фильтрация обновлений в зависимости от чата. """ + def __init__(self, chat_type: Union[str, list]) -> None: self.chat_type = chat_type - async def __call__(self, update: Union[Message, CallbackQuery]) -> bool: + async def __call__( + self, update: Union[Message, CallbackQuery] + ) -> bool: if isinstance(update, Message): chat_type = update.chat.type elif isinstance(update, CallbackQuery): @@ -21,4 +24,3 @@ class ChatTypeFilter(BaseFilter): return chat_type == self.chat_type else: return chat_type in self.chat_type - diff --git a/Mousey/Bot/Filters/user_role.py b/Mousey/Bot/Filters/user_role.py index 5463b32..9f65f87 100644 --- a/Mousey/Bot/Filters/user_role.py +++ b/Mousey/Bot/Filters/user_role.py @@ -8,22 +8,24 @@ from Mousey.Database import check_user class UserRoleFilter(BaseFilter): - ''' - Фильтрация сообщений на основе их роли в БД. - ''' + """ + Фильтрация сообщений на основе их роли в БД. + """ + def __init__(self, user_role: Union[UserRole, list]) -> None: if isinstance(user_role, list): - self.user_role = [ role.value for role in user_role ] + self.user_role = [role.value for role in user_role] else: - self.user_role = [ user_role.value ] + self.user_role = [user_role.value] - async def __call__(self, update: Union[Message, CallbackQuery], session) -> bool: + async def __call__( + self, update: Union[Message, CallbackQuery], session + ) -> bool: if isinstance(update, Message): telegram_id = update.from_user.id elif isinstance(update, CallbackQuery): telegram_id = update.from_user.id - - user = await check_user(session, telegram_id) - - return user.role in self.user_role + user = await check_user(session, telegram_id) + + return user.role in self.user_role diff --git a/Mousey/Bot/Filters/utils.py b/Mousey/Bot/Filters/utils.py index 7bd91a1..f76f2bd 100644 --- a/Mousey/Bot/Filters/utils.py +++ b/Mousey/Bot/Filters/utils.py @@ -2,16 +2,19 @@ from aiogram import Router from aiogram.filters import BaseFilter -def add_filters(router: Router, update_type: str, *filters: BaseFilter) -> None: +def add_filters( + router: Router, + update_type: str, + *filters: BaseFilter, +) -> None: """ - Добавить фильтр на указанных тип обновлений к перечисленным роутерам. + Добавить фильтр на указанных тип обновлений к перечисленным роутерам. - update_type: str = "message", "callback" или "all". + update_type: str = "message", "callback" или "all". """ for filter in filters: if update_type in ("message", "all"): router.message.filter(filter) - + if update_type in ("callback", "all"): router.callback_query.filter(filter) - diff --git a/Mousey/Bot/Handlers/Admin/__init__.py b/Mousey/Bot/Handlers/Admin/__init__.py index ca84861..31d1235 100644 --- a/Mousey/Bot/Handlers/Admin/__init__.py +++ b/Mousey/Bot/Handlers/Admin/__init__.py @@ -27,7 +27,7 @@ from .news import ( def __setup_admin_router() -> Router: """ - Регистрация событий для роутера администрации бота. + Регистрация событий для роутера администрации бота. """ router = Router() @@ -35,15 +35,21 @@ def __setup_admin_router() -> Router: ### Меню ### ############ router.message.register(cmd_admin_menu, Command("admin")) - router.callback_query.register(call_admin_menu, F.data == "admin_menu") + router.callback_query.register( + call_admin_menu, F.data == "admin_menu" + ) - router.callback_query.register(call_admin_commands, F.data == "admin_commands") + router.callback_query.register( + call_admin_commands, F.data == "admin_commands" + ) ####################### ### Сбор информации ### ####################### - router.message.register(cmd_admin_database_info, Command("database_info")) - + router.message.register( + cmd_admin_database_info, Command("database_info") + ) + ############## ### Разное ### ############## @@ -57,12 +63,14 @@ def __setup_admin_router() -> Router: ########################## ### Модерация новостей ### ########################## - router.callback_query.register(call_news_menu, F.data == "admin_news_menu") + router.callback_query.register( + call_news_menu, F.data == "admin_news_menu" + ) router.callback_query.register( call_news_favorite, F.data == "admin_news_favorite", ) - + # Просмотр новостей router.callback_query.register( call_news_offer_menu, @@ -70,7 +78,6 @@ def __setup_admin_router() -> Router: ) logger.success("Роутер для модерации готов.") - + # Вывод роутера return router - diff --git a/Mousey/Bot/Handlers/Admin/info.py b/Mousey/Bot/Handlers/Admin/info.py index 53523fe..10a7da8 100644 --- a/Mousey/Bot/Handlers/Admin/info.py +++ b/Mousey/Bot/Handlers/Admin/info.py @@ -5,9 +5,11 @@ from sqlalchemy.ext.asyncio import AsyncSession from Mousey.Database import get_database_data -async def cmd_admin_database_info(message: Message, session: AsyncSession) -> None: +async def cmd_admin_database_info( + message: Message, session: AsyncSession +) -> None: """ - Получить всю важную информацию из БД. + Получить всю важную информацию из БД. """ data = await get_database_data(session) @@ -17,4 +19,3 @@ async def cmd_admin_database_info(message: Message, session: AsyncSession) -> No news_count=data["news_count"], ), ) - diff --git a/Mousey/Bot/Handlers/Admin/menu.py b/Mousey/Bot/Handlers/Admin/menu.py index 6c86225..271bc1e 100644 --- a/Mousey/Bot/Handlers/Admin/menu.py +++ b/Mousey/Bot/Handlers/Admin/menu.py @@ -1,7 +1,10 @@ from aiogram.utils.i18n import gettext as _ from aiogram.types import Message, CallbackQuery -from Mousey.Bot.Keyboards import get_admin_menu_markup, get_back_markup +from Mousey.Bot.Keyboards import ( + get_admin_menu_markup, + get_back_markup, +) ################# @@ -9,7 +12,7 @@ from Mousey.Bot.Keyboards import get_admin_menu_markup, get_back_markup ################# async def cmd_admin_menu(message: Message) -> None: """ - Вызов меню для администрации командой. + Вызов меню для администрации командой. """ await message.answer( text=_("Админ меню"), @@ -22,7 +25,7 @@ async def cmd_admin_menu(message: Message) -> None: ############# async def call_admin_menu(call: CallbackQuery) -> None: """ - Вызов меню для администрации с помощью Callback'а. + Вызов меню для администрации с помощью Callback'а. """ await call.message.edit_text( text=_("Админ меню"), @@ -32,10 +35,9 @@ async def call_admin_menu(call: CallbackQuery) -> None: async def call_admin_commands(call: CallbackQuery) -> None: """ - Просмотр команд для администратора. + Просмотр команд для администратора. """ await call.message.edit_text( text=_("Список админ команд"), reply_markup=get_back_markup(callback_data="admin_menu"), ) - diff --git a/Mousey/Bot/Handlers/Admin/news.py b/Mousey/Bot/Handlers/Admin/news.py index d1485dc..e41e2f7 100644 --- a/Mousey/Bot/Handlers/Admin/news.py +++ b/Mousey/Bot/Handlers/Admin/news.py @@ -25,8 +25,12 @@ def __get_offer_text(news) -> str: # Стандартная информация для новости if news is not None: telegram_id = news.tg_id - telegram_username = news.tg_username or _("Админ меню новости, профиль скрыт") - text = news.text[:512] + "..." if len(news.text) >= 512 else "" + telegram_username = news.tg_username or _( + "Админ меню новости, профиль скрыт" + ) + text = ( + news.text[:512] + "..." if len(news.text) >= 512 else "" + ) # Опциональное получение контактов contact = news.contact @@ -37,12 +41,16 @@ def __get_offer_text(news) -> str: else: contact = _("Админ меню новости, контакт не указан") - return _("Админ меню новости, информация о новости").format( + return ( + _("Админ меню новости, информация о новости").format( telegram_id=telegram_id, telegram_username=telegram_username, text=text, contact=contact, - ) if news is not None else _("Админ меню новости непрочитанных нет") + ) + if news is not None + else _("Админ меню новости непрочитанных нет") + ) ############## @@ -50,7 +58,7 @@ def __get_offer_text(news) -> str: ############## async def call_news_menu(call: CallbackQuery) -> None: """ - Админ-меню для просмотра предложенных новостей. + Админ-меню для просмотра предложенных новостей. """ await call.message.edit_text( text=_("Админ меню новости"), @@ -58,19 +66,23 @@ async def call_news_menu(call: CallbackQuery) -> None: ) -async def call_news_favorite(call: CallbackQuery, session: AsyncSession) -> None: +async def call_news_favorite( + call: CallbackQuery, session: AsyncSession +) -> None: """ - Избранные новости для редактирования и использования. + Избранные новости для редактирования и использования. """ await call.message.edit_text( text=_("Функция в разработке"), - reply_markup=get_back_markup("Назад", "admin_news_menu") + reply_markup=get_back_markup("Назад", "admin_news_menu"), ) -async def call_news_offer_menu(call: CallbackQuery, session: AsyncSession): +async def call_news_offer_menu( + call: CallbackQuery, session: AsyncSession +): """ - Меню для работы с предложенными новостями через Callback'и. + Меню для работы с предложенными новостями через Callback'и. """ data = call.data.split("_") news_id = int(data[3]) @@ -81,21 +93,25 @@ async def call_news_offer_menu(call: CallbackQuery, session: AsyncSession): await call.message.edit_text( text=__get_offer_text(news), - reply_markup=get_back_markup(callback_data="admin_news_menu") if news is None \ + reply_markup=( + get_back_markup(callback_data="admin_news_menu") + if news is None else get_admin_news_offer_markup(news) + ), ) return # Обработка callback'а с действием step = data[4] - + # Выбрана распечатка новости if step == "print": news = await get_news(session, news_id) await call.message.answer(text=call.message.text) await call.message.answer(text=news.text) await call.message.answer( - text=news.contact or _("Админ меню новости, контакт не указан") + text=news.contact + or _("Админ меню новости, контакт не указан") ) return @@ -115,26 +131,37 @@ async def call_news_offer_menu(call: CallbackQuery, session: AsyncSession): user = await check_user(session, news.tg_id) reasons = { - UserRole.USER.value: _("Админ новости, автор новости забанен"), - UserRole.BANNED.value: _("Админ новости, автор новости уже был забанен"), + UserRole.USER.value: _( + "Админ новости, автор новости забанен" + ), + UserRole.BANNED.value: _( + "Админ новости, автор новости уже был забанен" + ), } if reasons.get(user.role) is not None: await see_news(session, news_id) - await update_user_role(session, user.tg_id, UserRole.BANNED) + await update_user_role( + session, user.tg_id, UserRole.BANNED + ) await call.answer( - text=reasons.get(user.role, _("Админ новости, нельзя забанить администратора")), + text=reasons.get( + user.role, + _("Админ новости, нельзя забанить администратора"), + ), show_alert=True, ) return # Выбрана следующая или предыдущая новость - news = await get_next_unseen_news(session, news_id) if step == "next" else \ - await get_prev_unseen_news(session, news_id) + news = ( + await get_next_unseen_news(session, news_id) + if step == "next" + else await get_prev_unseen_news(session, news_id) + ) await call.message.edit_text( text=__get_offer_text(news), - reply_markup=get_admin_news_offer_markup(news=news) + reply_markup=get_admin_news_offer_markup(news=news), ) - diff --git a/Mousey/Bot/Handlers/Admin/utils.py b/Mousey/Bot/Handlers/Admin/utils.py index 4e4b132..daaccf0 100644 --- a/Mousey/Bot/Handlers/Admin/utils.py +++ b/Mousey/Bot/Handlers/Admin/utils.py @@ -9,7 +9,7 @@ from Mousey.Database import update_user_role async def cmd_sticker_id(message: Message): """ - Отправка ID стикера. + Отправка ID стикера. """ await message.answer( text=str(message.sticker.file_id), @@ -17,25 +17,30 @@ async def cmd_sticker_id(message: Message): async def cmd_update_role( - message: Message, - command: CommandObject, - session: AsyncSession, - ) -> None: + message: Message, + command: CommandObject, + session: AsyncSession, +) -> None: """ - Обновление роли по ID. + Обновление роли по ID. """ - args = command.args if command.args is None else command.args.split() + args = ( + command.args if command.args is None else command.args.split() + ) roles = [role.value for role in UserRole] - if args is None or not (len(args) == 2 and args[0] in roles and args[1].isdigit()): + if args is None or not ( + len(args) == 2 and args[0] in roles and args[1].isdigit() + ): await message.answer( - text=_("Обновление роли, необходимо ввести существующую роль").format(roles=roles), + text=_( + "Обновление роли, необходимо ввести существующую роль" + ).format(roles=roles), ) return - + await update_user_role(session, int(args[1]), args[0]) await message.answer( text=_("Обновление роли, роль успешно обновлена"), ) - diff --git a/Mousey/Bot/Handlers/Private/__init__.py b/Mousey/Bot/Handlers/Private/__init__.py index d20c541..9c19a5b 100644 --- a/Mousey/Bot/Handlers/Private/__init__.py +++ b/Mousey/Bot/Handlers/Private/__init__.py @@ -8,7 +8,12 @@ from aiogram.filters import Command from Mousey.Bot.States import OfferNews from .utils import cmd_get_stickers, cmd_cancel -from .menu import cmd_menu, call_menu, call_useful_info, call_about_bot_info +from .menu import ( + cmd_menu, + call_menu, + call_useful_info, + call_about_bot_info, +) from .news import ( call_news_menu, cmd_news_offer, @@ -24,7 +29,7 @@ from .news import ( def __setup_private_router() -> Router: """ - Регистрация событий для роутера пользователей. + Регистрация событий для роутера пользователей. """ router = Router() @@ -33,30 +38,46 @@ def __setup_private_router() -> Router: ######################## router.message.register(cmd_cancel, Command("cancel")) router.message.register(cmd_get_stickers, Command("get_stickers")) - + ######################### ### Главное меню бота ### ######################### - router.message.register(cmd_menu, Command(commands=["start", "menu"])) + router.message.register( + cmd_menu, Command(commands=["start", "menu"]) + ) router.callback_query.register(call_menu, F.data == "menu") - router.callback_query.register(call_useful_info, F.data == "useful_info") - router.callback_query.register(call_about_bot_info, F.data == "about_bot_info") + router.callback_query.register( + call_useful_info, F.data == "useful_info" + ) + router.callback_query.register( + call_about_bot_info, F.data == "about_bot_info" + ) ###################### ### Новостное меню ### ###################### - router.callback_query.register(call_news_menu, F.data == "news_menu") - + router.callback_query.register( + call_news_menu, F.data == "news_menu" + ) + # Статистика новостей - router.callback_query.register(call_news_statistics, F.data == "news_statistics") - + router.callback_query.register( + call_news_statistics, F.data == "news_statistics" + ) + # Меню, для предложки новостей - router.callback_query.register(call_news_offer, F.data == "news_offer") + router.callback_query.register( + call_news_offer, F.data == "news_offer" + ) # Кнопки при предложении новости - router.callback_query.register(call_input_news_text, F.data == "news_input_text") - router.callback_query.register(call_input_news_contact, F.data == "news_input_contact") + router.callback_query.register( + call_input_news_text, F.data == "news_input_text" + ) + router.callback_query.register( + call_input_news_contact, F.data == "news_input_contact" + ) # Обработка ввода текста для предложки router.message.register( @@ -79,12 +100,15 @@ def __setup_private_router() -> Router: ) # Отправить новость - router.callback_query.register(call_news_offer_send, F.data == "news_offer_send") + router.callback_query.register( + call_news_offer_send, F.data == "news_offer_send" + ) # Отменить отправку новости - router.callback_query.register(call_news_offer_cancel, F.data == "news_offer_cancel") - + router.callback_query.register( + call_news_offer_cancel, F.data == "news_offer_cancel" + ) + logger.success("Роутер для ЛС готов.") return router - diff --git a/Mousey/Bot/Handlers/Private/menu.py b/Mousey/Bot/Handlers/Private/menu.py index 34d950c..aaf38e4 100644 --- a/Mousey/Bot/Handlers/Private/menu.py +++ b/Mousey/Bot/Handlers/Private/menu.py @@ -12,7 +12,7 @@ from Mousey.Bot.Keyboards import get_menu_markup, get_back_markup ################# async def cmd_menu(message: Message, session: AsyncSession) -> None: """ - Отправка главного меню бота сообщением. + Отправка главного меню бота сообщением. """ await check_user( session=session, @@ -28,9 +28,11 @@ async def cmd_menu(message: Message, session: AsyncSession) -> None: ####################### ### Обратные вызовы ### ####################### -async def call_menu(call: CallbackQuery, session: AsyncSession) -> None: +async def call_menu( + call: CallbackQuery, session: AsyncSession +) -> None: """ - Вызов главного меню с помощью колбека. + Вызов главного меню с помощью колбека. """ await check_user( session=session, @@ -45,7 +47,7 @@ async def call_menu(call: CallbackQuery, session: AsyncSession) -> None: async def call_useful_info(call: CallbackQuery): """ - Полезные ссылки и прочая информация в главном меню. + Полезные ссылки и прочая информация в главном меню. """ user_id = call.from_user.id @@ -57,10 +59,9 @@ async def call_useful_info(call: CallbackQuery): async def call_about_bot_info(call: CallbackQuery): """ - Информация о боте в главном меню. + Информация о боте в главном меню. """ await call.message.edit_text( text=_("Информация о боте"), reply_markup=get_back_markup(), ) - diff --git a/Mousey/Bot/Handlers/Private/news.py b/Mousey/Bot/Handlers/Private/news.py index 9a786a7..b39cf17 100644 --- a/Mousey/Bot/Handlers/Private/news.py +++ b/Mousey/Bot/Handlers/Private/news.py @@ -24,7 +24,7 @@ from Mousey.Bot.Keyboards import ( ####################### async def __get_news_offer_text(state: FSMContext) -> str: data = await state.get_data() - + news_text = _("Текст для новости отсутствует") news_contact = _("Контакты для новости отсутствуют") @@ -34,9 +34,9 @@ async def __get_news_offer_text(state: FSMContext) -> str: ) if data.get("news_contact") is not None: - news_contact = _("Шаблон для вставки контактов новости").format( - contact=data["news_contact"][:256] - ) + news_contact = _( + "Шаблон для вставки контактов новости" + ).format(contact=data["news_contact"][:256]) news_text += "..." if len(news_text) >= 512 else "" news_contact += "..." if len(news_contact) >= 256 else "" @@ -50,10 +50,13 @@ async def __get_news_offer_text(state: FSMContext) -> str: def __check_user_for_offer(data: dict, user) -> bool: if user.role in (UserRole.ADMIN.value, UserRole.MAIN_ADMIN.value): return data.get("news_text") is not None - + if user.role == UserRole.USER.value: - return data.get("news_text") is not None and user.unseen_news <= 3 - + return ( + data.get("news_text") is not None + and user.unseen_news <= 3 + ) + return False @@ -62,7 +65,7 @@ def __check_user_for_offer(data: dict, user) -> bool: ################# async def cmd_news_offer(message: Message, state: FSMContext) -> None: """ - Меню, чтобы предложить новость. + Меню, чтобы предложить новость. """ current_state = await state.get_state() @@ -80,9 +83,11 @@ async def cmd_news_offer(message: Message, state: FSMContext) -> None: ) -async def cmd_news_input_error(message: Message, state: FSMContext) -> None: +async def cmd_news_input_error( + message: Message, state: FSMContext +) -> None: """ - Некоректная отправка сообщения для предложки. + Некоректная отправка сообщения для предложки. """ await message.answer( text=_("Неправильная форма данных для новости"), @@ -94,7 +99,7 @@ async def cmd_news_input_error(message: Message, state: FSMContext) -> None: ############## async def call_news_menu(call: CallbackQuery) -> None: """ - Вызов новостного меню. + Вызов новостного меню. """ await call.message.edit_text( text=_("Новостное меню"), @@ -102,11 +107,15 @@ async def call_news_menu(call: CallbackQuery) -> None: ) -async def call_news_statistics(call: CallbackQuery, session: AsyncSession) -> None: +async def call_news_statistics( + call: CallbackQuery, session: AsyncSession +) -> None: """ - Статистика новостей пользователя. + Статистика новостей пользователя. """ - news_statistics = await get_news_statistics(session, int(call.from_user.id)) + news_statistics = await get_news_statistics( + session, int(call.from_user.id) + ) await call.message.edit_text( text=_("Шаблон для статистики новостей").format( @@ -117,9 +126,11 @@ async def call_news_statistics(call: CallbackQuery, session: AsyncSession) -> No ) -async def call_news_offer(call: CallbackQuery, state: FSMContext) -> None: +async def call_news_offer( + call: CallbackQuery, state: FSMContext +) -> None: """ - Меню, чтобы предложить новость. + Меню, чтобы предложить новость. """ await state.set_state() @@ -129,12 +140,14 @@ async def call_news_offer(call: CallbackQuery, state: FSMContext) -> None: ) -async def call_input_news_text(call: CallbackQuery, state: FSMContext) -> None: +async def call_input_news_text( + call: CallbackQuery, state: FSMContext +) -> None: """ - Сообщение для ввода текста для новости. + Сообщение для ввода текста для новости. """ await state.set_state(OfferNews.typing_text) - + await call.message.edit_text( text=_("Ввести текст для новости"), reply_markup=get_back_markup( @@ -144,9 +157,11 @@ async def call_input_news_text(call: CallbackQuery, state: FSMContext) -> None: ) -async def call_input_news_contact(call: CallbackQuery, state: FSMContext) -> None: +async def call_input_news_contact( + call: CallbackQuery, state: FSMContext +) -> None: """ - Сообщение для ввода контактов для новости. + Сообщение для ввода контактов для новости. """ await state.set_state(OfferNews.typing_contact) @@ -159,17 +174,19 @@ async def call_input_news_contact(call: CallbackQuery, state: FSMContext) -> Non ) -async def call_news_offer_cancel(call: CallbackQuery, state: FSMContext): +async def call_news_offer_cancel( + call: CallbackQuery, state: FSMContext +): await call_cancel(call, state, callback_data="news_menu") async def call_news_offer_send( - call: CallbackQuery, - state: FSMContext, - session: AsyncSession, - ) -> None: + call: CallbackQuery, + state: FSMContext, + session: AsyncSession, +) -> None: """ - Сообщение об отправке новости. + Сообщение об отправке новости. """ data = await state.get_data() user = await check_user(session, call.from_user.id) @@ -181,20 +198,20 @@ async def call_news_offer_send( telegram_username=call.from_user.username, text=data["news_text"], contact=data.get("news_contact"), - ) + ) await call.message.edit_text( text=_("Новость успешно отправлена"), reply_markup=get_back_markup(callback_data="news_menu"), ) await state.clear() return - + reasons = { "text": _("Отсутствует текст для новости"), "banned": _("Вы забанены"), "limite": _("Превышен лимит непрочитанных новостей"), } - + if data.get("news_text") is None: reason = reasons["text"] @@ -209,4 +226,3 @@ async def call_news_offer_send( reply_markup=get_back_markup(callback_data="news_menu"), ) await state.clear() - diff --git a/Mousey/Bot/Handlers/Private/utils.py b/Mousey/Bot/Handlers/Private/utils.py index d76d0e8..1729f0d 100644 --- a/Mousey/Bot/Handlers/Private/utils.py +++ b/Mousey/Bot/Handlers/Private/utils.py @@ -10,11 +10,9 @@ from Mousey.Bot.Keyboards import get_back_markup async def cmd_get_stickers(message: Message): """ - Отправка случайного школьного стикера. + Отправка случайного школьного стикера. """ - await message.answer( - text=_("Информация про набор стикеров") - ) + await message.answer(text=_("Информация про набор стикеров")) await message.answer_sticker( sticker=choice(stickers_id), @@ -23,7 +21,7 @@ async def cmd_get_stickers(message: Message): async def cmd_cancel(message: Message, state: FSMContext): """ - Отмена текущещей операции и очистка данных пользователя. + Отмена текущещей операции и очистка данных пользователя. """ await state.clear() @@ -32,14 +30,17 @@ async def cmd_cancel(message: Message, state: FSMContext): ) -async def call_cancel(call: CallbackQuery, state: FSMContext, callback_data: str = "menu"): +async def call_cancel( + call: CallbackQuery, + state: FSMContext, + callback_data: str = "menu", +): """ - Отмена текущещей операции и очистка данных пользователя. + Отмена текущещей операции и очистка данных пользователя. """ await state.clear() await call.message.edit_text( text=_("Отмена выполнения текущей операции"), - reply_markup=get_back_markup(callback_data=callback_data) + reply_markup=get_back_markup(callback_data=callback_data), ) - diff --git a/Mousey/Bot/Handlers/__init__.py b/Mousey/Bot/Handlers/__init__.py index e649475..986e19c 100644 --- a/Mousey/Bot/Handlers/__init__.py +++ b/Mousey/Bot/Handlers/__init__.py @@ -6,12 +6,16 @@ from .Admin import __setup_admin_router from .Private import __setup_private_router from Mousey.Misc import UserRole -from Mousey.Bot.Filters import add_filters, ChatTypeFilter, UserRoleFilter +from Mousey.Bot.Filters import ( + add_filters, + ChatTypeFilter, + UserRoleFilter, +) def setup_routers(dispatcher: Router) -> None: """ - Настройка всех роутеров и подключение их к диспетчеру. + Настройка всех роутеров и подключение их к диспетчеру. """ # Пользовательский роутер для ЛС бота private_router = __setup_private_router() @@ -39,4 +43,3 @@ def setup_routers(dispatcher: Router) -> None: private_router, admin_router, ) - diff --git a/Mousey/Bot/Keyboards/__init__.py b/Mousey/Bot/Keyboards/__init__.py index e46cff0..ea16669 100644 --- a/Mousey/Bot/Keyboards/__init__.py +++ b/Mousey/Bot/Keyboards/__init__.py @@ -17,4 +17,3 @@ from .inline import ( get_admin_news_markup, get_admin_news_offer_markup, ) - diff --git a/Mousey/Bot/Keyboards/inline.py b/Mousey/Bot/Keyboards/inline.py index d554d0b..71be52a 100644 --- a/Mousey/Bot/Keyboards/inline.py +++ b/Mousey/Bot/Keyboards/inline.py @@ -7,11 +7,10 @@ from .utils import create_callback_markup ### Пользовательские ### ######################## def get_back_markup( - button_name: str = "Назад", - callback_data: str = "menu" - ) -> InlineKeyboardMarkup: + button_name: str = "Назад", callback_data: str = "menu" +) -> InlineKeyboardMarkup: """ - Пластичная функция для отправки обратно в какое-то меню. + Пластичная функция для отправки обратно в какое-то меню. """ return create_callback_markup( [button_name], @@ -30,23 +29,29 @@ def get_menu_markup() -> InlineKeyboardMarkup: def get_news_menu_markup() -> InlineKeyboardMarkup: return create_callback_markup( - ["Предложить новость", "Статистика", "Назад"], - ["news_offer", "news_statistics", "menu"], - 1, - 1, - 1, + ["Предложить новость", "Статистика", "Назад"], + ["news_offer", "news_statistics", "menu"], + 1, + 1, + 1, ) def get_offer_news_markup() -> InlineKeyboardMarkup: return create_callback_markup( ["Написать текст", "Указать контакты", "Отправить", "Отмена"], - ["news_input_text", "news_input_contact", "news_offer_send", "news_offer_cancel"], + [ + "news_input_text", + "news_input_contact", + "news_offer_send", + "news_offer_cancel", + ], 1, 1, 2, ) + ############# ### Админ ### ############# @@ -58,6 +63,7 @@ def get_admin_menu_markup() -> InlineKeyboardMarkup: 1, ) + def get_admin_news_markup() -> InlineKeyboardMarkup: return create_callback_markup( ["Предложка", "Избранные новости", "Назад"], @@ -99,4 +105,3 @@ def get_admin_news_offer_markup(news) -> InlineKeyboardMarkup: 1, 1, ) - diff --git a/Mousey/Bot/Keyboards/utils.py b/Mousey/Bot/Keyboards/utils.py index 5962676..8a0ba6c 100644 --- a/Mousey/Bot/Keyboards/utils.py +++ b/Mousey/Bot/Keyboards/utils.py @@ -5,15 +5,15 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder def create_callback_markup( - texts: List[str], - data: List[str], - *adjust: int - ) -> InlineKeyboardMarkup: + texts: List[str], + data: List[str], + *adjust: int, +) -> InlineKeyboardMarkup: """ - Создание Callback-Inline клавиатуры. - Принимает два списка: текст кнопок и данные, которые они посылают. - Также можно указать размеры для каждой строчки клавиатуры. - Выводит объект для reply_markup. + Создание Callback-Inline клавиатуры. + Принимает два списка: текст кнопок и данные, которые они посылают. + Также можно указать размеры для каждой строчки клавиатуры. + Выводит объект для reply_markup. """ builder = InlineKeyboardBuilder() @@ -24,6 +24,5 @@ def create_callback_markup( if len(adjust) > 0: builder.adjust(*adjust) - - return builder.as_markup() + return builder.as_markup() diff --git a/Mousey/Bot/Middlewares/__init__.py b/Mousey/Bot/Middlewares/__init__.py index 458aba9..8dc02ec 100644 --- a/Mousey/Bot/Middlewares/__init__.py +++ b/Mousey/Bot/Middlewares/__init__.py @@ -1,8 +1,4 @@ -__all__ = [ - "i18n_middleware", - "DatabaseSessionMiddleware" -] +__all__ = ["i18n_middleware", "DatabaseSessionMiddleware"] from .i18n import i18n_middleware from .database import DatabaseSessionMiddleware - diff --git a/Mousey/Bot/Middlewares/database.py b/Mousey/Bot/Middlewares/database.py index eb3c22e..3985f9b 100644 --- a/Mousey/Bot/Middlewares/database.py +++ b/Mousey/Bot/Middlewares/database.py @@ -8,18 +8,20 @@ from sqlalchemy.ext.asyncio import async_sessionmaker class DatabaseSessionMiddleware(BaseMiddleware): """ - Мидлвари для получения сессии в БД для фильтров, сообщений и прочего. + Мидлвари для получения сессии в БД для фильтров, сообщений и прочего. """ + def __init__(self, session_pool: async_sessionmaker) -> None: self.session_pool = session_pool async def __call__( self, - handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + handler: Callable[ + [TelegramObject, Dict[str, Any]], Awaitable[Any] + ], event: TelegramObject, data: Dict[str, Any], ) -> Any: async with self.session_pool() as session: data["session"] = session return await handler(event, data) - diff --git a/Mousey/Bot/States/__init__.py b/Mousey/Bot/States/__init__.py index b3dc646..f2a8e64 100644 --- a/Mousey/Bot/States/__init__.py +++ b/Mousey/Bot/States/__init__.py @@ -1,4 +1,3 @@ __all__ = ["OfferNews"] from .offer_news import OfferNews - diff --git a/Mousey/Bot/States/offer_news.py b/Mousey/Bot/States/offer_news.py index a0a3f7a..86e7881 100644 --- a/Mousey/Bot/States/offer_news.py +++ b/Mousey/Bot/States/offer_news.py @@ -4,4 +4,3 @@ from aiogram.fsm.state import StatesGroup, State class OfferNews(StatesGroup): typing_text = State() typing_contact = State() - diff --git a/Mousey/Bot/__init__.py b/Mousey/Bot/__init__.py index 92e4b99..3234b55 100644 --- a/Mousey/Bot/__init__.py +++ b/Mousey/Bot/__init__.py @@ -1,4 +1,3 @@ __all__ = ["start"] from .start import start - diff --git a/Mousey/Bot/settings.py b/Mousey/Bot/settings.py index 9413b64..1123105 100644 --- a/Mousey/Bot/settings.py +++ b/Mousey/Bot/settings.py @@ -2,7 +2,9 @@ import json from aiogram import Bot from aiogram.types.bot_command import BotCommand -from aiogram.types.bot_command_scope_all_private_chats import BotCommandScopeAllPrivateChats +from aiogram.types.bot_command_scope_all_private_chats import ( + BotCommandScopeAllPrivateChats, +) from loguru import logger @@ -11,10 +13,12 @@ from Mousey.Misc import BOT_SETTINGS_DIR async def set_profile_info(bot: Bot) -> None: """ - Установка всей информации в профиле для бота. - Имя, описание, аватар... + Установка всей информации в профиле для бота. + Имя, описание, аватар... """ - with open(BOT_SETTINGS_DIR / "settings.json", "r", encoding="utf-8") as file: + with open( + BOT_SETTINGS_DIR / "settings.json", "r", encoding="utf-8" + ) as file: bot_info = json.load(file) await bot.set_my_name(bot_info["name"]) @@ -26,19 +30,22 @@ async def set_profile_info(bot: Bot) -> None: async def set_command_menu(bot: Bot) -> None: """ - Установка меню пользовательских команд в Telegram для бота. + Установка меню пользовательских команд в Telegram для бота. """ - with open(BOT_SETTINGS_DIR / "settings.json", "r", encoding="utf-8") as file: + with open( + BOT_SETTINGS_DIR / "settings.json", "r", encoding="utf-8" + ) as file: bot_info = json.load(file) await bot.set_my_commands( [ - BotCommand(command=command_info["name"], description=command_info["description"]) + BotCommand( + command=command_info["name"], + description=command_info["description"], + ) for command_info in bot_info["commands"] ], scope=BotCommandScopeAllPrivateChats(), ) logger.info("Меню команд для бота настроено.") - - diff --git a/Mousey/Bot/start.py b/Mousey/Bot/start.py index c98b65b..bc5428f 100644 --- a/Mousey/Bot/start.py +++ b/Mousey/Bot/start.py @@ -17,23 +17,23 @@ from Mousey.Database import create_db, drop_db, session_maker @logger.catch async def start( - to_drop_db: bool, - to_update_telegram_profile: bool, - ) -> None: + to_drop_db: bool, + to_update_telegram_profile: bool, +) -> None: """ - Запуск бота + Запуск бота """ # Загрузка базы данных if to_drop_db: await drop_db() logger.warning("База данных очищена.") - + await create_db() # Настройка бота bot = Bot(token=getenv("BOT_TOKEN")) await set_command_menu(bot=bot) - + # Обновление профиля if to_update_telegram_profile: await set_profile_info(bot=bot) @@ -42,23 +42,24 @@ async def start( dp = Dispatcher( storage=RedisStorage(redis=redis), ) - + # Добавление мидлвари для диспетчера dp.message.middleware(i18n_middleware) dp.callback_query.middleware(i18n_middleware) - dp.update.middleware(DatabaseSessionMiddleware(session_pool=session_maker)) - + dp.update.middleware( + DatabaseSessionMiddleware(session_pool=session_maker) + ) + logger.success("Все мидлвари успешно добавлены.") # Добавление роутеров для диспетчера setup_routers(dispatcher=dp) logger.success("Все роутеры успешно добавлены.") - + # Старт пуллинга бота await bot(DeleteWebhook(drop_pending_updates=True)) logger.debug("Все Telegram запросы для бота удалены.") logger.success("Старт пуллинга бота.") await dp.start_polling(bot) - diff --git a/Mousey/Database/Models/__init__.py b/Mousey/Database/Models/__init__.py index a5e7ca7..3a61d43 100644 --- a/Mousey/Database/Models/__init__.py +++ b/Mousey/Database/Models/__init__.py @@ -3,4 +3,3 @@ __all__ = ["Base", "News", "Users"] from .base import Base from .news import News from .user import Users - diff --git a/Mousey/Database/Models/base.py b/Mousey/Database/Models/base.py index 1b62a4c..d2a5f3d 100644 --- a/Mousey/Database/Models/base.py +++ b/Mousey/Database/Models/base.py @@ -4,11 +4,15 @@ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column class Base(DeclarativeBase): """ - Основной шаблон для схем в базе данных. + Основной шаблон для схем в базе данных. """ + # Информация о том, когда была добавлена строка в БД - added: Mapped[DateTime] = mapped_column(DateTime, default=func.now()) + added: Mapped[DateTime] = mapped_column( + DateTime, default=func.now() + ) # Информация о том, когда последний раз была обновлена строчка - updated: Mapped[DateTime] = mapped_column(DateTime, default=func.now(), onupdate=func.now()) - + updated: Mapped[DateTime] = mapped_column( + DateTime, default=func.now(), onupdate=func.now() + ) diff --git a/Mousey/Database/Models/news.py b/Mousey/Database/Models/news.py index d77cb81..83f89d4 100644 --- a/Mousey/Database/Models/news.py +++ b/Mousey/Database/Models/news.py @@ -8,21 +8,27 @@ from .base import Base class News(Base): """ - Схема для хранения информации о предложенных новостях в БД. + Схема для хранения информации о предложенных новостях в БД. """ + __tablename__ = "news" - + # Уникальный ID новости - news_id: Mapped[int] = mapped_column(primary_key=True, unique=True, autoincrement=True) - + news_id: Mapped[int] = mapped_column( + primary_key=True, unique=True, autoincrement=True + ) + # Информация о пользователе, который предложил новость tg_id: Mapped[int] = mapped_column(nullable=False) - tg_username: Mapped[str] = mapped_column(String(32), nullable=True) + tg_username: Mapped[str] = mapped_column( + String(32), nullable=True + ) # Текст новости и контакты для связи text: Mapped[str] = mapped_column(Text, nullable=False) contact: Mapped[str] = mapped_column(Text, nullable=True) # Статус новости - status: Mapped[str] = mapped_column(String(3), default=NewsStatus.UNSEEN.value, nullable=False) - + status: Mapped[str] = mapped_column( + String(3), default=NewsStatus.UNSEEN.value, nullable=False + ) diff --git a/Mousey/Database/Models/user.py b/Mousey/Database/Models/user.py index bfc6073..bbca358 100644 --- a/Mousey/Database/Models/user.py +++ b/Mousey/Database/Models/user.py @@ -8,17 +8,23 @@ from Mousey.Misc import UserRole class Users(Base): """ - Схема для хранения информации о пользователях бота в БД. + Схема для хранения информации о пользователях бота в БД. """ + __tablename__ = "user" - + # Уникальный ID пользователя (Telegram ID) - tg_id: Mapped[int] = mapped_column(primary_key=True, unique=True, autoincrement=False) + tg_id: Mapped[int] = mapped_column( + primary_key=True, unique=True, autoincrement=False + ) # Статистика по новостям у пользователя all_news: Mapped[int] = mapped_column(default=0, nullable=False) - unseen_news: Mapped[int] = mapped_column(default=0, nullable=False) - - # Роль пользователя для бота - role: Mapped[str] = mapped_column(String(16), default=UserRole.USER.value, nullable=False) + unseen_news: Mapped[int] = mapped_column( + default=0, nullable=False + ) + # Роль пользователя для бота + role: Mapped[str] = mapped_column( + String(16), default=UserRole.USER.value, nullable=False + ) diff --git a/Mousey/Database/utils.py b/Mousey/Database/utils.py index 0612d00..0fe11c0 100644 --- a/Mousey/Database/utils.py +++ b/Mousey/Database/utils.py @@ -1,6 +1,7 @@ """ - Файл с кастомными функциями для обращения к базе данных. +Файл с кастомными функциями для обращения к базе данных. """ + from os import getenv from typing import Tuple @@ -17,10 +18,14 @@ from Mousey.Misc import UserRole, NewsStatus """ Изменение состояния пользователя в базе данных. """ -async def _get_user(session: AsyncSession, telegram_id: int) -> Users | None: + + +async def _get_user( + session: AsyncSession, telegram_id: int +) -> Users | None: """ - Получить пользователя из БД. - Возвращает либо объект пользователя, либо None, если пользователя нет. + Получить пользователя из БД. + Возвращает либо объект пользователя, либо None, если пользователя нет. """ query = select(Users).where(Users.tg_id == telegram_id) result = await session.execute(query) @@ -30,8 +35,8 @@ async def _get_user(session: AsyncSession, telegram_id: int) -> Users | None: async def _add_user(session: AsyncSession, telegram_id: int) -> Users: """ - Добавить пользователя в БД. - Возвращает только что добавленный объект пользователя. + Добавить пользователя в БД. + Возвращает только что добавленный объект пользователя. """ user = Users(tg_id=telegram_id) session.add(user) @@ -41,11 +46,13 @@ async def _add_user(session: AsyncSession, telegram_id: int) -> Users: return user -async def check_user(session: AsyncSession, telegram_id: int) -> Users: +async def check_user( + session: AsyncSession, telegram_id: int +) -> Users: """ - Проверяет, есть ли пользователь в БД. - Если его нет, то добавляет. - Всегда возвращает объект пользователя. + Проверяет, есть ли пользователь в БД. + Если его нет, то добавляет. + Всегда возвращает объект пользователя. """ result = await _get_user(session, telegram_id) @@ -55,29 +62,35 @@ async def check_user(session: AsyncSession, telegram_id: int) -> Users: return await _add_user(session, telegram_id) -async def get_news_statistics(session: AsyncSession, telegram_id: int) -> Tuple[int]: +async def get_news_statistics( + session: AsyncSession, telegram_id: int +) -> Tuple[int]: """ - Получить количество всех предложенных пользователем новостей - и тех, которые не просмотрели. + Получить количество всех предложенных пользователем новостей + и тех, которые не просмотрели. """ user = await check_user(session, telegram_id) return user.all_news, user.unseen_news -async def update_user_role(session: AsyncSession, telegram_id: int, role: UserRole) -> None: +async def update_user_role( + session: AsyncSession, telegram_id: int, role: UserRole +) -> None: """ - Обновление роли пользователя. - Ничего не возвращает. + Обновление роли пользователя. + Ничего не возвращает. """ user = await check_user(session, telegram_id) if isinstance(role, UserRole): role = role.value - query = update(Users).where(Users.tg_id == user.tg_id).values( - role=role - ) + query = ( + update(Users) + .where(Users.tg_id == user.tg_id) + .values(role=role) + ) await session.execute(query) @@ -86,39 +99,49 @@ async def update_user_role(session: AsyncSession, telegram_id: int, role: UserRo async def add_main_admin(session: AsyncSession) -> None: """ - Добавить главного администратора в БД. + Добавить главного администратора в БД. """ main_admin_id = getenv("MAIN_ADMIN_ID") if not main_admin_id.isdigit(): logger.warning("Основной главный администратор не указан!") return - + main_admin_id = int(main_admin_id) - + await check_user(session, main_admin_id) - await update_user_role(session, main_admin_id, UserRole.MAIN_ADMIN) - - logger.info("Основной главный администратор добавлен в базу данных.") + await update_user_role( + session, main_admin_id, UserRole.MAIN_ADMIN + ) + + logger.info( + "Основной главный администратор добавлен в базу данных." + ) """ Взаимодействие с БД для новостей. """ + + async def _change_news_count( - session: AsyncSession, - telegram_id: int, - add_count_all: int, - add_count_unseen: int - ) -> None: + session: AsyncSession, + telegram_id: int, + add_count_all: int, + add_count_unseen: int, +) -> None: """ - Изменения количества новостей для пользователя. + Изменения количества новостей для пользователя. """ user = await check_user(session, telegram_id) - query = update(Users).where(Users.tg_id == user.tg_id).values( - all_news=user.all_news + add_count_all, - unseen_news=user.unseen_news + add_count_unseen, + query = ( + update(Users) + .where(Users.tg_id == user.tg_id) + .values( + all_news=user.all_news + add_count_all, + unseen_news=user.unseen_news + add_count_unseen, + ) ) await session.execute(query) @@ -127,14 +150,14 @@ async def _change_news_count( async def add_news( - session: AsyncSession, - telegram_id: int, - telegram_username: str, - text: str, - contact: str | None - ) -> None: + session: AsyncSession, + telegram_id: int, + telegram_username: str, + text: str, + contact: str | None, +) -> None: """ - Добавление новости в БД. + Добавление новости в БД. """ news = News( tg_id=telegram_id, @@ -143,7 +166,7 @@ async def add_news( contact=contact, ) session.add(news) - + await _change_news_count( session=session, telegram_id=telegram_id, @@ -154,37 +177,53 @@ async def add_news( await session.commit() -async def get_next_unseen_news(session: AsyncSession, news_id: int) -> News | None: +async def get_next_unseen_news( + session: AsyncSession, news_id: int +) -> News | None: """ - Получить следующую по счету непрочитанную новость. + Получить следующую по счету непрочитанную новость. """ - query = select(News)\ - .where(News.status == NewsStatus.UNSEEN.value, News.news_id > news_id)\ - .order_by(News.news_id.asc())\ - .limit(1) - + query = ( + select(News) + .where( + News.status == NewsStatus.UNSEEN.value, + News.news_id > news_id, + ) + .order_by(News.news_id.asc()) + .limit(1) + ) + result = await session.execute(query) - + return result.scalar() -async def get_prev_unseen_news(session: AsyncSession, news_id: int) -> News | None: +async def get_prev_unseen_news( + session: AsyncSession, news_id: int +) -> News | None: """ - Получить предыдущую по счету непрочитанную новость. + Получить предыдущую по счету непрочитанную новость. """ - query = select(News)\ - .where(News.status == NewsStatus.UNSEEN.value, News.news_id < news_id)\ - .order_by(News.news_id.desc())\ - .limit(1) - + query = ( + select(News) + .where( + News.status == NewsStatus.UNSEEN.value, + News.news_id < news_id, + ) + .order_by(News.news_id.desc()) + .limit(1) + ) + result = await session.execute(query) - + return result.scalar() -async def get_news(session: AsyncSession, news_id: int) -> News | None: +async def get_news( + session: AsyncSession, news_id: int +) -> News | None: """ - Вспомогательная функция для получения новости из БД по ключу. + Вспомогательная функция для получения новости из БД по ключу. """ query = select(News).where(News.news_id == news_id) result = await session.execute(query) @@ -194,17 +233,17 @@ async def get_news(session: AsyncSession, news_id: int) -> News | None: async def see_news(session: AsyncSession, news_id: int) -> bool: """ - Удалить просмотренную новость. + Удалить просмотренную новость. """ news = await get_news(session, news_id) if news is None: return False - + query = delete(News).where(News.news_id == news.news_id) await session.execute(query) await session.commit() - + user = await check_user(session, news.tg_id) await _change_news_count( session=session, @@ -219,22 +258,19 @@ async def see_news(session: AsyncSession, news_id: int) -> bool: """ Сбор данных из БД. """ + + async def get_database_data(session: AsyncSession) -> dict: """ - Сбор полезной информации и данных от БД. + Сбор полезной информации и данных от БД. """ data = dict() data["users_count"] = ( - await session.execute( - select(func.count()).select_from(Users) - ) + await session.execute(select(func.count()).select_from(Users)) ).scalar() data["news_count"] = ( - await session.execute( - select(func.count()).select_from(News) - ) + await session.execute(select(func.count()).select_from(News)) ).scalar() return data - diff --git a/Mousey/Misc/__init__.py b/Mousey/Misc/__init__.py index de7b7f2..8bc53e4 100644 --- a/Mousey/Misc/__init__.py +++ b/Mousey/Misc/__init__.py @@ -1,10 +1,18 @@ __all__ = [ "stickers_id", - "UserRole", "NewsStatus", - "LOG_DIR", "LOCALE_DIR", "BOT_SETTINGS_DIR", "CONFIG_FILE_PATH" + "UserRole", + "NewsStatus", + "LOG_DIR", + "LOCALE_DIR", + "BOT_SETTINGS_DIR", + "CONFIG_FILE_PATH", ] from .stickers_id import stickers_id from .enums import UserRole, NewsStatus -from .paths import LOG_DIR, LOCALE_DIR, BOT_SETTINGS_DIR, CONFIG_FILE_PATH - +from .paths import ( + LOG_DIR, + LOCALE_DIR, + BOT_SETTINGS_DIR, + CONFIG_FILE_PATH, +) diff --git a/Mousey/Redis/__init__.py b/Mousey/Redis/__init__.py index f1fd005..e31b114 100644 --- a/Mousey/Redis/__init__.py +++ b/Mousey/Redis/__init__.py @@ -4,4 +4,6 @@ import os from redis.asyncio.client import Redis -redis = Redis(host=os.getenv("REDIS_HOST"), port=os.getenv("REDIS_PORT")) +redis = Redis( + host=os.getenv("REDIS_HOST"), port=os.getenv("REDIS_PORT") +) diff --git a/Mousey/__main__.py b/Mousey/__main__.py index c580931..6ba34b7 100644 --- a/Mousey/__main__.py +++ b/Mousey/__main__.py @@ -23,14 +23,17 @@ def main(): logger.info("Удачи!") load_dotenv(CONFIG_FILE_PATH) - logger.info("Переменные окружения из файла конфигурации загружены.") + logger.info( + "Переменные окружения из файла конфигурации загружены." + ) # Запуск бота logger.debug("Пытаюсь запустить бота...") asyncio.run( start( to_drop_db="drop_db" in sys.argv, - to_update_telegram_profile="update_telegram_profile" in sys.argv, + to_update_telegram_profile="update_telegram_profile" + in sys.argv, ) )