aboutsummaryrefslogtreecommitdiff
path: root/handlers/user/announcements.py
blob: dc85b5448f8bb3888b1e8c5a61a714b486e51f9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from math import ceil

from aiogram import Bot, Router
from aiogram.filters import Command
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
from aiogram.types.callback_query import CallbackQuery
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.sql.functions import count

from libs.msg import eclipse_text
from models import Announcement
from models.callback_data import AnnounceItemClb, AnnouncePageClb

router = Router(name="announcements")
PAGE_SIZE = 5


async def get_reply_markup(
    page: int,
    session: AsyncSession,
) -> InlineKeyboardMarkup | None:
    total = await session.scalar(select(count()).select_from(Announcement))
    assert total is not None
    total_pages = ceil(total / PAGE_SIZE)

    if total == 0:
        return None

    page = max(0, min(page, total_pages - 1))
    query = (
        select(Announcement)
        .offset(PAGE_SIZE * page)
        .limit(PAGE_SIZE)
        .order_by(Announcement.id.desc())
    )
    announcements = await session.scalars(query)

    announcement_buttons = [
        [
            InlineKeyboardButton(
                text=(
                    f"{eclipse_text(a.message.text, 10)} "
                    f"({a.datetime.strftime('%d %b %y г.')})"
                ),
                callback_data=AnnounceItemClb(page=page, announce_id=a.id).pack(),
            )
        ]
        for a in announcements
    ]

    page_buttons = []
    if page > 0:
        page_buttons.append(
            InlineKeyboardButton(
                text="◀️",
                callback_data=AnnouncePageClb(page=page - 1).pack(),
            )
        )
    if page < total_pages - 1:
        page_buttons.append(
            InlineKeyboardButton(
                text="▶️",
                callback_data=AnnouncePageClb(page=page + 1).pack(),
            )
        )

    return InlineKeyboardMarkup(inline_keyboard=[*announcement_buttons, page_buttons])


@router.message(Command("announcements"))
async def command(msg: Message, bot: Bot, session: AsyncSession) -> None:
    reply_markup = await get_reply_markup(0, session)

    if reply_markup is None:
        await msg.answer("Нету анонсов для просмотра.")
        return

    await msg.answer("Выберете анонс для просмотра.", reply_markup=reply_markup)


@router.callback_query(AnnouncePageClb.filter())
async def page(
    clb: CallbackQuery,
    callback_data: AnnouncePageClb,
    session: AsyncSession,
) -> None:
    assert isinstance(clb.message, Message)

    reply_markup = await get_reply_markup(callback_data.page, session)
    await clb.message.edit_text(
        "Выберете анонс для просмотра:",
        reply_markup=reply_markup,
    )

    await clb.answer()


@router.callback_query(AnnounceItemClb.filter())
async def item(
    clb: CallbackQuery,
    callback_data: AnnounceItemClb,
    session: AsyncSession,
) -> None:
    assert isinstance(clb.message, Message)

    announcement = await session.get(Announcement, callback_data.announce_id)
    assert announcement is not None

    rich_text = announcement.message
    reply_markup = InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="Назад к выбору",
                    callback_data=AnnouncePageClb(page=callback_data.page).pack(),
                )
            ]
        ]
    )

    await clb.message.edit_text(
        text=rich_text.text,
        entities=rich_text.entities,
        parse_mode=None,
        reply_markup=reply_markup,
    )

    await clb.answer()