Untitled

4ae4d avatar
4ae4d
plain_text
02/10/2026 7:41 AM
10.8 KB
9
Indexable
--- a/src/bot/core/handlers/events_filters.py
+++ b/src/bot/core/handlers/events_filters.py
@@ -1,12 +1,13 @@
 from dialog_bot_sdk.entities.messaging import UpdateInteractiveMediaEvent

 from core.bot_kit.fsm import FSMContext, State, StatesGroup
 from core.config import bot
 from core.handlers.events_ui import send_city_events_page, send_my_events_page, send_points_page
-from core.markups.events_filters import events_filters_menu_keyboard
+from core.markups.events_filters import events_filters_city_keyboard, events_filters_menu_keyboard
 from core.markups.tags import TagChoice
+from core.services.city import CityService
 from core.services.event import EventService
 from core.services.tag import TagService
 from core.utils import delete_prev_message_by_peer
 from core.utils.events_filter import (
     format_events_filter_summary,
     get_events_filter,
     reset_events_filter,
     set_events_filter,
 )
 from core.utils.tags_toggle_ui import TagsToggleCfg, is_done, parse_toggle_key, send_tags_toggle_ui

@@
 class EventsFiltersTagsState(StatesGroup):
     tags = State()
+
+
+class EventsFiltersCityState(StatesGroup):
+    city = State()

@@
 _CTX_KEY = "events_filters_edit_ctx"
 _OFFSET_KEY = "events_filters_edit_offset"
 _TAG_IDS_KEY = "events_filters_edit_tags_selected"
+
+_CITIES_OFFSET_KEY = "events_filters_city_offset"
+_CITY_SELECTED_ID_KEY = "events_filters_city_selected_id"
+_CITY_SELECTED_NAME_KEY = "events_filters_city_selected_name"
+
+_CITIES_PAGE_LIMIT = 10

@@
 def events_filters_not_implemented_handler(event: UpdateInteractiveMediaEvent, context: FSMContext):
@@
     bot.messaging.send_message(
         peer=event.peer,
         text=f"⚠️ Пока не реализовано в этом коммите.\n\n{summary}\n\nВыбери, что изменить:",
         interactive_media_groups=events_filters_menu_keyboard(ctx_name=ctx_name, offset=offset),
     )
