diff options
| author | salmonik <raisersoft@proton.me> | 2025-10-20 17:45:37 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2025-10-20 17:45:37 +0200 |
| commit | 19ff005b7d340bf271c8cde245857d512f5148db (patch) | |
| tree | 8f68e197cd083062069e991146da881593430e51 /cogs | |
| parent | upload to server if file too big for conv (diff) | |
| download | senator-sperma-19ff005b7d340bf271c8cde245857d512f5148db.tar.gz senator-sperma-19ff005b7d340bf271c8cde245857d512f5148db.zip | |
simplified the searching algorithm
Diffstat (limited to 'cogs')
| -rw-r--r-- | cogs/music/play_utils.py | 60 |
1 files changed, 13 insertions, 47 deletions
diff --git a/cogs/music/play_utils.py b/cogs/music/play_utils.py index ad2a2e1..6fa0edd 100644 --- a/cogs/music/play_utils.py +++ b/cogs/music/play_utils.py | |||
| @@ -196,16 +196,15 @@ class PlayUtils: | |||
| 196 | # -- LOCAL PLAY -- | 196 | # -- LOCAL PLAY -- |
| 197 | 197 | ||
| 198 | @staticmethod | 198 | @staticmethod |
| 199 | async def search_local(query, max_results=5, min_score=30): | 199 | async def search_local(query, max_results=5): |
| 200 | """Search for audio files using fuzzy matching on both filename and path. | 200 | """Search for audio files that contain the query in their name (case-insensitive). |
| 201 | 201 | ||
| 202 | Args: | 202 | Args: |
| 203 | query: Search query string | 203 | query: Search query string |
| 204 | max_results: Maximum number of results to return | 204 | max_results: Maximum number of results to return |
| 205 | min_score: Minimum score threshold for matches (0-100) | ||
| 206 | 205 | ||
| 207 | Returns: | 206 | Returns: |
| 208 | List of matching file paths, sorted by relevance | 207 | List of matching file paths |
| 209 | """ | 208 | """ |
| 210 | logger.info(f"Starting local search for query: '{query}'") | 209 | logger.info(f"Starting local search for query: '{query}'") |
| 211 | try: | 210 | try: |
| @@ -214,9 +213,8 @@ class PlayUtils: | |||
| 214 | search_paths = data.get('audio_paths', []) | 213 | search_paths = data.get('audio_paths', []) |
| 215 | logger.info(f"Searching in paths: {search_paths}") | 214 | logger.info(f"Searching in paths: {search_paths}") |
| 216 | 215 | ||
| 217 | candidates = [] | 216 | matches = [] |
| 218 | files_checked = 0 | 217 | q = query.lower() |
| 219 | q = query.lower().replace('_', ' ').replace('-', ' ') | ||
| 220 | 218 | ||
| 221 | for path in search_paths: | 219 | for path in search_paths: |
| 222 | path = Path(path) | 220 | path = Path(path) |
| @@ -231,51 +229,19 @@ class PlayUtils: | |||
| 231 | if not file_path.is_file(): | 229 | if not file_path.is_file(): |
| 232 | continue | 230 | continue |
| 233 | 231 | ||
| 234 | files_checked += 1 | ||
| 235 | |||
| 236 | # Check if file has a valid extension | 232 | # Check if file has a valid extension |
| 237 | if file_path.suffix.lower() not in {'.mp4', '.mp3', '.wav', '.opus', '.m4a'}: | 233 | if file_path.suffix.lower() not in {'.mp4', '.mp3', '.wav', '.opus', '.m4a'}: |
| 238 | continue | 234 | continue |
| 239 | 235 | ||
| 240 | # Get relative path from search root | 236 | # Check if query is in filename (case-insensitive) |
| 241 | rel_path = file_path.relative_to(path).parent | 237 | if q in file_path.name.lower(): |
| 242 | 238 | matches.append(str(file_path.absolute())) | |
| 243 | # Create searchable strings | 239 | if len(matches) >= max_results: |
| 244 | filename = Utils.normalize_name(file_path, keep_ext=False) | 240 | logger.info(f"Found {len(matches)} matches, stopping search") |
| 245 | full_path_str = str(rel_path / file_path.stem).lower() | 241 | return matches |
| 246 | |||
| 247 | # Calculate scores | ||
| 248 | score_filename = Utils.combined_score(q, filename) | ||
| 249 | score_path = Utils.combined_score(q, full_path_str) | ||
| 250 | |||
| 251 | # Use the better score | ||
| 252 | score = max(score_filename, score_path) | ||
| 253 | |||
| 254 | # Apply bonuses | ||
| 255 | depth_bonus = max(0, 1.0 - (len(rel_path.parts) / 10.0)) # Prefer shallower paths | ||
| 256 | ext_bonus = 1.1 if file_path.suffix.lower() in q.split('.')[-1].lower() else 1.0 | ||
| 257 | |||
| 258 | final_score = score * (0.9 + depth_bonus * 0.1) * ext_bonus | ||
| 259 | |||
| 260 | if final_score >= min_score: | ||
| 261 | candidates.append((final_score, str(file_path.absolute()))) | ||
| 262 | logger.debug(f"Match: {file_path} (score: {final_score:.1f})") | ||
| 263 | |||
| 264 | logger.info(f"Search complete. Checked {files_checked} files, found {len(candidates)} matches.") | ||
| 265 | |||
| 266 | if not candidates: | ||
| 267 | logger.warning("No matching audio files found.") | ||
| 268 | return [] | ||
| 269 | |||
| 270 | # Sort by score (descending) and get top results | ||
| 271 | candidates.sort(key=lambda x: x[0], reverse=True) | ||
| 272 | top_matches = candidates[:max_results] | ||
| 273 | |||
| 274 | logger.info(f"Top {len(top_matches)} matches:") | ||
| 275 | for i, (score, path) in enumerate(top_matches, 1): | ||
| 276 | logger.info(f" {i}. {path} (score: {score:.1f})") | ||
| 277 | 242 | ||
| 278 | return [c[1] for c in top_matches] | 243 | logger.info(f"Search complete. Found {len(matches)} matches.") |
| 244 | return matches | ||
| 279 | 245 | ||
| 280 | except Exception as e: | 246 | except Exception as e: |
| 281 | logger.error(f"Error during local search: {str(e)}", exc_info=True) | 247 | logger.error(f"Error during local search: {str(e)}", exc_info=True) |
