Skip to content

Commit

Permalink
Adds more details to factoid search (#1089)
Browse files Browse the repository at this point in the history
* Adds more details to factoid search

* formatting

* Fixes empty matches
  • Loading branch information
ajax146 authored Jul 22, 2024
1 parent 5c7ed19 commit 4d2bd4d
Showing 1 changed file with 103 additions and 45 deletions.
148 changes: 103 additions & 45 deletions techsupport_bot/commands/factoids.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,27 @@ async def get_factoid(

return factoid

async def get_list_of_aliases(
self: Self, factoid_to_search: str, guild: str
) -> list[str]:
"""Gets an alphabetical list of all ways to call a factoid
This will include the internal parent AND all aliases
Args:
factoid_to_search (str): The name of the factoid to search for aliases of
guild (str): The guild to search for factoids in
Returns:
list[str]: The list of all ways to call the factoid, including what was passed
"""
factoid = await self.get_factoid(factoid_to_search, guild)
alias_list = [factoid.name]
factoids = await self.get_all_factoids(guild)
for test_factoid in factoids:
if test_factoid.alias and test_factoid.alias == factoid.name:
alias_list.append(test_factoid.name)
return sorted(alias_list)

# -- Adding and removing factoids --

async def add_factoid(
Expand Down Expand Up @@ -1970,13 +1991,44 @@ async def send_factoids_as_file(
# Returns the file
return yaml_file

def search_content_and_bold(
self: Self, original: str, search_string: str
) -> list[str]:
"""Searches a string for a substring and bolds it
Args:
original (str): The original content to search through
search_string (str): The string we are searching for
Returns:
list[str]: Snippets that have been modified with the search string
"""
# Compile the regular expression for the substring
pattern = re.compile(re.escape(search_string))
matches = list(pattern.finditer(original))

matches_list = []

# Print all instances with 20 characters before and after each occurrence
for match in matches:
start = max(match.start() - 20, 0)
end = min(match.end() + 20, len(original))
context = original[start:end]
# Replace the substring in the context with the formatted version
context_with_formatting = context.replace(
search_string, f"**{search_string}**"
)
matches_list.append(context_with_formatting.replace("****", ""))

return matches_list

@auxiliary.with_typing
@commands.guild_only()
@factoid.command(
aliases=["find"],
brief="Searches a factoid",
description="Searches a factoid by name and contents",
usage="[optional-flag]",
usage="[search-query]",
)
async def search(self: Self, ctx: commands.Context, *, query: str) -> None:
"""Commands to search a factoid
Expand All @@ -1996,54 +2048,60 @@ async def search(self: Self, ctx: commands.Context, *, query: str) -> None:
return

factoids = await self.get_all_factoids(guild, list_hidden=False)
# Makes query lowercase, makes sure you can't search for JSON elements
embed = discord.Embed(color=discord.Color.green())
num_of_matches = 0
matches = {}

# - Name matches -
name_matches = "`"
for factoid in factoids:
# Hard limit of 10
if num_of_matches > 10:
name_matches = name_matches[:-2] + " more...---"
break

if not factoid.alias and query in factoid.name.lower():
name_matches += f"{factoid.name}`, `"
num_of_matches += 1

if name_matches == "`":
name_matches = "No matches found!, `"

# Adds name matches to the embed
embed.add_field(name="Name matches", value=name_matches[:-3], inline=False)
factoid_key = ", ".join(await self.get_list_of_aliases(factoid.name, guild))
if query in factoid.name.lower():
if factoid_key in matches:
matches[factoid_key].append(
f"Name: {factoid.name.lower().replace(query, f'**{query}**')}"
)
else:
matches[factoid_key] = [
f"Name: {factoid.name.lower().replace(query, f'**{query}**')}"
]

if query in factoid.message.lower():
matches_list = self.search_content_and_bold(
factoid.message.lower(), query
)
for match in matches_list:
if factoid_key in matches:
matches[factoid_key].append(f"Content: {match}")
else:
matches[factoid_key] = [f"Content: {match}"]

# - Content matches -
num_of_matches = 0
content_matches = "`"
for factoid in factoids:
# Hard limit of 10
if num_of_matches > 10:
content_matches = content_matches[:-2] + " more...---"
break

if factoid.embed_config is not None and (
any(word in factoid.embed_config.lower() for word in query.split())
or any(word in factoid.message.lower() for word in query.split())
if (
factoid.embed_config is not None
and query in factoid.embed_config.lower()
):
content_matches += f"{factoid.name}`, `"
num_of_matches += 1

if content_matches == "`":
content_matches = "No matches found! "

# Adds content matches to the embed
embed.add_field(
name="Content matches", value=content_matches[:-3], inline=False
)

# Finally, send the embed
await ctx.send(embed=embed)
matches_list = self.search_content_and_bold(
factoid.embed_config.lower(), query
)
for match in matches_list:
if factoid_key in matches:
matches[factoid_key].append(
f"Embed: {match.replace('_', '`_`')}"
)
else:
matches[factoid_key] = [f"Embed: {match.replace('_', '`_`')}"]
if len(matches) == 0:
embed = auxiliary.prepare_deny_embed(
f"No factoids could be found matching `{query}`"
)
await ctx.send(embed=embed)
return
embeds = []
embed = discord.Embed(color=discord.Color.green())
for index, match in enumerate(matches):
if index > 0 and index % 10 == 0:
embeds.append(embed)
embed = discord.Embed(color=discord.Color.green())
embed.add_field(name=match, value="\n".join(matches.get(match)))

embeds.append(embed)
await ui.PaginateView().send(ctx.channel, ctx.author, embeds)

@auxiliary.with_typing
@commands.check(has_manage_factoids_role)
Expand Down

0 comments on commit 4d2bd4d

Please sign in to comment.