Repository: Cog-Creators/Red-DiscordBot

Issue:
[V3 Mongo] Unescaped username/password
# Other bugs

<!-- 
Did you find a bug with something other than a command? Fill out the following:
-->

#### What were you trying to do?

`redbot <instance>` to start the instance after setting up mongodb with authentication. Using the latest V3/Develop build.

#### What were you expecting to happen?

redbot asks for token / prefix and begins.

#### What actually happened?

<details><summary>This traceback (clicky)</summary><p>

```python
Traceback (most recent call last):
  File "/home/zephyrkul/.pyenv/versions/red/bin/redbot", line 11, in <module>
    load_entry_point('Red-DiscordBot==3.0.0b20', 'console_scripts', 'redbot')()
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/__main__.py", line 131, in main
    red = Red(cli_flags=cli_flags, description=description, pm_help=None)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/core/bot.py", line 42, in __init__
    self.db = Config.get_core_conf(force_registration=True)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/core/config.py", line 579, in get_core_conf
    driver_name, "Core", "0", data_path_override=core_path, **driver_details
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/core/drivers/__init__.py", line 32, in get_driver
    return Mongo(*args, **kwargs)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/core/drivers/red_mongo.py", line 35, in __init__
    _initialize(**kwargs)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/redbot/core/drivers/red_mongo.py", line 23, in _initialize
    _conn = motor.motor_asyncio.AsyncIOMotorClient(url)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/motor/core.py", line 141, in __init__
    delegate = self.__delegate_class__(*args, **kwargs)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/pymongo/mongo_client.py", line 494, in __init__
    res = uri_parser.parse_uri(entity, port, warn=True)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/pymongo/uri_parser.py", line 379, in parse_uri
    user, passwd = parse_userinfo(userinfo)
  File "/home/zephyrkul/.pyenv/versions/red/lib/python3.7/site-packages/pymongo/uri_parser.py", line 97, in parse_userinfo
    "RFC 3986, use %s()." % quote_fn)
pymongo.errors.InvalidURI: Username and password must be escaped according to RFC 3986, use urllib.parse.quote_plus().
```

</p></details>

#### How can we reproduce this issue?

Setup a mongo user with a username / password with URL-unsafe characters and run `redbot-setup`, then run `redbot <instance>`.

#### Small note

Opening a Python interpreter and running `quote_plus` on my username / password and passing the percent-encoded strings to `redbot-setup` fixed it on my end.


Discussion:

Resolving patch:
diff --git a/redbot/core/drivers/red_mongo.py b/redbot/core/drivers/red_mongo.py
--- a/redbot/core/drivers/red_mongo.py
+++ b/redbot/core/drivers/red_mongo.py
@@ -1,5 +1,6 @@
 import motor.motor_asyncio
 from .red_base import BaseDriver
+from urllib.parse import quote_plus
 
 __all__ = ["Mongo"]
 
@@ -15,7 +16,9 @@ def _initialize(**kwargs):
     db_name = kwargs.get("DB_NAME", "default_db")
 
     if admin_user is not None and admin_pass is not None:
-        url = "mongodb://{}:{}@{}:{}/{}".format(admin_user, admin_pass, host, port, db_name)
+        url = "mongodb://{}:{}@{}:{}/{}".format(
+            quote_plus(admin_user), quote_plus(admin_pass), host, port, db_name
+        )
     else:
         url = "mongodb://{}:{}/{}".format(host, port, db_name)
 


Test patch: