Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 78 additions & 47 deletions techsupport_bot/commands/factoids.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,6 @@ async def add_factoid(

# Removes the factoid from the cache
await self.handle_cache(guild, name)

await auxiliary.send_confirm_embed(
message=f"Successfully {fmt} the factoid `{factoid_name}`",
channel=ctx.channel,
Expand Down Expand Up @@ -1900,34 +1899,64 @@ async def send_factoids_as_file(

def search_content_and_bold(
self: Self, original: str, search_string: str
) -> list[str]:
"""Searches a string for a substring and bolds it
) -> str | None:
"""Finds all starting indices of the search_string in the original string.

Args:
original (str): The original content to search through
search_string (str): The string we are searching for
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
str | None: A single string with bolded matches and surrounding context,
or None if no matches exist.
"""
# 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}**"

original = original.replace(search_string, f"**{search_string}**")

show_range = 20

indices = []
search_len = len(search_string)
for i in range(len(original) - search_len + 1):
if original[i : i + search_len] == search_string:
indices.append(i)

if len(indices) == 0:
return None

# Generate ranges to include
ranges_to_include = []
for start in indices:
ranges_to_include.append(
(
max(0, start - show_range - 2),
min(len(original), start + search_len + show_range + 2),
)
)
matches_list.append(context_with_formatting.replace("****", ""))

return matches_list
# Minimize ranges by merging overlapping or adjacent ranges
minimized_ranges = []
for start, end in sorted(ranges_to_include):
if minimized_ranges and start <= minimized_ranges[-1][1]:
minimized_ranges[-1] = (
min(minimized_ranges[-1][0], start),
max(minimized_ranges[-1][1], end),
)
else:
minimized_ranges.append((start, end))

ranges_to_strs = []

if minimized_ranges[0][0] != 0:
ranges_to_strs.append("")

for include_range in minimized_ranges:
ranges_to_strs.append(original[include_range[0] : include_range[1]])

if minimized_ranges[len(minimized_ranges) - 1][1] != len(original):
ranges_to_strs.append("")

return "...".join(ranges_to_strs)

@auxiliary.with_typing
@commands.guild_only()
Expand Down Expand Up @@ -1956,43 +1985,45 @@ async def search(self: Self, ctx: commands.Context, *, query: str) -> None:

factoids = await self.get_all_factoids(guild, list_hidden=False)
matches = {}

for factoid in factoids:
if factoid.alias:
continue

factoid_key = ", ".join(await self.get_list_of_aliases(factoid.name, guild))
if query in factoid.name.lower():

# Name string
name_highlight = self.search_content_and_bold(factoid_key.lower(), query)
if name_highlight:
if factoid_key in matches:
matches[factoid_key].append(
f"Name: {factoid.name.lower().replace(query, f'**{query}**')}"
)
matches[factoid_key].append(f"Name: {name_highlight}")
else:
matches[factoid_key] = [
f"Name: {factoid.name.lower().replace(query, f'**{query}**')}"
]
matches[factoid_key] = [f"Name: {name_highlight}"]

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
content_highlight = self.search_content_and_bold(
factoid.message.lower(), query
)
if content_highlight:
if factoid_key in matches:
matches[factoid_key].append(f"Content: {content_highlight}")
else:
matches[factoid_key] = [f"Content: {content_highlight}"]

if (
factoid.embed_config is not None
and query in factoid.embed_config.lower()
):
matches_list = self.search_content_and_bold(
# Embed
if factoid.embed_config is not None:
embed_highlight = self.search_content_and_bold(
factoid.embed_config.lower(), query
)
for match in matches_list:
if embed_highlight:
if factoid_key in matches:
matches[factoid_key].append(
f"Embed: {match.replace('_', '`_`')}"
f"Embed: {embed_highlight.replace('_', '`_`')}"
)
else:
matches[factoid_key] = [f"Embed: {match.replace('_', '`_`')}"]
matches[factoid_key] = [
f"Embed: {embed_highlight.replace('_', '`_`')}"
]

if len(matches) == 0:
embed = auxiliary.prepare_deny_embed(
f"No factoids could be found matching `{query}`"
Expand Down
Loading