From 65c5cb92cec56bb80b68980c73b32d8b27481169 Mon Sep 17 00:00:00 2001 From: Yuriy Chebyshev Date: Sat, 8 Jun 2024 14:24:51 +0300 Subject: [PATCH 1/4] #82 spy on /start for orgs --- shvatka/tgbot/dialogs/starters/game_spy.py | 18 ++++++++++++++---- shvatka/tgbot/filters/is_org.py | 18 ++++++++++++++++++ shvatka/tgbot/utils/router.py | 5 ++++- 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 shvatka/tgbot/filters/is_org.py diff --git a/shvatka/tgbot/dialogs/starters/game_spy.py b/shvatka/tgbot/dialogs/starters/game_spy.py index a22008e7..edd63bd0 100644 --- a/shvatka/tgbot/dialogs/starters/game_spy.py +++ b/shvatka/tgbot/dialogs/starters/game_spy.py @@ -2,24 +2,34 @@ from aiogram.filters import Command from shvatka.tgbot import states +from shvatka.tgbot.filters.is_org import is_org_on_running_game, is_org from shvatka.tgbot.utils.router import register_start_handler -from shvatka.tgbot.views.commands import SPY_COMMAND, SPY_LEVELS_COMMAND, SPY_KEYS_COMMAND +from shvatka.tgbot.views.commands import SPY_COMMAND, SPY_LEVELS_COMMAND, SPY_KEYS_COMMAND, START_COMMAND def setup() -> Router: router = Router(name=__name__) register_start_handler( Command(commands=SPY_COMMAND), + is_org, state=states.OrgSpySG.main, - router=router, # TODO is_org + router=router, + ) + register_start_handler( + Command(commands=START_COMMAND), + is_org_on_running_game, + state=states.OrgSpySG.main, + router=router, ) register_start_handler( - Command(commands=SPY_LEVELS_COMMAND), # TODO is_org + Command(commands=SPY_LEVELS_COMMAND), + is_org, state=states.OrgSpySG.spy, router=router, ) register_start_handler( - Command(commands=SPY_KEYS_COMMAND), # TODO is_org + Command(commands=SPY_KEYS_COMMAND), + is_org, state=states.OrgSpySG.keys, router=router, ) diff --git a/shvatka/tgbot/filters/is_org.py b/shvatka/tgbot/filters/is_org.py new file mode 100644 index 00000000..fa9d8230 --- /dev/null +++ b/shvatka/tgbot/filters/is_org.py @@ -0,0 +1,18 @@ +from aiogram.types import Message + +from shvatka.core.models import dto +from shvatka.core.services.organizers import get_by_player +from shvatka.infrastructure.db.dao.holder import HolderDao + + +async def is_org_on_running_game(_: Message, player: dto.Player, game: dto.Game, dao: HolderDao): + if game is None or not game.is_started(): + return False + return await is_org(_, player=player, game=game, dao=dao) + + +async def is_org(_: Message, player: dto.Player, game: dto.Game, dao: HolderDao): + org = await get_by_player(player=player, game=game, dao=dao.organizer) + if org is None or org.deleted: + return False + return {"org": org} diff --git a/shvatka/tgbot/utils/router.py b/shvatka/tgbot/utils/router.py index dd3ee233..8b3246ba 100644 --- a/shvatka/tgbot/utils/router.py +++ b/shvatka/tgbot/utils/router.py @@ -1,4 +1,7 @@ +from typing import Callable + from aiogram import Router, Dispatcher +from aiogram.dispatcher.event.handler import CallbackType from aiogram.filters import Filter from aiogram.fsm.state import State from aiogram.types import Message @@ -20,7 +23,7 @@ def disable_router_on_game(router: Router): def register_start_handler( - *filters: Filter, + *filters: CallbackType, state: State, router: Router, mode: StartMode = StartMode.NORMAL, From 5b1b3e6f0964c147d5fa855ae72b0a9fc8917fbd Mon Sep 17 00:00:00 2001 From: Yuriy Chebyshev Date: Sun, 9 Jun 2024 13:13:55 +0300 Subject: [PATCH 2/4] fixed for linters --- shvatka/tgbot/dialogs/starters/game_spy.py | 7 ++++++- shvatka/tgbot/utils/router.py | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shvatka/tgbot/dialogs/starters/game_spy.py b/shvatka/tgbot/dialogs/starters/game_spy.py index edd63bd0..a7f601e3 100644 --- a/shvatka/tgbot/dialogs/starters/game_spy.py +++ b/shvatka/tgbot/dialogs/starters/game_spy.py @@ -4,7 +4,12 @@ from shvatka.tgbot import states from shvatka.tgbot.filters.is_org import is_org_on_running_game, is_org from shvatka.tgbot.utils.router import register_start_handler -from shvatka.tgbot.views.commands import SPY_COMMAND, SPY_LEVELS_COMMAND, SPY_KEYS_COMMAND, START_COMMAND +from shvatka.tgbot.views.commands import ( + SPY_COMMAND, + SPY_LEVELS_COMMAND, + SPY_KEYS_COMMAND, + START_COMMAND, +) def setup() -> Router: diff --git a/shvatka/tgbot/utils/router.py b/shvatka/tgbot/utils/router.py index 8b3246ba..2fb4c70a 100644 --- a/shvatka/tgbot/utils/router.py +++ b/shvatka/tgbot/utils/router.py @@ -1,8 +1,6 @@ -from typing import Callable from aiogram import Router, Dispatcher from aiogram.dispatcher.event.handler import CallbackType -from aiogram.filters import Filter from aiogram.fsm.state import State from aiogram.types import Message from aiogram_dialog import StartMode, DialogManager From 929de112e73bc00f2cd746294b54d41fe0a847a8 Mon Sep 17 00:00:00 2001 From: Yuriy Chebyshev Date: Sun, 9 Jun 2024 13:51:33 +0300 Subject: [PATCH 3/4] fixed for comments --- shvatka/tgbot/dialogs/starters/game_spy.py | 10 ++--- shvatka/tgbot/filters/is_org.py | 51 ++++++++++++++++++---- shvatka/tgbot/utils/router.py | 1 - 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/shvatka/tgbot/dialogs/starters/game_spy.py b/shvatka/tgbot/dialogs/starters/game_spy.py index a7f601e3..0a1af27f 100644 --- a/shvatka/tgbot/dialogs/starters/game_spy.py +++ b/shvatka/tgbot/dialogs/starters/game_spy.py @@ -2,7 +2,7 @@ from aiogram.filters import Command from shvatka.tgbot import states -from shvatka.tgbot.filters.is_org import is_org_on_running_game, is_org +from shvatka.tgbot.filters.is_org import OrgFilter from shvatka.tgbot.utils.router import register_start_handler from shvatka.tgbot.views.commands import ( SPY_COMMAND, @@ -16,25 +16,25 @@ def setup() -> Router: router = Router(name=__name__) register_start_handler( Command(commands=SPY_COMMAND), - is_org, + OrgFilter(only_for_running_game=False), state=states.OrgSpySG.main, router=router, ) register_start_handler( Command(commands=START_COMMAND), - is_org_on_running_game, + OrgFilter(), state=states.OrgSpySG.main, router=router, ) register_start_handler( Command(commands=SPY_LEVELS_COMMAND), - is_org, + OrgFilter(can_spy=True), state=states.OrgSpySG.spy, router=router, ) register_start_handler( Command(commands=SPY_KEYS_COMMAND), - is_org, + OrgFilter(can_see_log_keys=True), state=states.OrgSpySG.keys, router=router, ) diff --git a/shvatka/tgbot/filters/is_org.py b/shvatka/tgbot/filters/is_org.py index fa9d8230..1aa3f2f0 100644 --- a/shvatka/tgbot/filters/is_org.py +++ b/shvatka/tgbot/filters/is_org.py @@ -1,3 +1,7 @@ +from dataclasses import dataclass +from typing import Any + +from aiogram.filters import BaseFilter from aiogram.types import Message from shvatka.core.models import dto @@ -5,14 +9,43 @@ from shvatka.infrastructure.db.dao.holder import HolderDao -async def is_org_on_running_game(_: Message, player: dto.Player, game: dto.Game, dao: HolderDao): - if game is None or not game.is_started(): - return False - return await is_org(_, player=player, game=game, dao=dao) +@dataclass +class OrgFilter(BaseFilter): + """ + if multiple values provided used AND semantic, + except is_primary (if provided - only this checked) + and only_for_running_game + """ + can_spy: bool | None = None + can_see_log_keys: bool | None = None + can_validate_waivers: bool | None = None + is_primary: bool | None = None + only_for_running_game: bool = True -async def is_org(_: Message, player: dto.Player, game: dto.Game, dao: HolderDao): - org = await get_by_player(player=player, game=game, dao=dao.organizer) - if org is None or org.deleted: - return False - return {"org": org} + async def __call__( # noqa: C901 + self, + message: Message, + game: dto.Game | None, + player: dto.Player, + dao: HolderDao, + ) -> bool | dict[str, Any]: + if not game or not game.is_active(): + return False + if self.only_for_running_game and not game.is_started(): + return False + org = await get_by_player(player=player, game=game, dao=dao.organizer) + if org is None or org.deleted: + return False + if self.is_primary is not None: + return isinstance(org, dto.PrimaryOrganizer) + if self.can_spy is not None: + if self.can_spy != org.can_spy: + return False + if self.can_see_log_keys is not None: + if self.can_see_log_keys != org.can_see_log_keys: + return False + if self.can_validate_waivers is not None: + if self.can_validate_waivers != org.can_validate_waivers: + return False + return True diff --git a/shvatka/tgbot/utils/router.py b/shvatka/tgbot/utils/router.py index 2fb4c70a..8986f14c 100644 --- a/shvatka/tgbot/utils/router.py +++ b/shvatka/tgbot/utils/router.py @@ -1,4 +1,3 @@ - from aiogram import Router, Dispatcher from aiogram.dispatcher.event.handler import CallbackType from aiogram.fsm.state import State From 08c99ded63efdf2f433801adf17033deeb362ef9 Mon Sep 17 00:00:00 2001 From: Yuriy Chebyshev Date: Sun, 9 Jun 2024 14:48:19 +0300 Subject: [PATCH 4/4] few refactoring game spy dialog --- shvatka/tgbot/dialogs/game_spy/dialogs.py | 9 +++------ shvatka/tgbot/dialogs/game_spy/getters.py | 10 ++++++++-- shvatka/tgbot/dialogs/game_spy/handlers.py | 4 ++++ shvatka/tgbot/filters/is_org.py | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/shvatka/tgbot/dialogs/game_spy/dialogs.py b/shvatka/tgbot/dialogs/game_spy/dialogs.py index acb6442e..1f47f413 100644 --- a/shvatka/tgbot/dialogs/game_spy/dialogs.py +++ b/shvatka/tgbot/dialogs/game_spy/dialogs.py @@ -1,11 +1,8 @@ -from datetime import datetime - from aiogram import F from aiogram_dialog import Dialog, Window from aiogram_dialog.widgets.kbd import Button, SwitchTo, Cancel from aiogram_dialog.widgets.text import Const, Jinja, Multi -from shvatka.core.utils.datetime_utils import tz_utc from shvatka.tgbot import states from .getters import get_org, get_spy, get_keys from .handlers import keys_handler @@ -61,9 +58,9 @@ "Промежуточный лог ключей \n" "для игры {{game.name}} " "(началась в {{game.start_at|user_timezone}}) \n" - "по состоянию на {{ now | user_timezone }}\n" "{% if key_link %}" - 'доступен по ссылке' + 'доступен по ссылке\n' + "по состоянию на {{ updated | user_timezone }}" "{% else %}" "пока недоступен (попробуй обновить)" "{% endif %}" @@ -71,7 +68,7 @@ Button(Const("🔄Обновить"), id="refresh_spy", on_click=keys_handler), SwitchTo(Const("🔙Назад"), id="back", state=states.OrgSpySG.main), state=states.OrgSpySG.keys, - getter=(get_org, get_keys, {"now": datetime.now(tz=tz_utc)}), + getter=(get_org, get_keys), disable_web_page_preview=True, ), ) diff --git a/shvatka/tgbot/dialogs/game_spy/getters.py b/shvatka/tgbot/dialogs/game_spy/getters.py index e3aded5e..c6878a3f 100644 --- a/shvatka/tgbot/dialogs/game_spy/getters.py +++ b/shvatka/tgbot/dialogs/game_spy/getters.py @@ -9,7 +9,10 @@ async def get_org( dao: HolderDao, player: dto.Player, game: dto.Game, dialog_manager: DialogManager, **_ ): - org = await get_by_player(player=player, game=game, dao=dao.organizer) + if dialog_manager.middleware_data.get("org", None) is not None: + org = dialog_manager.middleware_data["org"] + else: + org = await get_by_player(player=player, game=game, dao=dao.organizer) return { "game": game, "player": player, @@ -27,4 +30,7 @@ async def get_spy( async def get_keys(dialog_manager: DialogManager, **_): - return {"key_link": dialog_manager.dialog_data.get("key_link", None)} + return { + "key_link": dialog_manager.dialog_data.get("key_link", None), + "updated": dialog_manager.dialog_data.get("updated", None), + } diff --git a/shvatka/tgbot/dialogs/game_spy/handlers.py b/shvatka/tgbot/dialogs/game_spy/handlers.py index da73d949..5ac2700c 100644 --- a/shvatka/tgbot/dialogs/game_spy/handlers.py +++ b/shvatka/tgbot/dialogs/game_spy/handlers.py @@ -1,8 +1,11 @@ +from datetime import datetime + from aiogram.types import CallbackQuery from aiogram_dialog import DialogManager from aiogram_dialog.widgets.kbd import Button from shvatka.core.models import dto +from shvatka.core.utils.datetime_utils import tz_utc from shvatka.infrastructure.db.dao.holder import HolderDao from shvatka.tgbot.views.keys import create_keys_page from shvatka.tgbot.views.telegraph import Telegraph @@ -16,3 +19,4 @@ async def keys_handler(c: CallbackQuery, widget: Button, manager: DialogManager) player: dto.Player = manager.middleware_data["player"] page = await create_keys_page(game, player, telegraph, dao, salt=game.manage_token[:8]) manager.dialog_data["key_link"] = page["url"] + manager.dialog_data["updated"] = datetime.now(tz=tz_utc) diff --git a/shvatka/tgbot/filters/is_org.py b/shvatka/tgbot/filters/is_org.py index 1aa3f2f0..d9ba5c8b 100644 --- a/shvatka/tgbot/filters/is_org.py +++ b/shvatka/tgbot/filters/is_org.py @@ -48,4 +48,4 @@ async def __call__( # noqa: C901 if self.can_validate_waivers is not None: if self.can_validate_waivers != org.can_validate_waivers: return False - return True + return {"org": org}