Skip to content

Commit 94bd53e

Browse files
committed
Use DatabaseManager for search filters
Replace the SearchFilterService indirection and centralize search filter operations in DatabaseManager. Handlers now call DatabaseManager.get_and_touch_user_filters / get_user_filters / upsert_user_filters / reset_user_filters directly; upsert_user_filters now accepts a SearchFilter and JSON-serializes it internally. Deleted the old services/search_filter/search_filter_service.py module and updated imports across many handlers and clip/search/semantic handlers. Also adjusted return types and SQL in database_manager.get_user_filters to return a SearchFilter (or None) and updated callers accordingly. Additional small refactors: renamed internal parser methods in FilterParser to use private names, renamed _format_filter to __format_filter and updated usages, removed some explicit typing annotations and cleaned up list initializations. These changes centralize filter persistence logic and simplify handler code.
1 parent 3169d7f commit 94bd53e

18 files changed

Lines changed: 51 additions & 88 deletions

bot/database/database_manager.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
)
3232
from bot.exceptions import TooManyActiveTokensError
3333
from bot.settings import settings
34+
from bot.types import SearchFilter
3435
from bot.utils.constants import DatabaseKeys
3536

3637
db_manager_logger = logging.getLogger(__name__)
@@ -1069,15 +1070,15 @@ async def set_user_active_series(user_id: int, series_id: int) -> None:
10691070
)
10701071

10711072
@staticmethod
1072-
async def get_user_filters(chat_id: int) -> Optional[Dict[str, Any]]:
1073+
async def get_user_filters(chat_id: int) -> Optional[SearchFilter]:
10731074
async with DatabaseManager.__get_db_connection() as conn:
10741075
row = await conn.fetchrow(
1075-
"SELECT filters, last_used_at FROM user_search_filters WHERE chat_id = $1",
1076+
"SELECT filters FROM user_search_filters WHERE chat_id = $1",
10761077
chat_id,
10771078
)
10781079
if row is None:
10791080
return None
1080-
return {"filters": json.loads(row["filters"]), "last_used_at": row["last_used_at"]}
1081+
return json.loads(row["filters"]) or None
10811082

10821083
@staticmethod
10831084
async def get_and_touch_user_filters(chat_id: int) -> Optional[Dict[str, Any]]:
@@ -1096,7 +1097,7 @@ async def get_and_touch_user_filters(chat_id: int) -> Optional[Dict[str, Any]]:
10961097
return json.loads(row["filters"])
10971098

