Repository: Cog-Creators/Red-DiscordBot

Issue:
[Audio/Core] MessagePredicate regex and escape chars
# Command bugs

#### Command name

[p]playlist copy
<https://github.com/Cog-Creators/Red-DiscordBot/blob/57d5c0870a2c704c8225af6c901bcda58c9a30bb/redbot/cogs/audio/audio.py#L1633>

[p]playlist queue
<https://github.com/Cog-Creators/Red-DiscordBot/blob/57d5c0870a2c704c8225af6c901bcda58c9a30bb/redbot/cogs/audio/audio.py#L1871>

#### What cog is this command from?

Audio, but could be in any cog that uses the MessagePredicate regex to check for the bot's prefix

#### What were you expecting to happen?

A user with a prefix of `\` to be able to use bot commands during the MessagePredicate active times.

#### What actually happened?

```
[2019-06-21 18:07:09] [ERROR] red: Exception in command 'playlist copy'
Traceback (most recent call last):
  File "c:\envs\3.1\lib\site-packages\discord\ext\commands\core.py", line 63, in wrapped
    ret = await coro(*args, **kwargs)
  File "c:\envs\3.1\lib\site-packages\redbot\cogs\audio\audio.py", line 1632, in _playlist_copy
    check=MessagePredicate.regex(fr"^(?!{ctx.prefix})", ctx),
  File "c:\program files (x86)\python37-32\Lib\asyncio\tasks.py", line 416, in wait_for
    return fut.result()
  File "c:\envs\3.1\lib\site-packages\discord\client.py", line 277, in dispatch
    result = condition(*args)
  File "c:\envs\3.1\lib\site-packages\redbot\core\utils\predicates.py", line 62, in __call__
    return self._pred(self, message)
  File "c:\envs\3.1\lib\site-packages\redbot\core\utils\predicates.py", line 793, in predicate
    pattern_obj = re.compile(pattern)
  File "c:\envs\3.1\lib\re.py", line 234, in compile
    return _compile(pattern, flags)
  File "c:\envs\3.1\lib\re.py", line 286, in _compile
    p = sre_compile.compile(pattern, flags)
  File "c:\envs\3.1\lib\sre_compile.py", line 764, in compile
    p = sre_parse.parse(p, flags)
  File "c:\envs\3.1\lib\sre_parse.py", line 930, in parse
    p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
  File "c:\envs\3.1\lib\sre_parse.py", line 426, in _parse_sub
    not nested and not items))
  File "c:\envs\3.1\lib\sre_parse.py", line 742, in _parse
    source.tell() - start)
re.error: missing ), unterminated subpattern at position 1
```

#### How can we reproduce this issue?

Set a prefix of an escape character (`\`) or other possible troublesome regex-related character, use playlist copy with that prefix to copy a playlist that already has an existing target playlist of that name, and then when the bot asks you for a new playlist name to save the copy to, use any bot command with that prefix.



Discussion:
I don't think this is actually a bug (in MessagePredicate, it is in audio)

The correct solution is to give it a proper regex (`re.escape(ctx.prefix)` to prevent the issue)

We can't escape for consumers, as we'd turn it into a string literal search.


Resolving patch:
diff --git a/redbot/cogs/audio/audio.py b/redbot/cogs/audio/audio.py
--- a/redbot/cogs/audio/audio.py
+++ b/redbot/cogs/audio/audio.py
@@ -1630,7 +1630,7 @@ async def _playlist_copy(self, ctx, playlist_name, from_server_id: int, to_serve
                         playlist_name_msg = await ctx.bot.wait_for(
                             "message",
                             timeout=15.0,
-                            check=MessagePredicate.regex(fr"^(?!{ctx.prefix})", ctx),
+                            check=MessagePredicate.regex(fr"^(?!{re.escape(ctx.prefix)})", ctx),
                         )
                         new_playlist_name = playlist_name_msg.content.split(" ")[0].strip('"')
                         if len(new_playlist_name) > 20:
@@ -1868,7 +1868,7 @@ async def _playlist_queue(self, ctx, playlist_name=None):
                 playlist_name_msg = await ctx.bot.wait_for(
                     "message",
                     timeout=15.0,
-                    check=MessagePredicate.regex(fr"^(?!{ctx.prefix})", ctx),
+                    check=MessagePredicate.regex(fr"^(?!{re.escape(ctx.prefix)})", ctx),
                 )
                 playlist_name = playlist_name_msg.content.split(" ")[0].strip('"')
                 if len(playlist_name) > 20:


Test patch: