prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add case-insensitive kwarg to the regex matcher
  It would be nice to specify case insensitive matching in the regex matcher.
  
  e.g
  ```python
  @match_regex(r'myregex', case_sensitive=False)
  async def myskill(opsdroid, config, message):
      pass
  ```
  
  </issue>
  <code>
  [start of opsdroid/parsers/regex.py]
  1 """A helper function for parsing and executing regex skills."""
  2 
  3 import logging
  4 import re
  5 
  6 
  7 _LOGGER = logging.getLogger(__name__)
  8 
  9 
  10 async def parse_regex(opsdroid, message):
  11     """Parse a message against all regex skills."""
  12     # pylint: disable=broad-except
  13     # We want to catch all exceptions coming from a skill module and not
  14     # halt the application. If a skill throws an exception it just doesn't
  15     # give a response to the user, so an error response should be given.
  16     for skill in opsdroid.skills:
  17         if "regex" in skill:
  18             regex = re.match(skill["regex"], message.text)
  19             if regex:
  20                 message.regex = regex
  21                 try:
  22                     await skill["skill"](opsdroid, skill["config"], message)
  23                 except Exception:
  24                     await message.respond(
  25                         "Whoops there has been an error")
  26                     await message.respond(
  27                         "Check the log for details")
  28                     _LOGGER.exception("Exception when parsing '" +
  29                                       message.text +
  30                                       "' against skill '" +
  31                                       skill["regex"] + "'")
  32
  [end of opsdroid/parsers/regex.py]
  [start of opsdroid/matchers.py]
  1 """Decorator functions to use when creating skill modules."""
  2 
  3 import logging
  4 
  5 from opsdroid.helper import get_opsdroid
  6 from opsdroid.web import Web
  7 
  8 
  9 _LOGGER = logging.getLogger(__name__)
  10 
  11 
  12 def match_regex(regex):
  13     """Return regex match decorator."""
  14     def matcher(func):
  15         """Add decorated function to skills list for regex matching."""
  16         opsdroid = get_opsdroid()
  17         opsdroid.skills.append({"regex": regex, "skill": func,
  18                                 "config":
  19                                 opsdroid.loader.current_import_config})
  20         return func
  21     return matcher
  22 
  23 
  24 def match_apiai_action(action):
  25     """Return apiai action match decorator."""
  26     def matcher(func):
  27         """Add decorated function to skills list for apiai matching."""
  28         opsdroid = get_opsdroid()
  29         opsdroid.skills.append({"apiai_action": action, "skill": func,
  30                                 "config":
  31                                 opsdroid.loader.current_import_config})
  32         return func
  33     return matcher
  34 
  35 
  36 def match_apiai_intent(intent):
  37     """Return apiai intent match decorator."""
  38     def matcher(func):
  39         """Add decorated function to skills list for apiai matching."""
  40         opsdroid = get_opsdroid()
  41         opsdroid.skills.append({"apiai_intent": intent, "skill": func,
  42                                 "config":
  43                                 opsdroid.loader.current_import_config})
  44         return func
  45     return matcher
  46 
  47 
  48 def match_crontab(crontab, timezone=None):
  49     """Return crontab match decorator."""
  50     def matcher(func):
  51         """Add decorated function to skills list for crontab matching."""
  52         opsdroid = get_opsdroid()
  53         config = opsdroid.loader.current_import_config
  54         opsdroid.skills.append({"crontab": crontab, "skill": func,
  55                                 "config": config, "timezone": timezone})
  56         return func
  57     return matcher
  58 
  59 
  60 def match_webhook(webhook):
  61     """Return webhook match decorator."""
  62     def matcher(func):
  63         """Add decorated function to skills list for webhook matching."""
  64         opsdroid = get_opsdroid()
  65         config = opsdroid.loader.current_import_config
  66         opsdroid.skills.append({"webhook": webhook, "skill": func,
  67                                 "config": config})
  68 
  69         async def wrapper(req, opsdroid=opsdroid, config=config):
  70             """Wrap up the aiohttp handler."""
  71             _LOGGER.info("Running skill %s via webhook", webhook)
  72             opsdroid.stats["webhooks_called"] = \
  73                 opsdroid.stats["webhooks_called"] + 1
  74             await func(opsdroid, config, req)
  75             return Web.build_response(200, {"called_skill": webhook})
  76 
  77         opsdroid.web_server.web_app.router.add_post(
  78             "/skill/{}/{}".format(config["name"], webhook), wrapper)
  79         opsdroid.web_server.web_app.router.add_post(
  80             "/skill/{}/{}/".format(config["name"], webhook), wrapper)
  81 
  82         return func
  83     return matcher
  84
  [end of opsdroid/matchers.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/opsdroid/matchers.py b/opsdroid/matchers.py
  --- a/opsdroid/matchers.py
  +++ b/opsdroid/matchers.py
  @@ -9,12 +9,14 @@
   _LOGGER = logging.getLogger(__name__)
   
   
  -def match_regex(regex):
  +def match_regex(regex, case_sensitive=True):
       """Return regex match decorator."""
       def matcher(func):
           """Add decorated function to skills list for regex matching."""
           opsdroid = get_opsdroid()
  -        opsdroid.skills.append({"regex": regex, "skill": func,
  +        opsdroid.skills.append({"regex": {"expression": regex,
  +                                          "case_sensitive": case_sensitive},
  +                                "skill": func,
                                   "config":
                                   opsdroid.loader.current_import_config})
           return func
  diff --git a/opsdroid/parsers/regex.py b/opsdroid/parsers/regex.py
  --- a/opsdroid/parsers/regex.py
  +++ b/opsdroid/parsers/regex.py
  @@ -15,7 +15,12 @@
       # give a response to the user, so an error response should be given.
       for skill in opsdroid.skills:
           if "regex" in skill:
  -            regex = re.match(skill["regex"], message.text)
  +            if skill["regex"]["case_sensitive"]:
  +                regex = re.match(skill["regex"]["expression"],
  +                                 message.text)
  +            else:
  +                regex = re.match(skill["regex"]["expression"],
  +                                 message.text, re.IGNORECASE)
               if regex:
                   message.regex = regex
                   try:
  @@ -28,4 +33,4 @@
                       _LOGGER.exception("Exception when parsing '" +
                                         message.text +
                                         "' against skill '" +
  -                                      skill["regex"] + "'")
  +                                      skill["regex"]["expression"] + "'")
  
verification_info: {"golden_diff": "diff --git a/opsdroid/matchers.py b/opsdroid/matchers.py\n--- a/opsdroid/matchers.py\n+++ b/opsdroid/matchers.py\n@@ -9,12 +9,14 @@\n _LOGGER = logging.getLogger(__name__)\n \n \n-def match_regex(regex):\n+def match_regex(regex, case_sensitive=True):\n     \"\"\"Return regex match decorator.\"\"\"\n     def matcher(func):\n         \"\"\"Add decorated function to skills list for regex matching.\"\"\"\n         opsdroid = get_opsdroid()\n-        opsdroid.skills.append({\"regex\": regex, \"skill\": func,\n+        opsdroid.skills.append({\"regex\": {\"expression\": regex,\n+                                          \"case_sensitive\": case_sensitive},\n+                                \"skill\": func,\n                                 \"config\":\n                                 opsdroid.loader.current_import_config})\n         return func\ndiff --git a/opsdroid/parsers/regex.py b/opsdroid/parsers/regex.py\n--- a/opsdroid/parsers/regex.py\n+++ b/opsdroid/parsers/regex.py\n@@ -15,7 +15,12 @@\n     # give a response to the user, so an error response should be given.\n     for skill in opsdroid.skills:\n         if \"regex\" in skill:\n-            regex = re.match(skill[\"regex\"], message.text)\n+            if skill[\"regex\"][\"case_sensitive\"]:\n+                regex = re.match(skill[\"regex\"][\"expression\"],\n+                                 message.text)\n+            else:\n+                regex = re.match(skill[\"regex\"][\"expression\"],\n+                                 message.text, re.IGNORECASE)\n             if regex:\n                 message.regex = regex\n                 try:\n@@ -28,4 +33,4 @@\n                     _LOGGER.exception(\"Exception when parsing '\" +\n                                       message.text +\n                                       \"' against skill '\" +\n-                                      skill[\"regex\"] + \"'\")\n+                                      skill[\"regex\"][\"expression\"] + \"'\")\n", "issue": "Add case-insensitive kwarg to the regex matcher\nIt would be nice to specify case insensitive matching in the regex matcher.\r\n\r\ne.g\r\n```python\r\n@match_regex(r'myregex', case_sensitive=False)\r\nasync def myskill(opsdroid, config, message):\r\n    pass\r\n```\n", "before_files": [{"content": "\"\"\"A helper function for parsing and executing regex skills.\"\"\"\n\nimport logging\nimport re\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\nasync def parse_regex(opsdroid, message):\n    \"\"\"Parse a message against all regex 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    for skill in opsdroid.skills:\n        if \"regex\" in skill:\n            regex = re.match(skill[\"regex\"], message.text)\n            if regex:\n                message.regex = regex\n                try:\n                    await skill[\"skill\"](opsdroid, skill[\"config\"], 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                                      skill[\"regex\"] + \"'\")\n", "path": "opsdroid/parsers/regex.py"}, {"content": "\"\"\"Decorator functions to use when creating skill modules.\"\"\"\n\nimport logging\n\nfrom opsdroid.helper import get_opsdroid\nfrom opsdroid.web import Web\n\n\n_LOGGER = logging.getLogger(__name__)\n\n\ndef match_regex(regex):\n    \"\"\"Return regex match decorator.\"\"\"\n    def matcher(func):\n        \"\"\"Add decorated function to skills list for regex matching.\"\"\"\n        opsdroid = get_opsdroid()\n        opsdroid.skills.append({\"regex\": regex, \"skill\": func,\n                                \"config\":\n                                opsdroid.loader.current_import_config})\n        return func\n    return matcher\n\n\ndef match_apiai_action(action):\n    \"\"\"Return apiai action match decorator.\"\"\"\n    def matcher(func):\n        \"\"\"Add decorated function to skills list for apiai matching.\"\"\"\n        opsdroid = get_opsdroid()\n        opsdroid.skills.append({\"apiai_action\": action, \"skill\": func,\n                                \"config\":\n                                opsdroid.loader.current_import_config})\n        return func\n    return matcher\n\n\ndef match_apiai_intent(intent):\n    \"\"\"Return apiai intent match decorator.\"\"\"\n    def matcher(func):\n        \"\"\"Add decorated function to skills list for apiai matching.\"\"\"\n        opsdroid = get_opsdroid()\n        opsdroid.skills.append({\"apiai_intent\": intent, \"skill\": func,\n                                \"config\":\n                                opsdroid.loader.current_import_config})\n        return func\n    return matcher\n\n\ndef match_crontab(crontab, timezone=None):\n    \"\"\"Return crontab match decorator.\"\"\"\n    def matcher(func):\n        \"\"\"Add decorated function to skills list for crontab matching.\"\"\"\n        opsdroid = get_opsdroid()\n        config = opsdroid.loader.current_import_config\n        opsdroid.skills.append({\"crontab\": crontab, \"skill\": func,\n                                \"config\": config, \"timezone\": timezone})\n        return func\n    return matcher\n\n\ndef match_webhook(webhook):\n    \"\"\"Return webhook match decorator.\"\"\"\n    def matcher(func):\n        \"\"\"Add decorated function to skills list for webhook matching.\"\"\"\n        opsdroid = get_opsdroid()\n        config = opsdroid.loader.current_import_config\n        opsdroid.skills.append({\"webhook\": webhook, \"skill\": func,\n                                \"config\": config})\n\n        async def wrapper(req, opsdroid=opsdroid, config=config):\n            \"\"\"Wrap up the aiohttp handler.\"\"\"\n            _LOGGER.info(\"Running skill %s via webhook\", webhook)\n            opsdroid.stats[\"webhooks_called\"] = \\\n                opsdroid.stats[\"webhooks_called\"] + 1\n            await func(opsdroid, config, req)\n            return Web.build_response(200, {\"called_skill\": webhook})\n\n        opsdroid.web_server.web_app.router.add_post(\n            \"/skill/{}/{}\".format(config[\"name\"], webhook), wrapper)\n        opsdroid.web_server.web_app.router.add_post(\n            \"/skill/{}/{}/\".format(config[\"name\"], webhook), wrapper)\n\n        return func\n    return matcher\n", "path": "opsdroid/matchers.py"}]}