This repository has been archived on 2025-09-07. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
MouseyBot/Mousey/Bot/Handlers/Private/news.py
2025-08-22 11:37:26 +07:00

212 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from aiogram.fsm.context import FSMContext
from aiogram.utils.i18n import gettext as _
from sqlalchemy.ext.asyncio import AsyncSession
from aiogram.types import CallbackQuery, Message
from .utils import call_cancel
from Mousey.Misc import UserRole
from Mousey.Bot.States import OfferNews
from Mousey.Database import (
add_news,
check_user,
get_news_statistics,
)
from Mousey.Bot.Keyboards import (
get_back_markup,
get_news_menu_markup,
get_offer_news_markup,
)
#######################
### Вспомогательное ###
#######################
async def __get_news_offer_text(state: FSMContext) -> str:
data = await state.get_data()
news_text = _("Текст для новости отсутствует")
news_contact = _("Контакты для новости отсутствуют")
if data.get("news_text") is not None:
news_text = _("Шаблон для вставки текста новости").format(
text=data["news_text"][:512]
)
if data.get("news_contact") is not None:
news_contact = _("Шаблон для вставки контактов новости").format(
contact=data["news_contact"][:256]
)
news_text += "..." if len(news_text) >= 512 else ""
news_contact += "..." if len(news_contact) >= 256 else ""
return _("Шаблон для формы отправки новости").format(
news_text=news_text,
news_contact=news_contact,
)
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 False
#################
### Сообщения ###
#################
async def cmd_news_offer(message: Message, state: FSMContext) -> None:
"""
Меню, чтобы предложить новость.
"""
current_state = await state.get_state()
if current_state == OfferNews.typing_text:
await state.update_data(news_text=message.text)
elif current_state == OfferNews.typing_contact:
await state.update_data(news_contact=message.text)
await state.set_state()
await message.answer(
text=await __get_news_offer_text(state),
reply_markup=get_offer_news_markup(),
)
async def cmd_news_input_error(message: Message, state: FSMContext) -> None:
"""
Некоректная отправка сообщения для предложки.
"""
await message.answer(
text=_("Неправильная форма данных для новости"),
)
##############
### Вызовы ###
##############
async def call_news_menu(call: CallbackQuery) -> None:
"""
Вызов новостного меню.
"""
await call.message.edit_text(
text=_("Новостное меню"),
reply_markup=get_news_menu_markup(),
)
async def call_news_statistics(call: CallbackQuery, session: AsyncSession) -> None:
"""
Статистика новостей пользователя.
"""
news_statistics = await get_news_statistics(session, int(call.from_user.id))
await call.message.edit_text(
text=_("Шаблон для статистики новостей").format(
all_news=news_statistics[0],
unseen_news=news_statistics[1],
),
reply_markup=get_back_markup(callback_data="news_menu"),
)
async def call_news_offer(call: CallbackQuery, state: FSMContext) -> None:
"""
Меню, чтобы предложить новость.
"""
await state.set_state()
await call.message.edit_text(
text=await __get_news_offer_text(state),
reply_markup=get_offer_news_markup(),
)
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(
button_name="Отменить отправку",
callback_data="news_offer_cancel",
),
)
async def call_input_news_contact(call: CallbackQuery, state: FSMContext) -> None:
"""
Сообщение для ввода контактов для новости.
"""
await state.set_state(OfferNews.typing_contact)
await call.message.edit_text(
text=_("Ввести контакты для новости"),
reply_markup=get_back_markup(
button_name="Отменить отправку",
callback_data="news_offer_cancel",
),
)
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:
"""
Сообщение об отправке новости.
"""
data = await state.get_data()
user = await check_user(session, call.from_user.id)
if __check_user_for_offer(data, user):
await add_news(
session=session,
telegram_id=call.from_user.id,
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"]
elif user.role == UserRole.BANNED.value:
reason = reasons["banned"]
else:
reason = reasons["limite"]
await call.message.edit_text(
text=_("Шаблон новость не отправлена").format(reason=reason),
reply_markup=get_back_markup(callback_data="news_menu"),
)
await state.clear()