We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
API.AI Error when network is disconnected
The following error should be caught and warned about cleanly.

```
ERROR asyncio: Task exception was never retrieved
future: <Task finished coro=<parse_apiai() done, defined at /Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py:34> exception=ClientConnectorError(8, 'Cannot connect to host api.api.ai:443 ssl:True [nodename nor servname provided, or not known]')>
Traceback (most recent call last):
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py", line 375, in connect
    proto = yield from self._create_connection(req)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py", line 632, in _create_connection
    _, proto = yield from self._create_direct_connection(req)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py", line 643, in _create_direct_connection
    hosts = yield from self._resolve_host(req.url.raw_host, req.port)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py", line 615, in _resolve_host
    self._resolver.resolve(host, port, family=self._family)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/resolver.py", line 30, in resolve
    host, port, type=socket.SOCK_STREAM, family=family)
  File "/opt/boxen/homebrew/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/opt/boxen/homebrew/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 743, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py", line 42, in parse_apiai
    result = await call_apiai(message, config)
  File "/Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py", line 27, in call_apiai
    headers=headers)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/client.py", line 621, in __await__
    resp = yield from self._coro
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/client.py", line 225, in _request
    conn = yield from self._connector.connect(req)
  File "/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py", line 380, in connect
    .format(key, exc.strerror)) from exc
aiohttp.client_exceptions.ClientConnectorError: [Errno 8] Cannot connect to host api.api.ai:443 ssl:True [nodename nor servname provided, or not known]
```