+
+
+def _safe_int(value: object, default: int = 0) -> int:
+    try:
+        if value is None:
+            return default
+        n = int(value)
+        return n if n >= 0 else default
+    except Exception:
+        return default
+
+
+def _send_city_picker(
+    *,
+    peer,
+    ctx_name: str,
+    back_offset: int,
+    cities_offset: int,
+    selected_city_id: str | None,
+    city_service: CityService,
+):
+    cities = city_service.get_all(offset=cities_offset, limit=_CITIES_PAGE_LIMIT)
+    has_prev = cities_offset > 0
+    has_next = len(cities) >= _CITIES_PAGE_LIMIT
+
+    bot.messaging.send_message(
+        peer=peer,
+        text="🏙️ *Фильтры: город*\n\nВыбери один город и нажми «Готово»:",
+        interactive_media_groups=events_filters_city_keyboard(
+            ctx_name=ctx_name,
+            back_offset=back_offset,
+            cities=cities,
+            cities_offset=cities_offset,
+            limit=_CITIES_PAGE_LIMIT,
+            selected_city_id=selected_city_id,
+            has_prev=has_prev,
+            has_next=has_next,
+        ),
+    )
+
+
[email protected]
+def events_filters_city_open_handler(
+    event: UpdateInteractiveMediaEvent,
+    context: FSMContext,
+    event_service: EventService,
+    city_service: CityService,
+):
+    delete_prev_message_by_peer(bot, event.peer)
+    context.set_state(None)
+
+    ctx_name, back_offset = _split_ctx_offset(event.data.value)
+    flt = get_events_filter(context, ctx_name=ctx_name)
+
+    # сохраняем "куда вернуться" + текущий выбор
+    context.update_data(
+        {
+            _CTX_KEY: ctx_name,
+            _OFFSET_KEY: int(back_offset),
+            _CITIES_OFFSET_KEY: 0,
+            _CITY_SELECTED_ID_KEY: flt.city_id,
+            _CITY_SELECTED_NAME_KEY: flt.city_name,
+        }
+    )
+    context.set_state(EventsFiltersCityState.city)
+
+    _send_city_picker(
+        peer=event.peer,
+        ctx_name=ctx_name,
+        back_offset=back_offset,
+        cities_offset=0,
+        selected_city_id=flt.city_id,
+        city_service=city_service,
+    )
+
+
[email protected]
+def events_filters_city_select_handler(
+    event: UpdateInteractiveMediaEvent,
+    context: FSMContext,
+    event_service: EventService,
+    city_service: CityService,
+):
+    state = context.get_state()
+    if not (state == EventsFiltersCityState.city or str(state) == str(EventsFiltersCityState.city)):
+        return
+
+    delete_prev_message_by_peer(bot, event.peer)
+
+    raw = str(event.data.value or "").strip()
+    data = context.get_data() or {}
+
+    ctx_name = str(data.get(_CTX_KEY) or "events")
+    back_offset = _safe_int(data.get(_OFFSET_KEY), 0)
+    cities_offset = _safe_int(data.get(_CITIES_OFFSET_KEY), 0)
+    selected_city_id = data.get(_CITY_SELECTED_ID_KEY)
+
+    # BACK / DONE несут ctx|offset
+    if raw.startswith("back:"):
+        _ctx, _off = _split_ctx_offset(raw[len("back:") :])
+        summary = format_events_filter_summary(get_events_filter(context, ctx_name=_ctx))
+        context.set_state(None)
+        context.update_data(
+            {
+                _CTX_KEY: None,
+                _OFFSET_KEY: None,
+                _CITIES_OFFSET_KEY: None,
+                _CITY_SELECTED_ID_KEY: None,
+                _CITY_SELECTED_NAME_KEY: None,
+            }
+        )
+        bot.messaging.send_message(
+            peer=event.peer,
+            text=f"🧰 *Фильтры*\n\n{summary}\n\nВыбери, что изменить:",
+            interactive_media_groups=events_filters_menu_keyboard(ctx_name=_ctx, offset=_off),
+        )
+        return
+
+    if raw.startswith("done:"):
+        _ctx, _off = _split_ctx_offset(raw[len("done:") :])
+        sel_id = str(data.get(_CITY_SELECTED_ID_KEY) or "").strip() or None
+        sel_name = str(data.get(_CITY_SELECTED_NAME_KEY) or "").strip() or None
+
+        flt = get_events_filter(context, ctx_name=_ctx)
+        flt.city_id = sel_id
+        flt.city_name = sel_name
+        set_events_filter(context, ctx_name=_ctx, flt=flt)
+
+        summary = format_events_filter_summary(get_events_filter(context, ctx_name=_ctx))
+        context.set_state(None)
+        context.update_data(
+            {
+                _CTX_KEY: None,
+                _OFFSET_KEY: None,
+                _CITIES_OFFSET_KEY: None,
+                _CITY_SELECTED_ID_KEY: None,
+                _CITY_SELECTED_NAME_KEY: None,
+            }
+        )
+        bot.messaging.send_message(
+            peer=event.peer,
+            text=f"🧰 *Фильтры*\n\n{summary}\n\nВыбери, что изменить:",
+            interactive_media_groups=events_filters_menu_keyboard(ctx_name=_ctx, offset=_off),
+        )
+        return
+
+    # CLEAR
+    if raw == "clear":
+        context.update_data({_CITY_SELECTED_ID_KEY: None, _CITY_SELECTED_NAME_KEY: None})
+        _send_city_picker(
+            peer=event.peer,
+            ctx_name=ctx_name,
+            back_offset=back_offset,
+            cities_offset=cities_offset,
+            selected_city_id=None,
+            city_service=city_service,
+        )
+        return
+
+    # PAGE
+    if raw.startswith("page:"):
+        new_off = _safe_int(raw[len("page:") :], 0)
+        context.update_data({_CITIES_OFFSET_KEY: new_off})
+        _send_city_picker(
+            peer=event.peer,
+            ctx_name=ctx_name,
+            back_offset=back_offset,
+            cities_offset=new_off,
+            selected_city_id=str(data.get(_CITY_SELECTED_ID_KEY) or "").strip() or None,
+            city_service=city_service,
+        )
+        return
+
+    # SELECT
+    if raw.startswith("select:"):
+        cid = raw[len("select:") :].strip()
+        if not cid:
+            return
+        city = city_service.get_by_id(cid)
+        context.update_data(
+            {
+                _CITY_SELECTED_ID_KEY: cid,
+                _CITY_SELECTED_NAME_KEY: (city.name if city else None),
+            }
+        )
+        _send_city_picker(
+            peer=event.peer,
+            ctx_name=ctx_name,
+            back_offset=back_offset,
+            cities_offset=cities_offset,
+            selected_city_id=cid,
+            city_service=city_service,
+        )
+        return
Editor is loading...
Leave a Comment