We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add --load-config flag
Need a flag for installing local skill dependencies when running a dockerized app. Should call the install new requirements.txt from skills loaded by `path` without running the bot

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `opsdroid/cli/utils.py`
Content:
```
1 """Utilities for the opsdroid CLI commands."""
2 
3 import click
4 import gettext
5 import os
6 import logging
7 import subprocess
8 import sys
9 import time
10 import warnings
11 
12 from opsdroid.core import OpsDroid
13 from opsdroid.configuration import load_config_file
14 from opsdroid.const import (
15     DEFAULT_LOG_FILENAME,
16     LOCALE_DIR,
17     DEFAULT_LANGUAGE,
18     DEFAULT_CONFIG_PATH,
19     DEFAULT_CONFIG_LOCATIONS,
20 )
21 from opsdroid.helper import get_config_option
22 from opsdroid.loader import Loader
23 
24 _LOGGER = logging.getLogger("opsdroid")
25 
26 path_option = click.option(
27     "-f",
28     "path",
29     help="Load a configuration from a path instead of using the default location.",
30     type=click.Path(exists=True),
31 )
32 
33 
34 def edit_files(ctx, param, value):
35     """Open config/log file with favourite editor.
36 
37     Args:
38         ctx (:obj:`click.Context`): The current click cli context.
39         param (dict): a dictionary of all parameters pass to the click
40             context when invoking this function as a callback.
41         value (string): the value of this parameter after invocation.
42             It is either "config" or "log" depending on the program
43             calling this function.
44 
45     Returns:
46         int: the exit code. Always returns 0 in this case.
47 
48     """
49 
50     if value == "config":
51         file = DEFAULT_CONFIG_PATH
52         if ctx.command.name == "cli":
53             warn_deprecated_cli_option(
54                 "The flag -e/--edit-files has been deprecated. "
55                 "Please run `opsdroid config edit` instead."
56             )
57     elif value == "log":
58         file = DEFAULT_LOG_FILENAME
59         if ctx.command.name == "cli":
60             warn_deprecated_cli_option(
61                 "The flag -l/--view-log has been deprecated. "
62                 "Please run `opsdroid logs` instead."
63             )
64     else:
65         return
66 
67     editor = os.environ.get("EDITOR", "vi")
68     if editor == "vi":
69         click.echo(
70             "You are about to edit a file in vim. \n"
71             "Read the tutorial on vim at: https://bit.ly/2HRvvrB"
72         )
73         time.sleep(3)
74 
75     subprocess.run([editor, file])
76     ctx.exit(0)
77 
78 
79 def validate_config(ctx, path, value):
80     """Validate opsdroid configuration.
81 
82     We load the configuration and modules from it to run the validation on them.
83     Only modules that contain the constant variable `CONFIG_SCHEMA` will be validated
84     the ones without it will just be silent.
85 
86     Note that if the path doesn't exist or is a bad one click will throw an error telling
87     you that the path doesn't exist. Also, the file needs to be either a json or a yaml file.
88 
89 
90     Args:
91         ctx (:obj:`click.Context`): The current click cli context.
92         path (string): a string representing the path to load the config,
93             obtained from `ctx.obj`.
94         value (string): the value of this parameter after invocation.
95             It is either "config" or "log" depending on the program
96             calling this function.
97 
98     Returns:
99         int: the exit code. Always returns 0 in this case.
100 
101     """
102     with OpsDroid() as opsdroid:
103         loader = Loader(opsdroid)
104 
105         config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)
106 
107         loader.load_modules_from_config(config)
108         click.echo("Configuration validated - No errors founds!")
109 
110         ctx.exit(0)
111 
112 
113 def warn_deprecated_cli_option(text):
114     """Warn users that the cli option they have used is deprecated."""
115     print(f"Warning: {text}")
116     warnings.warn(text, DeprecationWarning)
117 
118 
119 def configure_lang(config):
120     """Configure app language based on user config.
121 
122     Args:
123         config: Language Configuration and it uses ISO 639-1 code.
124         for more info https://en.m.wikipedia.org/wiki/List_of_ISO_639-1_codes
125 
126 
127     """
128     lang_code = config.get("lang", DEFAULT_LANGUAGE)
129     if lang_code != DEFAULT_LANGUAGE:
130         lang = gettext.translation("opsdroid", LOCALE_DIR, (lang_code,), fallback=True)
131         lang.install()
132 
133 
134 def check_dependencies():
135     """Check for system dependencies required by opsdroid.
136 
137     Returns:
138         int: the exit code. Returns 1 if the Python version installed is
139         below 3.6.
140 
141     """
142     if sys.version_info.major < 3 or sys.version_info.minor < 6:
143         logging.critical(_("Whoops! opsdroid requires python 3.6 or above."))
144         sys.exit(1)
145 
146 
147 def welcome_message(config):
148     """Add welcome message if set to true in configuration.
149 
150     Args:
151         config: config loaded by Loader
152 
153     Raises:
154         KeyError: If 'welcome-message' key is not found in configuration file
155 
156     """
157     try:
158         if config["welcome-message"]:
159             _LOGGER.info("=" * 40)
160             _LOGGER.info(
161                 _(
162                     "You can customise your opsdroid by modifying your configuration.yaml."
163                 )
164             )
165             _LOGGER.info(
166                 _("Read more at: http://opsdroid.readthedocs.io/#configuration")
167             )
168             _LOGGER.info(_("Watch the Get Started Videos at: http://bit.ly/2fnC0Fh"))
169             _LOGGER.info(
170                 _(
171                     "Install Opsdroid Desktop at: \n"
172                     "https://github.com/opsdroid/opsdroid-desktop/releases"
173                 )
174             )
175             _LOGGER.info("=" * 40)
176     except KeyError:
177         _LOGGER.warning(
178             _("'welcome-message: true/false' is missing in configuration.yaml")
179         )
180 
181 
182 def list_all_modules(ctx, path, value):
183     """List the active modules from config.
184 
185     This function will try to get information from the modules that are active in the
186     configuration file and print them as a table or will just print a sentence saying that
187     there are no active modules for that type.
188 
189     Args:
190         ctx (:obj:`click.Context`): The current click cli context.
191         path (str): a str that contains a path passed.
192         value (string): the value of this parameter after invocation.
193             It is either "config" or "log" depending on the program
194             calling this function.
195 
196     Returns:
197         int: the exit code. Always returns 0 in this case.
198 
199     """
200     config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)
201 
202     click.echo(
203         click.style(
204             f"{'NAME':15} {'TYPE':15} {'MODE':15} {'CACHED':15}  {'LOCATION':15}",
205             fg="blue",
206             bold=True,
207         )
208     )
209     for module_type, module in config.items():
210         if module_type in ("connectors", "databases", "parsers", "skills"):
211             for name, options in module.items():
212 
213                 mode = get_config_option(
214                     ["repo", "path", "gist"], options, True, "module"
215                 )
216                 cache = get_config_option(["no-cache"], options, "no", "yes")
217                 location = get_config_option(
218                     ["repo", "path", "gist"],
219                     options,
220                     True,
221                     f"opsdroid.{module_type}.{name}",
222                 )
223 
224                 click.echo(
225                     f"{name:15} {module_type:15} {mode[1]:15} {cache[0]:15}  {location[2]:15}"
226                 )
227 
228     ctx.exit(0)
229
```