--- 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/parsers/apiai.py`
Content:
```
1 """A helper function for parsing and executing api.ai skills."""
2 
3 import logging
4 import json
5 
6 import aiohttp
7 
8 
9 _LOGGER = logging.getLogger(__name__)
10 
11 
12 async def call_apiai(message, config):
13     """Call the api.ai api and return the response."""
14     async with aiohttp.ClientSession() as session:
15         payload = {
16             "v": "20150910",
17             "lang": "en",
18             "sessionId": message.connector.name,
19             "query": message.text
20         }
21         headers = {
22             "Authorization": "Bearer " + config['access-token'],
23             "Content-Type": "application/json"
24         }
25         resp = await session.post("https://api.api.ai/v1/query",
26                                   data=json.dumps(payload),
27                                   headers=headers)
28         result = await resp.json()
29         _LOGGER.debug("api.ai response - " + json.dumps(result))
30 
31         return result
32 
33 
34 async def parse_apiai(opsdroid, message, config):
35     """Parse a message against all apiai skills."""
36     # pylint: disable=broad-except
37     # We want to catch all exceptions coming from a skill module and not
38     # halt the application. If a skill throws an exception it just doesn't
39     # give a response to the user, so an error response should be given.
40     if 'access-token' in config:
41 
42         result = await call_apiai(message, config)
43 
44         if result["status"]["code"] >= 300:
45             _LOGGER.error("api.ai error - " +
46                           str(result["status"]["code"]) + " " +
47                           result["status"]["errorType"])
48             return
49 
50         if "min-score" in config and \
51                 result["result"]["score"] < config["min-score"]:
52             _LOGGER.debug("api.ai score lower than min-score")
53             return
54 
55         if result:
56             for skill in opsdroid.skills:
57 
58                 if "apiai_action" in skill or "apiai_intent" in skill:
59                     if ("action" in result["result"] and
60                             skill["apiai_action"] in
61                             result["result"]["action"]) \
62                             or ("intentName" in result["result"] and
63                                 skill["apiai_intent"] in
64                                 result["result"]["intentName"]):
65                         message.apiai = result
66                         try:
67                             await skill["skill"](opsdroid, skill["config"],
68                                                  message)
69                         except Exception:
70                             await message.respond(
71                                 "Whoops there has been an error")
72                             await message.respond(
73                                 "Check the log for details")
74                             _LOGGER.exception("Exception when parsing '" +
75                                               message.text +
76                                               "' against skill '" +
77                                               result["result"]["action"] + "'")
78
```
--- 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/parsers/apiai.py b/opsdroid/parsers/apiai.py
--- a/opsdroid/parsers/apiai.py
+++ b/opsdroid/parsers/apiai.py
@@ -38,8 +38,11 @@
     # halt the application. If a skill throws an exception it just doesn't
     # give a response to the user, so an error response should be given.
     if 'access-token' in config:
-
-        result = await call_apiai(message, config)
+        try:
+            result = await call_apiai(message, config)
+        except aiohttp.ClientOSError:
+            _LOGGER.error("No response from api.ai, check your network.")
+            return
 
         if result["status"]["code"] >= 300:
             _LOGGER.error("api.ai error - " +

{"golden_diff": "diff --git a/opsdroid/parsers/apiai.py b/opsdroid/parsers/apiai.py\n--- a/opsdroid/parsers/apiai.py\n+++ b/opsdroid/parsers/apiai.py\n@@ -38,8 +38,11 @@\n     # halt the application. If a skill throws an exception it just doesn't\n     # give a response to the user, so an error response should be given.\n     if 'access-token' in config:\n-\n-        result = await call_apiai(message, config)\n+        try:\n+            result = await call_apiai(message, config)\n+        except aiohttp.ClientOSError:\n+            _LOGGER.error(\"No response from api.ai, check your network.\")\n+            return\n \n         if result[\"status\"][\"code\"] >= 300:\n             _LOGGER.error(\"api.ai error - \" +\n", "issue": "API.AI Error when network is disconnected\nThe following error should be caught and warned about cleanly.\r\n\r\n```\r\nERROR asyncio: Task exception was never retrieved\r\nfuture: <Task finished coro=<parse_apiai() done, defined at /Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py:34> exception=ClientConnectorError(8, 'Cannot connect to host api.api.ai:443 ssl:True [nodename nor servname provided, or not known]')>\r\nTraceback (most recent call last):\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py\", line 375, in connect\r\n    proto = yield from self._create_connection(req)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py\", line 632, in _create_connection\r\n    _, proto = yield from self._create_direct_connection(req)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py\", line 643, in _create_direct_connection\r\n    hosts = yield from self._resolve_host(req.url.raw_host, req.port)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py\", line 615, in _resolve_host\r\n    self._resolver.resolve(host, port, family=self._family)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/resolver.py\", line 30, in resolve\r\n    host, port, type=socket.SOCK_STREAM, family=family)\r\n  File \"/opt/boxen/homebrew/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py\", line 55, in run\r\n    result = self.fn(*self.args, **self.kwargs)\r\n  File \"/opt/boxen/homebrew/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py\", line 743, in getaddrinfo\r\n    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):\r\nsocket.gaierror: [Errno 8] nodename nor servname provided, or not known\r\n\r\nThe above exception was the direct cause of the following exception:\r\n\r\nTraceback (most recent call last):\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py\", line 42, in parse_apiai\r\n    result = await call_apiai(message, config)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/opsdroid/parsers/apiai.py\", line 27, in call_apiai\r\n    headers=headers)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/client.py\", line 621, in __await__\r\n    resp = yield from self._coro\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/client.py\", line 225, in _request\r\n    conn = yield from self._connector.connect(req)\r\n  File \"/Users/jacob/Projects/opsdroid/opsdroid/venv/lib/python3.6/site-packages/aiohttp/connector.py\", line 380, in connect\r\n    .format(key, exc.strerror)) from exc\r\naiohttp.client_exceptions.ClientConnectorError: [Errno 8] Cannot connect to host api.api.ai:443 ssl:True [nodename nor servname provided, or not known]\r\n```\n", "before_files": [{"content": "\"\"\"A helper function for parsing and executing api.ai skills.\"\"\"\n\nimport logging\nimport json\n\nimport aiohttp\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nasync def call_apiai(message, config):\n    \"\"\"Call the api.ai api and return the response.\"\"\"\n    async with aiohttp.ClientSession() as session:\n        payload = {\n            \"v\": \"20150910\",\n            \"lang\": \"en\",\n            \"sessionId\": message.connector.name,\n            \"query\": message.text\n        }\n        headers = {\n            \"Authorization\": \"Bearer \" + config['access-token'],\n            \"Content-Type\": \"application/json\"\n        }\n        resp = await session.post(\"https://api.api.ai/v1/query\",\n                                  data=json.dumps(payload),\n                                  headers=headers)\n        result = await resp.json()\n        _LOGGER.debug(\"api.ai response - \" + json.dumps(result))\n\n        return result\n\n\nasync def parse_apiai(opsdroid, message, config):\n    \"\"\"Parse a message against all apiai skills.\"\"\"\n    # pylint: disable=broad-except\n    # We want to catch all exceptions coming from a skill module and not\n    # halt the application. If a skill throws an exception it just doesn't\n    # give a response to the user, so an error response should be given.\n    if 'access-token' in config:\n\n        result = await call_apiai(message, config)\n\n        if result[\"status\"][\"code\"] >= 300:\n            _LOGGER.error(\"api.ai error - \" +\n                          str(result[\"status\"][\"code\"]) + \" \" +\n                          result[\"status\"][\"errorType\"])\n            return\n\n        if \"min-score\" in config and \\\n                result[\"result\"][\"score\"] < config[\"min-score\"]:\n            _LOGGER.debug(\"api.ai score lower than min-score\")\n            return\n\n        if result:\n            for skill in opsdroid.skills:\n\n                if \"apiai_action\" in skill or \"apiai_intent\" in skill:\n                    if (\"action\" in result[\"result\"] and\n                            skill[\"apiai_action\"] in\n                            result[\"result\"][\"action\"]) \\\n                            or (\"intentName\" in result[\"result\"] and\n                                skill[\"apiai_intent\"] in\n                                result[\"result\"][\"intentName\"]):\n                        message.apiai = result\n                        try:\n                            await skill[\"skill\"](opsdroid, skill[\"config\"],\n                                                 message)\n                        except Exception:\n                            await message.respond(\n                                \"Whoops there has been an error\")\n                            await message.respond(\n                                \"Check the log for details\")\n                            _LOGGER.exception(\"Exception when parsing '\" +\n                                              message.text +\n                                              \"' against skill '\" +\n                                              result[\"result\"][\"action\"] + \"'\")\n", "path": "opsdroid/parsers/apiai.py"}], "after_files": [{"content": "\"\"\"A helper function for parsing and executing api.ai skills.\"\"\"\n\nimport logging\nimport json\n\nimport aiohttp\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nasync def call_apiai(message, config):\n    \"\"\"Call the api.ai api and return the response.\"\"\"\n    async with aiohttp.ClientSession() as session:\n        payload = {\n            \"v\": \"20150910\",\n            \"lang\": \"en\",\n            \"sessionId\": message.connector.name,\n            \"query\": message.text\n        }\n        headers = {\n            \"Authorization\": \"Bearer \" + config['access-token'],\n            \"Content-Type\": \"application/json\"\n        }\n        resp = await session.post(\"https://api.api.ai/v1/query\",\n                                  data=json.dumps(payload),\n                                  headers=headers)\n        result = await resp.json()\n        _LOGGER.debug(\"api.ai response - \" + json.dumps(result))\n\n        return result\n\n\nasync def parse_apiai(opsdroid, message, config):\n    \"\"\"Parse a message against all apiai skills.\"\"\"\n    # pylint: disable=broad-except\n    # We want to catch all exceptions coming from a skill module and not\n    # halt the application. If a skill throws an exception it just doesn't\n    # give a response to the user, so an error response should be given.\n    if 'access-token' in config:\n        try:\n            result = await call_apiai(message, config)\n        except aiohttp.ClientOSError:\n            _LOGGER.error(\"No response from api.ai, check your network.\")\n            return\n\n        if result[\"status\"][\"code\"] >= 300:\n            _LOGGER.error(\"api.ai error - \" +\n                          str(result[\"status\"][\"code\"]) + \" \" +\n                          result[\"status\"][\"errorType\"])\n            return\n\n        if \"min-score\" in config and \\\n                result[\"result\"][\"score\"] < config[\"min-score\"]:\n            _LOGGER.debug(\"api.ai score lower than min-score\")\n            return\n\n        if result:\n            for skill in opsdroid.skills:\n\n                if \"apiai_action\" in skill or \"apiai_intent\" in skill:\n                    if (\"action\" in result[\"result\"] and\n                            skill[\"apiai_action\"] in\n                            result[\"result\"][\"action\"]) \\\n                            or (\"intentName\" in result[\"result\"] and\n                                skill[\"apiai_intent\"] in\n                                result[\"result\"][\"intentName\"]):\n                        message.apiai = result\n                        try:\n                            await skill[\"skill\"](opsdroid, skill[\"config\"],\n                                                 message)\n                        except Exception:\n                            await message.respond(\n                                \"Whoops there has been an error\")\n                            await message.respond(\n                                \"Check the log for details\")\n                            _LOGGER.exception(\"Exception when parsing '\" +\n                                              message.text +\n                                              \"' against skill '\" +\n                                              result[\"result\"][\"action\"] + \"'\")\n", "path": "opsdroid/parsers/apiai.py"}]}