Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt pytest pytest-asyncio

- name: Compile sources
run: |
python -m compileall -q src main.py

- name: Run tests
env:
BOT_TOKEN: dummy-token
Expand Down
2 changes: 2 additions & 0 deletions src/app/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
create_room,
room_admin,
wishes,
custom_invation,
invitation,
debug,
join_room,
Expand All @@ -34,6 +35,7 @@ async def run_bot(token: str) -> None:
wishes.router,
room_admin.router,
create_room.router,
custom_invation.router,
invitation.router,
debug.router,
join_room.router,
Expand Down
131 changes: 131 additions & 0 deletions src/handlers/custom_invation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import Message, CallbackQuery

from src.db import db
from src.keyboards import common_kb, invitation_kb, room_admin_kb
from src.states.states import Gen, CallbackFactory
from src.texts import messages
from src.texts.callback_actions import CallbackAction
from src.handlers.common import get_room_name


router = Router(name=__name__)


@router.callback_query(
CallbackFactory.filter(F.action == CallbackAction.CUSTOM_INVITATION)
)
async def custom_invitation(
call: CallbackQuery, callback_data: CallbackFactory, state: FSMContext
):
isMemberOrAdmin = await db.check_room_and_member(
call.from_user.id, callback_data.room_iden
)
room_name = await get_room_name(callback_data.room_iden)

if isMemberOrAdmin == "MEMBER NOT EXISTS":
await call.message.edit_text(
messages.not_a_member(room_name),
reply_markup=await common_kb.ok_kb("None", asAdmin=False),
)
return

elif isMemberOrAdmin == "ROOM NOT EXISTS":
await call.message.edit_text(
messages.room_not_exists(room_name),
reply_markup=await common_kb.ok_kb("None", asAdmin=False),
)
return

await state.set_state(Gen.set_custom_invitation)
await state.set_data({"room_iden": callback_data.room_iden})

await call.message.answer(
messages.prompt_custom_invitation(room_name),
reply_markup=await common_kb.cancel_kb("None", asAdmin=True),
)


@router.message(Gen.set_custom_invitation)
async def set_custom_invitation(msg: Message, state: FSMContext):
data = await state.get_data()
room_iden = data.get("room_iden")

if msg.text == "🚫Отмена":
await state.clear()
if room_iden:
room_name = await get_room_name(room_iden)
await msg.answer(
messages.room_admin_title(room_name),
reply_markup=await room_admin_kb.room_admin_kb(room_iden),
)
else:
await msg.answer(messages.menu(), reply_markup=common_kb.choice_kb)
return

if msg.media_group_id:
await msg.answer(
messages.media_group_not_supported(),
reply_markup=await common_kb.cancel_kb("None", asAdmin=True),
)
return

if not room_iden:
await state.clear()
await msg.answer(messages.menu(), reply_markup=common_kb.choice_kb)
return

access = await db.check_room_and_member(msg.from_user.id, room_iden)
room_name = await get_room_name(room_iden)
if access == "ROOM NOT EXISTS":
await state.clear()
await msg.answer(
messages.room_not_exists(room_name),
reply_markup=await common_kb.ok_kb("None", asAdmin=False),
)
return

if access == "MEMBER NOT EXISTS":
await state.clear()
await msg.answer(
messages.not_a_member(room_name),
reply_markup=await common_kb.ok_kb("None", asAdmin=False),
)
return

raw_text = msg.text or msg.caption or ""
if not raw_text and not msg.photo:
await msg.answer(
messages.invitation_empty(),
reply_markup=await common_kb.cancel_kb("None", asAdmin=True),
)
return

invitation_text = raw_text.replace("\\", "/").replace("'", "`").replace('"', "`")
manual_join = f"Если приглашение не сработало попробуйте присоединиться в ручном режиме <code>{room_name}</code>"

if invitation_text.strip():
full_text = f"{invitation_text}\n\n{manual_join}"
else:
full_text = manual_join

limit = 1024 if msg.photo else 4096
if len(full_text) > limit:
await msg.answer(
messages.invitation_too_long(),
reply_markup=await common_kb.cancel_kb("None", asAdmin=True),
)
return

info = await msg.bot.get_me()
kb = await invitation_kb.join_to_room_kb(room_iden, info.username)

await state.clear()
if msg.photo:
await msg.answer_photo(
photo=msg.photo[-1].file_id, caption=full_text, reply_markup=kb
)
return

await msg.answer(full_text, reply_markup=kb)
10 changes: 10 additions & 0 deletions src/keyboards/room_admin_kb.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ async def room_admin_kb(room_iden):
).pack(),
)
],
[
InlineKeyboardButton(
text="📝Кастомное приглашение",
callback_data=states.CallbackFactory(
action=CallbackAction.CUSTOM_INVITATION,
room_iden=room_iden,
asAdmin=True,
).pack(),
)
],
[
InlineKeyboardButton(
text="◀️Вернуться в меню",
Expand Down
1 change: 1 addition & 0 deletions src/states/states.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ class Gen(StatesGroup):
room_name_to_join = State()
approval_delete = State()
set_wishes = State()
set_custom_invitation = State()
set_room_price = State()
set_room_time = State()
1 change: 1 addition & 0 deletions src/texts/callback_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class CallbackAction:
SEE_WISHES = "see_wishes"

CREATE_INVITATION = "create_invitation"
CUSTOM_INVITATION = "custom_invitation"

START_EVENT = "start_event"
DELETE_ROOM = "delete_room"
Expand Down
17 changes: 16 additions & 1 deletion src/texts/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,26 @@ def event_started_notify(room_name: str) -> str:

def invitation_text(room_name: str) -> str:
return (
f"✉️Приглашение принять участвие в Тайном санта в комнате {room_name}\n"
f"✉️Приглашение принять участвие в Тайном санта в комнате <code>{room_name}</code>\n"
"<b>Если приглашение не сработало попробуйте присоединиться в ручном режиме</b>"
)


def prompt_custom_invitation(room_name: str) -> str:
return (
f"Отправьте текст приглашения для комнаты <code>{room_name}</code>\n"
"Можно добавить одно фото без альбома"
)


def invitation_too_long() -> str:
return "Слишком длинное приглашение. Укоротите текст и отправьте новое"


def invitation_empty() -> str:
return "Приглашение не распознано. Отправьте текст или фото с подписью"


def room_not_exists_retry() -> str:
return "Такой комнаты не существует\nПопробуйте ещё раз:"

Expand Down