From bafc78b07e2c6d9df0e2c56da9c60a7b1a4b12ff Mon Sep 17 00:00:00 2001 From: ajax146 <31014239+ajax146@users.noreply.github.com> Date: Sun, 21 Jul 2024 23:29:53 -0400 Subject: [PATCH 1/3] Adds more details to factoid search --- techsupport_bot/commands/factoids.py | 131 ++++++++++++++++++--------- 1 file changed, 86 insertions(+), 45 deletions(-) diff --git a/techsupport_bot/commands/factoids.py b/techsupport_bot/commands/factoids.py index 83b5add99..c0d70f463 100644 --- a/techsupport_bot/commands/factoids.py +++ b/techsupport_bot/commands/factoids.py @@ -620,6 +620,17 @@ async def get_factoid( return factoid + async def get_list_of_aliases( + self: Self, factoid_to_search: str, guild: str + ) -> list[str]: + 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( @@ -1970,13 +1981,42 @@ async def send_factoids_as_file( # Returns the file return yaml_file + def search_content_and_bold(self, original: str, search_string: str) -> list[str]: + """Searches a string for a substring and bolds it + + Args: + original (str): _description_ + search_string (str): _description_ + + Returns: + list[str]: _description_ + """ + # 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 @@ -1996,54 +2036,55 @@ 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('_', '`_`')}"] + + 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) From 7cfb2d03e41e9b6492f79a4f518f91a9eaf75798 Mon Sep 17 00:00:00 2001 From: ajax146 <31014239+ajax146@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:49:13 -0400 Subject: [PATCH 2/3] formatting --- techsupport_bot/commands/factoids.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/techsupport_bot/commands/factoids.py b/techsupport_bot/commands/factoids.py index c0d70f463..ec6a644f1 100644 --- a/techsupport_bot/commands/factoids.py +++ b/techsupport_bot/commands/factoids.py @@ -623,6 +623,16 @@ async def get_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) @@ -1981,15 +1991,17 @@ async def send_factoids_as_file( # Returns the file return yaml_file - def search_content_and_bold(self, original: str, search_string: str) -> list[str]: + 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): _description_ - search_string (str): _description_ + original (str): The original content to search through + search_string (str): The string we are searching for Returns: - list[str]: _description_ + 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)) From 0f89cfa5cc2187d39407a43af73812f11e88007a Mon Sep 17 00:00:00 2001 From: ajax146 <31014239+ajax146@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:28:47 -0400 Subject: [PATCH 3/3] Fixes empty matches --- techsupport_bot/commands/factoids.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/techsupport_bot/commands/factoids.py b/techsupport_bot/commands/factoids.py index ec6a644f1..9d470ba16 100644 --- a/techsupport_bot/commands/factoids.py +++ b/techsupport_bot/commands/factoids.py @@ -2086,7 +2086,12 @@ async def search(self: Self, ctx: commands.Context, *, query: str) -> None: ) 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):