10981099
@staticmethod
1099-
async def upsert_user_filters(chat_id: int, filters_json: str) -> None:
1100+
async def upsert_user_filters(chat_id: int, filters: SearchFilter) -> None:
11001101
async with DatabaseManager.__get_db_connection() as conn:
11011102
async with conn.transaction():
11021103
await conn.execute(
@@ -1107,7 +1108,7 @@ async def upsert_user_filters(chat_id: int, filters_json: str) -> None:
11071108
SET filters = user_search_filters.filters || $2::jsonb,
11081109
last_used_at = CURRENT_TIMESTAMP
11091110
""",
1110-
chat_id, filters_json,
1111+
chat_id, json.dumps(filters),
11111112
)
11121113

11131114
@staticmethod

bot/handlers/bot_message_handler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
Dict,
1414
List,
1515
Optional,
16+
Tuple,
1617
Union,
1718
)
1819

@@ -216,7 +217,7 @@ async def __extract_clip_with_size_guard(
216217
start_time: float,
217218
end_time: float,
218219
segment: Dict[str, Any],
219-
) -> tuple[Path, float, float]:
220+
) -> Tuple[Path, float, float]:
220221
output = await ClipsExtractor.extract_clip(video_path, start_time, end_time, self._logger)
221222
file_size_bytes = output.stat().st_size
222223
limit_bytes = settings.FILE_SIZE_LIMIT_MB * 1024 * 1024

bot/handlers/not_sending_videos/characters_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
scene_to_search_segment,
2222
)
2323
from bot.search.video_frames import CharacterFinder
24-
from bot.services.search_filter import SearchFilterService
2524
from bot.settings import settings as s
2625
from bot.types import CharacterScene
2726

@@ -52,7 +51,8 @@ async def _do_handle(self) -> None:
5251
user_id = self._message.get_user_id()
5352
series_name = await self._get_user_active_series(user_id)
5453

55-
seasons = await SearchFilterService.get_seasons_from_active_filters(self._message.get_chat_id())
54+
active_filter = await DatabaseManager.get_and_touch_user_filters(self._message.get_chat_id())
55+
seasons = active_filter.get("seasons") if active_filter else None
5656

5757
if not args:
5858
await self.__handle_list_mode(series_name, is_full)

bot/handlers/not_sending_videos/filter_handler.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import math
33
from typing import List
44

5+
from bot.database.database_manager import DatabaseManager
56
from bot.handlers.bot_message_handler import (
67
BotMessageHandler,
78
ValidatorFunctions,
@@ -18,7 +19,6 @@
1819
from bot.services.search_filter import (
1920
FilterParser,
2021
FilterValidator,
21-
SearchFilterService,
2222
)
2323

2424

@@ -51,12 +51,12 @@ async def _do_handle(self) -> None:
5151
await self.__handle_set(chat_id, subcommand, series_name)
5252

5353
async def __handle_reset(self, chat_id: int) -> None:
54-
await SearchFilterService.reset_filters(chat_id)
54+
await DatabaseManager.reset_user_filters(chat_id)
5555
await self._reply(get_filter_reset_message())
5656
await self._log_system_message(logging.INFO, get_log_filter_reset_message(chat_id))
5757

5858
async def __handle_info(self, chat_id: int) -> None:
59-
search_filter = await SearchFilterService.get_filters_for_display(chat_id)
59+
search_filter = await DatabaseManager.get_user_filters(chat_id)
6060
await self._reply(get_filter_info_message(search_filter))
6161

6262
async def __handle_set(self, chat_id: int, raw: str, series_name: str) -> None:
@@ -68,7 +68,7 @@ async def __handle_set(self, chat_id: int, raw: str, series_name: str) -> None:
6868
await self._reply(get_no_args_message())
6969
return
7070
resolved_filter, notes = await FilterValidator.resolve(search_filter, series_name, self._logger)
71-
await SearchFilterService.update_filters(chat_id, resolved_filter)
72-
active = await SearchFilterService.get_filters_for_display(chat_id)
71+
await DatabaseManager.upsert_user_filters(chat_id, resolved_filter)
72+
active = await DatabaseManager.get_user_filters(chat_id)
7373
await self._reply(get_filter_set_message(active or resolved_filter, notes))
7474
await self._log_system_message(logging.INFO, get_log_filter_set_message(chat_id))

bot/handlers/not_sending_videos/objects_handler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
object_scene_to_search_segment,
2626
)
2727
from bot.search.video_frames import ObjectFinder
28-
from bot.services.search_filter import SearchFilterService
2928
from bot.settings import settings as s
3029
from bot.types import (
3130
ObjectScene,
@@ -51,7 +50,7 @@ def _get_usage_message(self) -> str:
5150

5251
async def __check_argument_count(self) -> bool:
5352
command = self._message.get_text().split()[0].lstrip("/").lower()
54-
min_args = 1 if command in ObjectsHandler.__SEARCH_COMMANDS else 0
53+
min_args = command in ObjectsHandler.__SEARCH_COMMANDS
5554
return await self._validate_argument_count(self._message, min_args, math.inf)
5655

5756
async def _do_handle(self) -> None:
@@ -65,7 +64,8 @@ async def _do_handle(self) -> None:
6564
if not args:
6665
await self.__handle_list_mode(series_name, is_full)
6766
else:
68-
seasons = await SearchFilterService.get_seasons_from_active_filters(self._message.get_chat_id())
67+
active_filter = await DatabaseManager.get_and_touch_user_filters(self._message.get_chat_id())
68+
seasons = active_filter.get("seasons") if active_filter else None
6969
if len(args) == 1:
7070
await self.__handle_object_mode(args[0], series_name, is_full, seasons)
7171
else:

bot/handlers/not_sending_videos/search_handler.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
)
2121
from bot.search.filter_applicator import FilterApplicator
2222
from bot.search.text_segments_finder import TextSegmentsFinder
23-
from bot.services.search_filter import SearchFilterService
2423
from bot.settings import settings
2524

2625

@@ -58,7 +57,7 @@ async def _do_handle(self) -> None:
5857
active_series = await self._get_user_active_series(user_id)
5958
chat_id = self._message.get_chat_id()
6059

61-
search_filter = await SearchFilterService.get_active_filters(chat_id)
60+
search_filter = await DatabaseManager.get_and_touch_user_filters(chat_id)
6261

6362
segments = await TextSegmentsFinder.find_segment_by_quote(
6463
quote, self._logger, active_series,

bot/handlers/not_sending_videos/semantic_search_handler.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
)
2525
from bot.search.filter_applicator import FilterApplicator
2626
from bot.search.semantic_segments_finder import SemanticSearchMode
27-
from bot.services.search_filter import SearchFilterService
2827
from bot.utils.constants import EpisodeMetadataKeys
2928

3029

@@ -68,19 +67,20 @@ async def _handle_semantic_results(
6867
return
6968

7069
chat_id = self._message.get_chat_id()
71-
search_filter = await SearchFilterService.get_active_filters(chat_id)
72-
73-
if search_filter and mode != SemanticSearchMode.EPISODE:
74-
results = await FilterApplicator.apply_to_text_segments(
75-
results, search_filter, active_series, self._logger,
76-
)
77-
elif search_filter:
78-
seasons = FilterApplicator.get_seasons_list(search_filter)
79-
if seasons:
80-
results = [
81-
r for r in results
82-
if r.get(EpisodeMetadataKeys.EPISODE_METADATA, {}).get(EpisodeMetadataKeys.SEASON) in seasons
83-
]
70+
search_filter = await DatabaseManager.get_and_touch_user_filters(chat_id)
71+
72+
if search_filter:
73+
if mode == SemanticSearchMode.EPISODE:
74+
seasons = FilterApplicator.get_seasons_list(search_filter)
75+
if seasons:
76+
results = [
77+
r for r in results
78+
if r.get(EpisodeMetadataKeys.EPISODE_METADATA, {}).get(EpisodeMetadataKeys.SEASON) in seasons
79+
]
80+
else:
81+
results = await FilterApplicator.apply_to_text_segments(
82+
results, search_filter, active_series, self._logger,
83+
)
8484

8585
if not results:
8686
await self.__reply_no_segments_found(query)

bot/handlers/not_sending_videos/transcription_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Tuple,
77
)
88

9+
from bot.database.database_manager import DatabaseManager
910
from bot.handlers.bot_message_handler import (
1011
BotMessageHandler,
1112
ValidatorFunctions,
@@ -22,7 +23,6 @@
2223
from bot.search.scene_finder import SceneFinder
2324
from bot.search.text_segments_finder import TextSegmentsFinder
2425
from bot.services.scene_snap.scene_snap_service import SceneSnapService
25-
from bot.services.search_filter import SearchFilterService
2626
from bot.types import TranscriptionContext
2727
from bot.utils.constants import (
2828
EpisodeMetadataKeys,
@@ -48,7 +48,7 @@ async def _do_handle(self) -> None:
4848
quote = " ".join(args[1:])
4949

5050
active_series = await self._get_user_active_series(self._message.get_user_id())
51-
search_filter = await SearchFilterService.get_active_filters(self._message.get_chat_id())
51+
search_filter = await DatabaseManager.get_and_touch_user_filters(self._message.get_chat_id())
5252

5353
result = await TextSegmentsFinder.find_segment_with_context(
5454
quote, self._logger, active_series, context_size=15, search_filter=search_filter,

bot/handlers/sending_videos/character_clip_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
get_no_scenes_found_message,
1414
)
1515
from bot.search.video_frames import CharacterFinder
16-
from bot.services.search_filter import SearchFilterService
1716
from bot.settings import settings
1817

1918

@@ -35,7 +34,8 @@ async def _do_handle(self) -> None:
3534
user_id = self._message.get_user_id()
3635
series_name = await self._get_user_active_series(user_id)
3736

38-
seasons = await SearchFilterService.get_seasons_from_active_filters(self._message.get_chat_id())
37+
active_filter = await DatabaseManager.get_and_touch_user_filters(self._message.get_chat_id())
38+
seasons = active_filter.get("seasons") if active_filter else None
3939

4040
character, emotion_input, emotion_en = await self._find_character(args, series_name)
4141
if character is None:

bot/handlers/sending_videos/clip_handler.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from bot.search.filter_applicator import FilterApplicator
2323
from bot.search.text_segments_finder import TextSegmentsFinder
2424
from bot.services.scene_snap.scene_snap_service import SceneSnapService
25-
from bot.services.search_filter import SearchFilterService
2625
from bot.settings import settings
2726
from bot.utils.constants import SegmentKeys
2827
from bot.video.clips_extractor import ClipsExtractor
@@ -59,7 +58,7 @@ async def _do_handle(self) -> None:
5958

6059
active_series = await self._get_user_active_series(msg.get_user_id())
6160

62-
search_filter = await SearchFilterService.get_active_filters(msg.get_chat_id())
61+
search_filter = await DatabaseManager.get_and_touch_user_filters(msg.get_chat_id())
6362

6463
raw = await TextSegmentsFinder.find_segment_by_quote(
6564
quote, self._logger, active_series,

0 commit comments

Comments
 (0)