Path: `opsdroid/cli/config.py`
Content:
```
1 """The config subcommand for opsdroid cli."""
2 
3 import click
4 
5 from opsdroid.cli.utils import (
6     edit_files,
7     warn_deprecated_cli_option,
8     validate_config,
9     list_all_modules,
10     path_option,
11 )
12 from opsdroid.const import EXAMPLE_CONFIG_FILE
13 
14 
15 def print_example_config(ctx, param, value):
16     """[Deprecated] Print out the example config.
17 
18     Args:
19         ctx (:obj:`click.Context`): The current click cli context.
20         param (dict): a dictionary of all parameters pass to the click
21             context when invoking this function as a callback.
22         value (bool): the value of this parameter after invocation.
23             Defaults to False, set to True when this flag is called.
24 
25     Returns:
26         int: the exit code. Always returns 0 in this case.
27 
28     """
29     if not value or ctx.resilient_parsing:
30         return
31     if ctx.command.name == "cli":
32         warn_deprecated_cli_option(
33             "The flag --gen-config has been deprecated. "
34             "Please run `opsdroid config gen` instead."
35         )
36     with open(EXAMPLE_CONFIG_FILE, "r") as conf:
37         click.echo(conf.read())
38     ctx.exit(0)
39 
40 
41 @click.group()
42 @path_option
43 @click.pass_context
44 def config(ctx, path):
45     """Subcommands related to opsdroid configuration."""
46     ctx.obj = path
47 
48 
49 @config.command()
50 @click.pass_context
51 def gen(ctx):
52     """Print out the example config.
53 
54     This is a pretty basic function that will simply open your opsdroid
55     configuration file and prints the whole thing into the terminal.
56     You can also use the -f flag to generate a config from a path instead
57     of using the default config location.
58 
59     Args:
60         ctx (:obj:`click.Context`): The current click cli context.
61 
62     Returns:
63         int: the exit code. Always returns 0 in this case.
64 
65     """
66     print_example_config(ctx, ctx.obj, True)
67 
68 
69 @config.command()
70 @click.pass_context
71 def edit(ctx):
72     """Open config file with your favourite editor.
73 
74     By default this command will open the configuration file with
75     vi/vim. If you have a different editor that you would like to sure,
76     you need to change the environment variable - `EDITOR`.
77 
78     Args:
79         ctx (:obj:`click.Context`): The current click cli context.
80 
81     Returns:
82         int: the exit code. Always returns 0 in this case.
83 
84     """
85     edit_files(ctx, None, "config")
86 
87 
88 @config.command()
89 @click.pass_context
90 def lint(ctx):
91     """Validate the configuration.
92 
93     This subcommand allows you to validate your configuration or a configuration
94     from a file if the -f flag is used. This avoids the need to start the bot just
95     to have it crash because of a configuration error.
96 
97     This command could also be helpful if you need to do changes to the configuration but
98     you are unsure if everything is set correct. You could have the new config
99     file located somewhere and test it before using it to start opsdroid.
100 
101     Args:
102         ctx (:obj:`click.Context`): The current click cli context.
103 
104     Returns:
105         int: the exit code. Always returns 0 in this case.
106 
107     """
108     validate_config(ctx, ctx.obj, "config")
109 
110 
111 @config.command()
112 @click.pass_context
113 def list_modules(ctx):
114     """Print out a list of all active modules.
115 
116     This function will try to get information from the modules that are active in the
117     configuration file and print them as a table or will just print a sentence saying that
118     there are no active modules for that type.
119 
120     Args:
121         ctx (:obj:`click.Context`): The current click cli context.
122 
123     Returns:
124         int: the exit code. Always returns 0 in this case.
125 
126     """
127     list_all_modules(ctx, ctx.obj, "config")
128
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/opsdroid/cli/config.py b/opsdroid/cli/config.py
--- a/opsdroid/cli/config.py
+++ b/opsdroid/cli/config.py
@@ -3,11 +3,12 @@
 import click
 
 from opsdroid.cli.utils import (
+    build_config,
     edit_files,
-    warn_deprecated_cli_option,
-    validate_config,
     list_all_modules,
     path_option,
+    validate_config,
+    warn_deprecated_cli_option,
 )
 from opsdroid.const import EXAMPLE_CONFIG_FILE
 
@@ -125,3 +126,31 @@
 
     """
     list_all_modules(ctx, ctx.obj, "config")
+
+
+@config.command()
+@click.pass_context
+@click.option(
+    "--verbose",
+    "verbose",
+    is_flag=True,
+    help="Turns logging level to debug to see all logging messages.",
+)
+def build(ctx, verbose):
+    """Load configuration, load modules and install dependencies.
+
+    This function loads the configuration and install all necessary
+    dependencies defined on a `requirements.txt` file inside the module.
+    If the flag `--verbose` is passed the logging level will be set as debug and
+    all logs will be shown to the user.
+
+
+    Args:
+        ctx (:obj:`click.Context`): The current click cli context.
+        verbose (bool): set the logging level to debug.
+
+    Returns:
+        int: the exit code. Always returns 0 in this case.
+
+    """
+    build_config(ctx, {"path": ctx.obj, "verbose": verbose}, "config")
diff --git a/opsdroid/cli/utils.py b/opsdroid/cli/utils.py
--- a/opsdroid/cli/utils.py
+++ b/opsdroid/cli/utils.py
@@ -1,6 +1,7 @@
 """Utilities for the opsdroid CLI commands."""
 
 import click
+import contextlib
 import gettext
 import os
 import logging
@@ -20,6 +21,8 @@
 )
 from opsdroid.helper import get_config_option
 from opsdroid.loader import Loader
+from opsdroid.logging import configure_logging
+
 
 _LOGGER = logging.getLogger("opsdroid")
 
@@ -226,3 +229,44 @@
                 )
 
     ctx.exit(0)
+
+
+def build_config(ctx, params, value):
+    """Load configuration, load modules and install dependencies.
+
+    This function loads the configuration and install all necessary
+    dependencies defined on a `requirements.txt` file inside the module.
+    If the flag `--verbose` is passed the logging level will be set as debug and
+    all logs will be shown to the user.
+
+
+    Args:
+        ctx (:obj:`click.Context`): The current click cli context.
+        params (dict): a dictionary of all parameters pass to the click
+            context when invoking this function as a callback.
+        value (string): the value of this parameter after invocation.
+            It is either "config" or "log" depending on the program
+            calling this function.
+
+    Returns:
+        int: the exit code. Always returns 0 in this case.
+
+    """
+    click.echo("Opsdroid will build modules from config.")
+    path = params.get("path")
+
+    with contextlib.suppress(Exception):
+        check_dependencies()
+
+        config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)
+
+        if params["verbose"]:
+            config["logging"] = {"level": "debug"}
+            configure_logging(config)
+
+        with OpsDroid(config=config) as opsdroid:
+
+            opsdroid.loader.load_modules_from_config(config)
+
+            click.echo(click.style("SUCCESS:", bg="green", bold=True), nl=False)
+            click.echo(" Opsdroid modules successfully built from config.")

{"golden_diff": "diff --git a/opsdroid/cli/config.py b/opsdroid/cli/config.py\n--- a/opsdroid/cli/config.py\n+++ b/opsdroid/cli/config.py\n@@ -3,11 +3,12 @@\n import click\n \n from opsdroid.cli.utils import (\n+    build_config,\n     edit_files,\n-    warn_deprecated_cli_option,\n-    validate_config,\n     list_all_modules,\n     path_option,\n+    validate_config,\n+    warn_deprecated_cli_option,\n )\n from opsdroid.const import EXAMPLE_CONFIG_FILE\n \n@@ -125,3 +126,31 @@\n \n     \"\"\"\n     list_all_modules(ctx, ctx.obj, \"config\")\n+\n+\n+@config.command()\n+@click.pass_context\n+@click.option(\n+    \"--verbose\",\n+    \"verbose\",\n+    is_flag=True,\n+    help=\"Turns logging level to debug to see all logging messages.\",\n+)\n+def build(ctx, verbose):\n+    \"\"\"Load configuration, load modules and install dependencies.\n+\n+    This function loads the configuration and install all necessary\n+    dependencies defined on a `requirements.txt` file inside the module.\n+    If the flag `--verbose` is passed the logging level will be set as debug and\n+    all logs will be shown to the user.\n+\n+\n+    Args:\n+        ctx (:obj:`click.Context`): The current click cli context.\n+        verbose (bool): set the logging level to debug.\n+\n+    Returns:\n+        int: the exit code. Always returns 0 in this case.\n+\n+    \"\"\"\n+    build_config(ctx, {\"path\": ctx.obj, \"verbose\": verbose}, \"config\")\ndiff --git a/opsdroid/cli/utils.py b/opsdroid/cli/utils.py\n--- a/opsdroid/cli/utils.py\n+++ b/opsdroid/cli/utils.py\n@@ -1,6 +1,7 @@\n \"\"\"Utilities for the opsdroid CLI commands.\"\"\"\n \n import click\n+import contextlib\n import gettext\n import os\n import logging\n@@ -20,6 +21,8 @@\n )\n from opsdroid.helper import get_config_option\n from opsdroid.loader import Loader\n+from opsdroid.logging import configure_logging\n+\n \n _LOGGER = logging.getLogger(\"opsdroid\")\n \n@@ -226,3 +229,44 @@\n                 )\n \n     ctx.exit(0)\n+\n+\n+def build_config(ctx, params, value):\n+    \"\"\"Load configuration, load modules and install dependencies.\n+\n+    This function loads the configuration and install all necessary\n+    dependencies defined on a `requirements.txt` file inside the module.\n+    If the flag `--verbose` is passed the logging level will be set as debug and\n+    all logs will be shown to the user.\n+\n+\n+    Args:\n+        ctx (:obj:`click.Context`): The current click cli context.\n+        params (dict): a dictionary of all parameters pass to the click\n+            context when invoking this function as a callback.\n+        value (string): the value of this parameter after invocation.\n+            It is either \"config\" or \"log\" depending on the program\n+            calling this function.\n+\n+    Returns:\n+        int: the exit code. Always returns 0 in this case.\n+\n+    \"\"\"\n+    click.echo(\"Opsdroid will build modules from config.\")\n+    path = params.get(\"path\")\n+\n+    with contextlib.suppress(Exception):\n+        check_dependencies()\n+\n+        config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n+\n+        if params[\"verbose\"]:\n+            config[\"logging\"] = {\"level\": \"debug\"}\n+            configure_logging(config)\n+\n+        with OpsDroid(config=config) as opsdroid:\n+\n+            opsdroid.loader.load_modules_from_config(config)\n+\n+            click.echo(click.style(\"SUCCESS:\", bg=\"green\", bold=True), nl=False)\n+            click.echo(\" Opsdroid modules successfully built from config.\")\n", "issue": "Add --load-config flag\nNeed a flag for installing local skill dependencies when running a dockerized app. Should call the install new requirements.txt from skills loaded by `path` without running the bot\n", "before_files": [{"content": "\"\"\"Utilities for the opsdroid CLI commands.\"\"\"\n\nimport click\nimport gettext\nimport os\nimport logging\nimport subprocess\nimport sys\nimport time\nimport warnings\n\nfrom opsdroid.core import OpsDroid\nfrom opsdroid.configuration import load_config_file\nfrom opsdroid.const import (\n    DEFAULT_LOG_FILENAME,\n    LOCALE_DIR,\n    DEFAULT_LANGUAGE,\n    DEFAULT_CONFIG_PATH,\n    DEFAULT_CONFIG_LOCATIONS,\n)\nfrom opsdroid.helper import get_config_option\nfrom opsdroid.loader import Loader\n\n_LOGGER = logging.getLogger(\"opsdroid\")\n\npath_option = click.option(\n    \"-f\",\n    \"path\",\n    help=\"Load a configuration from a path instead of using the default location.\",\n    type=click.Path(exists=True),\n)\n\n\ndef edit_files(ctx, param, value):\n    \"\"\"Open config/log file with favourite editor.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        param (dict): a dictionary of all parameters pass to the click\n            context when invoking this function as a callback.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n\n    if value == \"config\":\n        file = DEFAULT_CONFIG_PATH\n        if ctx.command.name == \"cli\":\n            warn_deprecated_cli_option(\n                \"The flag -e/--edit-files has been deprecated. \"\n                \"Please run `opsdroid config edit` instead.\"\n            )\n    elif value == \"log\":\n        file = DEFAULT_LOG_FILENAME\n        if ctx.command.name == \"cli\":\n            warn_deprecated_cli_option(\n                \"The flag -l/--view-log has been deprecated. \"\n                \"Please run `opsdroid logs` instead.\"\n            )\n    else:\n        return\n\n    editor = os.environ.get(\"EDITOR\", \"vi\")\n    if editor == \"vi\":\n        click.echo(\n            \"You are about to edit a file in vim. \\n\"\n            \"Read the tutorial on vim at: https://bit.ly/2HRvvrB\"\n        )\n        time.sleep(3)\n\n    subprocess.run([editor, file])\n    ctx.exit(0)\n\n\ndef validate_config(ctx, path, value):\n    \"\"\"Validate opsdroid configuration.\n\n    We load the configuration and modules from it to run the validation on them.\n    Only modules that contain the constant variable `CONFIG_SCHEMA` will be validated\n    the ones without it will just be silent.\n\n    Note that if the path doesn't exist or is a bad one click will throw an error telling\n    you that the path doesn't exist. Also, the file needs to be either a json or a yaml file.\n\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        path (string): a string representing the path to load the config,\n            obtained from `ctx.obj`.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    with OpsDroid() as opsdroid:\n        loader = Loader(opsdroid)\n\n        config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n\n        loader.load_modules_from_config(config)\n        click.echo(\"Configuration validated - No errors founds!\")\n\n        ctx.exit(0)\n\n\ndef warn_deprecated_cli_option(text):\n    \"\"\"Warn users that the cli option they have used is deprecated.\"\"\"\n    print(f\"Warning: {text}\")\n    warnings.warn(text, DeprecationWarning)\n\n\ndef configure_lang(config):\n    \"\"\"Configure app language based on user config.\n\n    Args:\n        config: Language Configuration and it uses ISO 639-1 code.\n        for more info https://en.m.wikipedia.org/wiki/List_of_ISO_639-1_codes\n\n\n    \"\"\"\n    lang_code = config.get(\"lang\", DEFAULT_LANGUAGE)\n    if lang_code != DEFAULT_LANGUAGE:\n        lang = gettext.translation(\"opsdroid\", LOCALE_DIR, (lang_code,), fallback=True)\n        lang.install()\n\n\ndef check_dependencies():\n    \"\"\"Check for system dependencies required by opsdroid.\n\n    Returns:\n        int: the exit code. Returns 1 if the Python version installed is\n        below 3.6.\n\n    \"\"\"\n    if sys.version_info.major < 3 or sys.version_info.minor < 6:\n        logging.critical(_(\"Whoops! opsdroid requires python 3.6 or above.\"))\n        sys.exit(1)\n\n\ndef welcome_message(config):\n    \"\"\"Add welcome message if set to true in configuration.\n\n    Args:\n        config: config loaded by Loader\n\n    Raises:\n        KeyError: If 'welcome-message' key is not found in configuration file\n\n    \"\"\"\n    try:\n        if config[\"welcome-message\"]:\n            _LOGGER.info(\"=\" * 40)\n            _LOGGER.info(\n                _(\n                    \"You can customise your opsdroid by modifying your configuration.yaml.\"\n                )\n            )\n            _LOGGER.info(\n                _(\"Read more at: http://opsdroid.readthedocs.io/#configuration\")\n            )\n            _LOGGER.info(_(\"Watch the Get Started Videos at: http://bit.ly/2fnC0Fh\"))\n            _LOGGER.info(\n                _(\n                    \"Install Opsdroid Desktop at: \\n\"\n                    \"https://github.com/opsdroid/opsdroid-desktop/releases\"\n                )\n            )\n            _LOGGER.info(\"=\" * 40)\n    except KeyError:\n        _LOGGER.warning(\n            _(\"'welcome-message: true/false' is missing in configuration.yaml\")\n        )\n\n\ndef list_all_modules(ctx, path, value):\n    \"\"\"List the active modules from config.\n\n    This function will try to get information from the modules that are active in the\n    configuration file and print them as a table or will just print a sentence saying that\n    there are no active modules for that type.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        path (str): a str that contains a path passed.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n\n    click.echo(\n        click.style(\n            f\"{'NAME':15} {'TYPE':15} {'MODE':15} {'CACHED':15}  {'LOCATION':15}\",\n            fg=\"blue\",\n            bold=True,\n        )\n    )\n    for module_type, module in config.items():\n        if module_type in (\"connectors\", \"databases\", \"parsers\", \"skills\"):\n            for name, options in module.items():\n\n                mode = get_config_option(\n                    [\"repo\", \"path\", \"gist\"], options, True, \"module\"\n                )\n                cache = get_config_option([\"no-cache\"], options, \"no\", \"yes\")\n                location = get_config_option(\n                    [\"repo\", \"path\", \"gist\"],\n                    options,\n                    True,\n                    f\"opsdroid.{module_type}.{name}\",\n                )\n\n                click.echo(\n                    f\"{name:15} {module_type:15} {mode[1]:15} {cache[0]:15}  {location[2]:15}\"\n                )\n\n    ctx.exit(0)\n", "path": "opsdroid/cli/utils.py"}, {"content": "\"\"\"The config subcommand for opsdroid cli.\"\"\"\n\nimport click\n\nfrom opsdroid.cli.utils import (\n    edit_files,\n    warn_deprecated_cli_option,\n    validate_config,\n    list_all_modules,\n    path_option,\n)\nfrom opsdroid.const import EXAMPLE_CONFIG_FILE\n\n\ndef print_example_config(ctx, param, value):\n    \"\"\"[Deprecated] Print out the example config.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        param (dict): a dictionary of all parameters pass to the click\n            context when invoking this function as a callback.\n        value (bool): the value of this parameter after invocation.\n            Defaults to False, set to True when this flag is called.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    if not value or ctx.resilient_parsing:\n        return\n    if ctx.command.name == \"cli\":\n        warn_deprecated_cli_option(\n            \"The flag --gen-config has been deprecated. \"\n            \"Please run `opsdroid config gen` instead.\"\n        )\n    with open(EXAMPLE_CONFIG_FILE, \"r\") as conf:\n        click.echo(conf.read())\n    ctx.exit(0)\n\n\n@click.group()\n@path_option\n@click.pass_context\ndef config(ctx, path):\n    \"\"\"Subcommands related to opsdroid configuration.\"\"\"\n    ctx.obj = path\n\n\n@config.command()\n@click.pass_context\ndef gen(ctx):\n    \"\"\"Print out the example config.\n\n    This is a pretty basic function that will simply open your opsdroid\n    configuration file and prints the whole thing into the terminal.\n    You can also use the -f flag to generate a config from a path instead\n    of using the default config location.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    print_example_config(ctx, ctx.obj, True)\n\n\n@config.command()\n@click.pass_context\ndef edit(ctx):\n    \"\"\"Open config file with your favourite editor.\n\n    By default this command will open the configuration file with\n    vi/vim. If you have a different editor that you would like to sure,\n    you need to change the environment variable - `EDITOR`.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    edit_files(ctx, None, \"config\")\n\n\n@config.command()\n@click.pass_context\ndef lint(ctx):\n    \"\"\"Validate the configuration.\n\n    This subcommand allows you to validate your configuration or a configuration\n    from a file if the -f flag is used. This avoids the need to start the bot just\n    to have it crash because of a configuration error.\n\n    This command could also be helpful if you need to do changes to the configuration but\n    you are unsure if everything is set correct. You could have the new config\n    file located somewhere and test it before using it to start opsdroid.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    validate_config(ctx, ctx.obj, \"config\")\n\n\n@config.command()\n@click.pass_context\ndef list_modules(ctx):\n    \"\"\"Print out a list of all active modules.\n\n    This function will try to get information from the modules that are active in the\n    configuration file and print them as a table or will just print a sentence saying that\n    there are no active modules for that type.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    list_all_modules(ctx, ctx.obj, \"config\")\n", "path": "opsdroid/cli/config.py"}], "after_files": [{"content": "\"\"\"Utilities for the opsdroid CLI commands.\"\"\"\n\nimport click\nimport contextlib\nimport gettext\nimport os\nimport logging\nimport subprocess\nimport sys\nimport time\nimport warnings\n\nfrom opsdroid.core import OpsDroid\nfrom opsdroid.configuration import load_config_file\nfrom opsdroid.const import (\n    DEFAULT_LOG_FILENAME,\n    LOCALE_DIR,\n    DEFAULT_LANGUAGE,\n    DEFAULT_CONFIG_PATH,\n    DEFAULT_CONFIG_LOCATIONS,\n)\nfrom opsdroid.helper import get_config_option\nfrom opsdroid.loader import Loader\nfrom opsdroid.logging import configure_logging\n\n\n_LOGGER = logging.getLogger(\"opsdroid\")\n\npath_option = click.option(\n    \"-f\",\n    \"path\",\n    help=\"Load a configuration from a path instead of using the default location.\",\n    type=click.Path(exists=True),\n)\n\n\ndef edit_files(ctx, param, value):\n    \"\"\"Open config/log file with favourite editor.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        param (dict): a dictionary of all parameters pass to the click\n            context when invoking this function as a callback.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n\n    if value == \"config\":\n        file = DEFAULT_CONFIG_PATH\n        if ctx.command.name == \"cli\":\n            warn_deprecated_cli_option(\n                \"The flag -e/--edit-files has been deprecated. \"\n                \"Please run `opsdroid config edit` instead.\"\n            )\n    elif value == \"log\":\n        file = DEFAULT_LOG_FILENAME\n        if ctx.command.name == \"cli\":\n            warn_deprecated_cli_option(\n                \"The flag -l/--view-log has been deprecated. \"\n                \"Please run `opsdroid logs` instead.\"\n            )\n    else:\n        return\n\n    editor = os.environ.get(\"EDITOR\", \"vi\")\n    if editor == \"vi\":\n        click.echo(\n            \"You are about to edit a file in vim. \\n\"\n            \"Read the tutorial on vim at: https://bit.ly/2HRvvrB\"\n        )\n        time.sleep(3)\n\n    subprocess.run([editor, file])\n    ctx.exit(0)\n\n\ndef validate_config(ctx, path, value):\n    \"\"\"Validate opsdroid configuration.\n\n    We load the configuration and modules from it to run the validation on them.\n    Only modules that contain the constant variable `CONFIG_SCHEMA` will be validated\n    the ones without it will just be silent.\n\n    Note that if the path doesn't exist or is a bad one click will throw an error telling\n    you that the path doesn't exist. Also, the file needs to be either a json or a yaml file.\n\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        path (string): a string representing the path to load the config,\n            obtained from `ctx.obj`.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    with OpsDroid() as opsdroid:\n        loader = Loader(opsdroid)\n\n        config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n\n        loader.load_modules_from_config(config)\n        click.echo(\"Configuration validated - No errors founds!\")\n\n        ctx.exit(0)\n\n\ndef warn_deprecated_cli_option(text):\n    \"\"\"Warn users that the cli option they have used is deprecated.\"\"\"\n    print(f\"Warning: {text}\")\n    warnings.warn(text, DeprecationWarning)\n\n\ndef configure_lang(config):\n    \"\"\"Configure app language based on user config.\n\n    Args:\n        config: Language Configuration and it uses ISO 639-1 code.\n        for more info https://en.m.wikipedia.org/wiki/List_of_ISO_639-1_codes\n\n\n    \"\"\"\n    lang_code = config.get(\"lang\", DEFAULT_LANGUAGE)\n    if lang_code != DEFAULT_LANGUAGE:\n        lang = gettext.translation(\"opsdroid\", LOCALE_DIR, (lang_code,), fallback=True)\n        lang.install()\n\n\ndef check_dependencies():\n    \"\"\"Check for system dependencies required by opsdroid.\n\n    Returns:\n        int: the exit code. Returns 1 if the Python version installed is\n        below 3.6.\n\n    \"\"\"\n    if sys.version_info.major < 3 or sys.version_info.minor < 6:\n        logging.critical(_(\"Whoops! opsdroid requires python 3.6 or above.\"))\n        sys.exit(1)\n\n\ndef welcome_message(config):\n    \"\"\"Add welcome message if set to true in configuration.\n\n    Args:\n        config: config loaded by Loader\n\n    Raises:\n        KeyError: If 'welcome-message' key is not found in configuration file\n\n    \"\"\"\n    try:\n        if config[\"welcome-message\"]:\n            _LOGGER.info(\"=\" * 40)\n            _LOGGER.info(\n                _(\n                    \"You can customise your opsdroid by modifying your configuration.yaml.\"\n                )\n            )\n            _LOGGER.info(\n                _(\"Read more at: http://opsdroid.readthedocs.io/#configuration\")\n            )\n            _LOGGER.info(_(\"Watch the Get Started Videos at: http://bit.ly/2fnC0Fh\"))\n            _LOGGER.info(\n                _(\n                    \"Install Opsdroid Desktop at: \\n\"\n                    \"https://github.com/opsdroid/opsdroid-desktop/releases\"\n                )\n            )\n            _LOGGER.info(\"=\" * 40)\n    except KeyError:\n        _LOGGER.warning(\n            _(\"'welcome-message: true/false' is missing in configuration.yaml\")\n        )\n\n\ndef list_all_modules(ctx, path, value):\n    \"\"\"List the active modules from config.\n\n    This function will try to get information from the modules that are active in the\n    configuration file and print them as a table or will just print a sentence saying that\n    there are no active modules for that type.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        path (str): a str that contains a path passed.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n\n    click.echo(\n        click.style(\n            f\"{'NAME':15} {'TYPE':15} {'MODE':15} {'CACHED':15}  {'LOCATION':15}\",\n            fg=\"blue\",\n            bold=True,\n        )\n    )\n    for module_type, module in config.items():\n        if module_type in (\"connectors\", \"databases\", \"parsers\", \"skills\"):\n            for name, options in module.items():\n\n                mode = get_config_option(\n                    [\"repo\", \"path\", \"gist\"], options, True, \"module\"\n                )\n                cache = get_config_option([\"no-cache\"], options, \"no\", \"yes\")\n                location = get_config_option(\n                    [\"repo\", \"path\", \"gist\"],\n                    options,\n                    True,\n                    f\"opsdroid.{module_type}.{name}\",\n                )\n\n                click.echo(\n                    f\"{name:15} {module_type:15} {mode[1]:15} {cache[0]:15}  {location[2]:15}\"\n                )\n\n    ctx.exit(0)\n\n\ndef build_config(ctx, params, value):\n    \"\"\"Load configuration, load modules and install dependencies.\n\n    This function loads the configuration and install all necessary\n    dependencies defined on a `requirements.txt` file inside the module.\n    If the flag `--verbose` is passed the logging level will be set as debug and\n    all logs will be shown to the user.\n\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        params (dict): a dictionary of all parameters pass to the click\n            context when invoking this function as a callback.\n        value (string): the value of this parameter after invocation.\n            It is either \"config\" or \"log\" depending on the program\n            calling this function.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    click.echo(\"Opsdroid will build modules from config.\")\n    path = params.get(\"path\")\n\n    with contextlib.suppress(Exception):\n        check_dependencies()\n\n        config = load_config_file([path] if path else DEFAULT_CONFIG_LOCATIONS)\n\n        if params[\"verbose\"]:\n            config[\"logging\"] = {\"level\": \"debug\"}\n            configure_logging(config)\n\n        with OpsDroid(config=config) as opsdroid:\n\n            opsdroid.loader.load_modules_from_config(config)\n\n            click.echo(click.style(\"SUCCESS:\", bg=\"green\", bold=True), nl=False)\n            click.echo(\" Opsdroid modules successfully built from config.\")\n", "path": "opsdroid/cli/utils.py"}, {"content": "\"\"\"The config subcommand for opsdroid cli.\"\"\"\n\nimport click\n\nfrom opsdroid.cli.utils import (\n    build_config,\n    edit_files,\n    list_all_modules,\n    path_option,\n    validate_config,\n    warn_deprecated_cli_option,\n)\nfrom opsdroid.const import EXAMPLE_CONFIG_FILE\n\n\ndef print_example_config(ctx, param, value):\n    \"\"\"[Deprecated] Print out the example config.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        param (dict): a dictionary of all parameters pass to the click\n            context when invoking this function as a callback.\n        value (bool): the value of this parameter after invocation.\n            Defaults to False, set to True when this flag is called.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    if not value or ctx.resilient_parsing:\n        return\n    if ctx.command.name == \"cli\":\n        warn_deprecated_cli_option(\n            \"The flag --gen-config has been deprecated. \"\n            \"Please run `opsdroid config gen` instead.\"\n        )\n    with open(EXAMPLE_CONFIG_FILE, \"r\") as conf:\n        click.echo(conf.read())\n    ctx.exit(0)\n\n\n@click.group()\n@path_option\n@click.pass_context\ndef config(ctx, path):\n    \"\"\"Subcommands related to opsdroid configuration.\"\"\"\n    ctx.obj = path\n\n\n@config.command()\n@click.pass_context\ndef gen(ctx):\n    \"\"\"Print out the example config.\n\n    This is a pretty basic function that will simply open your opsdroid\n    configuration file and prints the whole thing into the terminal.\n    You can also use the -f flag to generate a config from a path instead\n    of using the default config location.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    print_example_config(ctx, ctx.obj, True)\n\n\n@config.command()\n@click.pass_context\ndef edit(ctx):\n    \"\"\"Open config file with your favourite editor.\n\n    By default this command will open the configuration file with\n    vi/vim. If you have a different editor that you would like to sure,\n    you need to change the environment variable - `EDITOR`.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    edit_files(ctx, None, \"config\")\n\n\n@config.command()\n@click.pass_context\ndef lint(ctx):\n    \"\"\"Validate the configuration.\n\n    This subcommand allows you to validate your configuration or a configuration\n    from a file if the -f flag is used. This avoids the need to start the bot just\n    to have it crash because of a configuration error.\n\n    This command could also be helpful if you need to do changes to the configuration but\n    you are unsure if everything is set correct. You could have the new config\n    file located somewhere and test it before using it to start opsdroid.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    validate_config(ctx, ctx.obj, \"config\")\n\n\n@config.command()\n@click.pass_context\ndef list_modules(ctx):\n    \"\"\"Print out a list of all active modules.\n\n    This function will try to get information from the modules that are active in the\n    configuration file and print them as a table or will just print a sentence saying that\n    there are no active modules for that type.\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    list_all_modules(ctx, ctx.obj, \"config\")\n\n\n@config.command()\n@click.pass_context\n@click.option(\n    \"--verbose\",\n    \"verbose\",\n    is_flag=True,\n    help=\"Turns logging level to debug to see all logging messages.\",\n)\ndef build(ctx, verbose):\n    \"\"\"Load configuration, load modules and install dependencies.\n\n    This function loads the configuration and install all necessary\n    dependencies defined on a `requirements.txt` file inside the module.\n    If the flag `--verbose` is passed the logging level will be set as debug and\n    all logs will be shown to the user.\n\n\n    Args:\n        ctx (:obj:`click.Context`): The current click cli context.\n        verbose (bool): set the logging level to debug.\n\n    Returns:\n        int: the exit code. Always returns 0 in this case.\n\n    \"\"\"\n    build_config(ctx, {\"path\": ctx.obj, \"verbose\": verbose}, \"config\")\n", "path": "opsdroid/cli/config.py"}]}