Repository: python-discord/bot

Issue:
make the "!otn s" command non case sensitive
make the "!otn s" command non case sensitive for easier querying. We would do this by casting the query into lowercase using `str.lower()` on the search, therefor making the command non case sensitive, because channel names are also stored in full lowercase.




Discussion:

Resolving patch:
diff --git a/bot/converters.py b/bot/converters.py
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -357,27 +357,38 @@ async def convert(self, ctx: Context, duration: str) -> datetime:
 class OffTopicName(Converter):
     """A converter that ensures an added off-topic name is valid."""
 
+    ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?'`-"
+
+    @classmethod
+    def translate_name(cls, name: str, *, from_unicode: bool = True) -> str:
+        """
+        Translates `name` into a format that is allowed in discord channel names.
+
+        If `from_unicode` is True, the name is translated from a discord-safe format, back to normalized text.
+        """
+        if from_unicode:
+            table = str.maketrans(cls.ALLOWED_CHARACTERS, '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ？’’-')
+        else:
+            table = str.maketrans('𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ？’’-', cls.ALLOWED_CHARACTERS)
+
+        return name.translate(table)
+
     async def convert(self, ctx: Context, argument: str) -> str:
         """Attempt to replace any invalid characters with their approximate Unicode equivalent."""
-        allowed_characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?'`-"
-
         # Chain multiple words to a single one
         argument = "-".join(argument.split())
 
         if not (2 <= len(argument) <= 96):
             raise BadArgument("Channel name must be between 2 and 96 chars long")
 
-        elif not all(c.isalnum() or c in allowed_characters for c in argument):
+        elif not all(c.isalnum() or c in self.ALLOWED_CHARACTERS for c in argument):
             raise BadArgument(
                 "Channel name must only consist of "
                 "alphanumeric characters, minus signs or apostrophes."
             )
 
         # Replace invalid characters with unicode alternatives.
-        table = str.maketrans(
-            allowed_characters, '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ？’’-'
-        )
-        return argument.translate(table)
+        return self.translate_name(argument)
 
 
 class ISODateTime(Converter):
diff --git a/bot/exts/fun/off_topic_names.py b/bot/exts/fun/off_topic_names.py
--- a/bot/exts/fun/off_topic_names.py
+++ b/bot/exts/fun/off_topic_names.py
@@ -139,10 +139,20 @@ async def list_command(self, ctx: Context) -> None:
     @has_any_role(*MODERATION_ROLES)
     async def search_command(self, ctx: Context, *, query: OffTopicName) -> None:
         """Search for an off-topic name."""
-        result = await self.bot.api_client.get('bot/off-topic-channel-names')
-        in_matches = {name for name in result if query in name}
-        close_matches = difflib.get_close_matches(query, result, n=10, cutoff=0.70)
-        lines = sorted(f"• {name}" for name in in_matches.union(close_matches))
+        query = OffTopicName.translate_name(query, from_unicode=False).lower()
+
+        # Map normalized names to returned names for search purposes
+        result = {
+            OffTopicName.translate_name(name, from_unicode=False).lower(): name
+            for name in await self.bot.api_client.get('bot/off-topic-channel-names')
+        }
+
+        # Search normalized keys
+        in_matches = {name for name in result.keys() if query in name}
+        close_matches = difflib.get_close_matches(query, result.keys(), n=10, cutoff=0.70)
+
+        # Send Results
+        lines = sorted(f"• {result[name]}" for name in in_matches.union(close_matches))
         embed = Embed(
             title="Query results",
             colour=Colour.blue()


Test patch: