Run Black formatter across 83 files and fix 1514 ruff violations: - E722: bare except → typed exceptions (17 fixes) - E711/E712/E721: comparison style fixes with noqa for SQLAlchemy (44 fixes) - F841: unused variable assignments (70 fixes) - F541/F401: f-string and import cleanup (1383 auto-fixes) Remaining 925 errors are all F403/F405 (star imports) — structural, requires converting to explicit imports in a separate effort. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
108 lines
2.8 KiB
Python
108 lines
2.8 KiB
Python
"""
|
|
Search Utilities
|
|
|
|
This module contains search and fuzzy matching functionality.
|
|
"""
|
|
|
|
import discord
|
|
from difflib import get_close_matches
|
|
from typing import Optional
|
|
|
|
|
|
def fuzzy_search(name, master_list):
|
|
"""
|
|
Perform fuzzy string matching against a list of options.
|
|
|
|
Args:
|
|
name: String to search for
|
|
master_list: List of strings to search against
|
|
|
|
Returns:
|
|
Best match string or raises ValueError if no good matches
|
|
"""
|
|
if name.lower() in master_list:
|
|
return name.lower()
|
|
|
|
great_matches = get_close_matches(name, master_list, cutoff=0.8)
|
|
if len(great_matches) == 1:
|
|
return great_matches[0]
|
|
elif len(great_matches) > 0:
|
|
matches = great_matches
|
|
else:
|
|
matches = get_close_matches(name, master_list, n=6)
|
|
if len(matches) == 1:
|
|
return matches[0]
|
|
|
|
if not matches:
|
|
raise ValueError(f"{name.title()} was not found")
|
|
|
|
return matches[0]
|
|
|
|
|
|
async def fuzzy_player_search(ctx, channel, bot, name, master_list):
|
|
"""
|
|
Interactive fuzzy player search with Discord UI.
|
|
|
|
Takes a name to search and returns the name of the best match.
|
|
|
|
Args:
|
|
ctx: discord context
|
|
channel: discord channel
|
|
bot: discord.py bot object
|
|
name: string to search for
|
|
master_list: list of names to search against
|
|
|
|
Returns:
|
|
Selected match or None if cancelled
|
|
"""
|
|
# Import here to avoid circular imports
|
|
from discord_ui.confirmations import Question
|
|
|
|
matches = fuzzy_search(name, master_list)
|
|
|
|
embed = discord.Embed(
|
|
title="Did You Mean...",
|
|
description="Enter the number of the card you would like to see.",
|
|
color=0x7FC600,
|
|
)
|
|
count = 1
|
|
for x in matches:
|
|
embed.add_field(name=f"{count}", value=x, inline=False)
|
|
count += 1
|
|
embed.set_footer(
|
|
text="These are the closest matches. Spell better if they're not who you want."
|
|
)
|
|
this_q = Question(bot, channel, None, "int", 45, embed=embed)
|
|
resp = await this_q.ask([ctx.author])
|
|
|
|
if not resp:
|
|
return None
|
|
if resp < count:
|
|
return matches[resp - 1]
|
|
else:
|
|
raise ValueError(f"{resp} is not a valid response.")
|
|
|
|
|
|
async def cardset_search(cardset: str, cardset_list: list) -> Optional[dict]:
|
|
"""
|
|
Search for a cardset by name and return the cardset data.
|
|
|
|
Args:
|
|
cardset: Cardset name to search for
|
|
cardset_list: List of available cardset names
|
|
|
|
Returns:
|
|
Cardset dictionary or None if not found
|
|
"""
|
|
# Import here to avoid circular imports
|
|
from api_calls import db_get
|
|
|
|
cardset_name = fuzzy_search(cardset, cardset_list)
|
|
if not cardset_name:
|
|
return None
|
|
|
|
c_query = await db_get("cardsets", params=[("name", cardset_name)])
|
|
if c_query["count"] == 0:
|
|
return None
|
|
return c_query["cardsets"][0]
|