prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Webhooks
  They haven't been delivered for a _long_ time now, so we finally need to dig deep and see what is going wrong. The room data is definitely up to date, however.
  
  </issue>
  <code>
  [start of backend/uclapi/roombookings/management/commands/trigger_webhooks.py]
  1 from django.core.management.base import BaseCommand
  2 from roombookings.models import Lock, BookingA, BookingB
  3 from roombookings.helpers import _serialize_bookings
  4 from dashboard.models import Webhook, WebhookTriggerHistory
  5 from datetime import datetime
  6 from deepdiff import DeepDiff
  7 import grequests
  8 from django.utils import timezone
  9 
  10 
  11 class Command(BaseCommand):
  12 
  13     help = 'Diff roombooking result sets and notify relevant webhooks'
  14 
  15     def handle(self, *args, **options):
  16         self.stdout.write("Triggering webhooks")
  17 
  18         # currently locked table is the old one, more recent one is not locked
  19         lock = Lock.objects.all()[0]  # there is only ever one lock
  20 
  21         if lock.bookingA:
  22             old_booking_table = BookingA
  23             new_booking_table = BookingB
  24         else:
  25             old_booking_table = BookingB
  26             new_booking_table = BookingA
  27 
  28         now = datetime.now()
  29 
  30         old_bookings = _serialize_bookings(
  31             old_booking_table.objects.filter(
  32                 startdatetime__gt=now
  33             )
  34         )
  35         new_bookings = _serialize_bookings(
  36             new_booking_table.objects.filter(
  37                 startdatetime__gt=now
  38             )
  39         )
  40 
  41         ddiff = DeepDiff(old_bookings, new_bookings, ignore_order=True)
  42 
  43         webhooks = Webhook.objects.all()
  44         #  assumption: list of webhooks will be longer than ddiff
  45 
  46         num_bookings_added = 0
  47         num_bookings_removed = 0
  48         if "iterable_item_added" in ddiff:
  49                 num_bookings_added = len(
  50                     ddiff["iterable_item_added"].values()
  51                 )
  52 
  53         if "iterable_item_removed" in ddiff:
  54                 num_bookings_removed = len(
  55                     ddiff["iterable_item_removed"].values()
  56                 )
  57 
  58         self.stdout.write(
  59             "{} bookings added\n{} bookings removed.".format(
  60                 num_bookings_added,
  61                 num_bookings_removed
  62             )
  63         )
  64 
  65         def webhook_map(webhook):
  66             def webhook_filter(booking):
  67                 return (
  68                     (
  69                         webhook.siteid == '' or
  70                         booking["siteid"] == webhook.siteid
  71                     ) and
  72                     (
  73                         webhook.roomid == '' or
  74                         booking["roomid"] == webhook.roomid
  75                     ) and
  76                     (
  77                         webhook.contact == '' or
  78                         # mimick SQL 'like'
  79                         webhook.contact in str(booking["contact"])
  80                     )
  81                 )
  82             output = {
  83                 "webhook_in_db": webhook,
  84                 "url": webhook.url,
  85                 "verification_secret": webhook.verification_secret
  86             }
  87             if "iterable_item_added" in ddiff:
  88                 bookings_added = list(filter(
  89                     webhook_filter, ddiff["iterable_item_added"].values()
  90                 ))
  91                 if bookings_added != []:
  92                     output["bookings_added"] = bookings_added
  93             if "iterable_item_removed" in ddiff:
  94                 bookings_removed = list(filter(
  95                     webhook_filter, ddiff["iterable_item_removed"].values()
  96                 ))
  97                 if bookings_removed != []:
  98                     output["bookings_removed"] = bookings_removed
  99 
  100             return output
  101 
  102         webhooks_to_enact = list(map(webhook_map, webhooks))
  103 
  104         unsent_requests = []
  105         for idx, webhook in enumerate(webhooks_to_enact):
  106             payload = {
  107                 "service": "roombookings",
  108                 "name": "bookings_changed",
  109                 "verification_secret": webhook["verification_secret"],
  110                 "content": {}
  111             }
  112 
  113             if "bookings_added" in webhook:
  114                 payload["content"]["bookings_added"] = (
  115                     webhook["bookings_added"]
  116                 )
  117             if "bookings_removed" in webhook:
  118                 payload["content"]["bookings_removed"] = (
  119                     webhook["bookings_removed"]
  120                 )
  121 
  122             webhooks_to_enact[idx]["payload"] = payload
  123 
  124             if payload["content"] != {}:
  125                 unsent_requests.append(
  126                     grequests.post(
  127                         webhook["url"], json=payload, headers={
  128                             "User-Agent": "uclapi-bot/1"
  129                         }
  130                     )
  131                 )
  132         self.stdout.write(
  133             "Triggering {} webhooks.".format(len(unsent_requests))
  134         )
  135         grequests.map(unsent_requests)
  136 
  137         for webhook in webhooks_to_enact:
  138             if webhook["payload"]["content"] != {}:
  139                 webhook_in_db = webhook["webhook_in_db"]
  140                 webhook_in_db.last_fired = timezone.now()
  141                 webhook_in_db.save()
  142 
  143                 new_webhook_history_entry = WebhookTriggerHistory(
  144                     webhook=webhook_in_db,
  145                     payload=webhook["payload"]
  146                 )
  147                 new_webhook_history_entry.save()
  148 
  149         self.stdout.write("Webhooks triggered.")
  150
  [end of backend/uclapi/roombookings/management/commands/trigger_webhooks.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/backend/uclapi/roombookings/management/commands/trigger_webhooks.py b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
  --- a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
  +++ b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
  @@ -4,16 +4,25 @@
   from dashboard.models import Webhook, WebhookTriggerHistory
   from datetime import datetime
   from deepdiff import DeepDiff
  -import grequests
   from django.utils import timezone
  +from requests_futures.sessions import FuturesSession
   
   
   class Command(BaseCommand):
   
       help = 'Diff roombooking result sets and notify relevant webhooks'
   
  +    def add_arguments(self, parser):
  +        parser.add_argument(
  +            '--debug',
  +            action='store_true',
  +            dest='debug',
  +            help='Print webhook responses',
  +        )
  +
       def handle(self, *args, **options):
           self.stdout.write("Triggering webhooks")
  +        session = FuturesSession()
   
           # currently locked table is the old one, more recent one is not locked
           lock = Lock.objects.all()[0]  # there is only ever one lock
  @@ -121,10 +130,11 @@
   
               webhooks_to_enact[idx]["payload"] = payload
   
  -            if payload["content"] != {}:
  +            if payload["content"] != {} and webhook["url"] != "":
                   unsent_requests.append(
  -                    grequests.post(
  -                        webhook["url"], json=payload, headers={
  +                    session.post(
  +                        webhook["url"], json=payload,
  +                        headers={
                               "User-Agent": "uclapi-bot/1"
                           }
                       )
  @@ -132,7 +142,11 @@
           self.stdout.write(
               "Triggering {} webhooks.".format(len(unsent_requests))
           )
  -        grequests.map(unsent_requests)
  +        if("debug" in options):
  +            for i in unsent_requests:
  +                self.stdout.write(
  +                    'response status {0}'.format(i.result().status_code)
  +                )
   
           for webhook in webhooks_to_enact:
               if webhook["payload"]["content"] != {}:
  
verification_info: {"golden_diff": "diff --git a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py\n--- a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py\n+++ b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py\n@@ -4,16 +4,25 @@\n from dashboard.models import Webhook, WebhookTriggerHistory\n from datetime import datetime\n from deepdiff import DeepDiff\n-import grequests\n from django.utils import timezone\n+from requests_futures.sessions import FuturesSession\n \n \n class Command(BaseCommand):\n \n     help = 'Diff roombooking result sets and notify relevant webhooks'\n \n+    def add_arguments(self, parser):\n+        parser.add_argument(\n+            '--debug',\n+            action='store_true',\n+            dest='debug',\n+            help='Print webhook responses',\n+        )\n+\n     def handle(self, *args, **options):\n         self.stdout.write(\"Triggering webhooks\")\n+        session = FuturesSession()\n \n         # currently locked table is the old one, more recent one is not locked\n         lock = Lock.objects.all()[0]  # there is only ever one lock\n@@ -121,10 +130,11 @@\n \n             webhooks_to_enact[idx][\"payload\"] = payload\n \n-            if payload[\"content\"] != {}:\n+            if payload[\"content\"] != {} and webhook[\"url\"] != \"\":\n                 unsent_requests.append(\n-                    grequests.post(\n-                        webhook[\"url\"], json=payload, headers={\n+                    session.post(\n+                        webhook[\"url\"], json=payload,\n+                        headers={\n                             \"User-Agent\": \"uclapi-bot/1\"\n                         }\n                     )\n@@ -132,7 +142,11 @@\n         self.stdout.write(\n             \"Triggering {} webhooks.\".format(len(unsent_requests))\n         )\n-        grequests.map(unsent_requests)\n+        if(\"debug\" in options):\n+            for i in unsent_requests:\n+                self.stdout.write(\n+                    'response status {0}'.format(i.result().status_code)\n+                )\n \n         for webhook in webhooks_to_enact:\n             if webhook[\"payload\"][\"content\"] != {}:\n", "issue": "Webhooks\nThey haven't been delivered for a _long_ time now, so we finally need to dig deep and see what is going wrong. The room data is definitely up to date, however.\n", "before_files": [{"content": "from django.core.management.base import BaseCommand\nfrom roombookings.models import Lock, BookingA, BookingB\nfrom roombookings.helpers import _serialize_bookings\nfrom dashboard.models import Webhook, WebhookTriggerHistory\nfrom datetime import datetime\nfrom deepdiff import DeepDiff\nimport grequests\nfrom django.utils import timezone\n\n\nclass Command(BaseCommand):\n\n    help = 'Diff roombooking result sets and notify relevant webhooks'\n\n    def handle(self, *args, **options):\n        self.stdout.write(\"Triggering webhooks\")\n\n        # currently locked table is the old one, more recent one is not locked\n        lock = Lock.objects.all()[0]  # there is only ever one lock\n\n        if lock.bookingA:\n            old_booking_table = BookingA\n            new_booking_table = BookingB\n        else:\n            old_booking_table = BookingB\n            new_booking_table = BookingA\n\n        now = datetime.now()\n\n        old_bookings = _serialize_bookings(\n            old_booking_table.objects.filter(\n                startdatetime__gt=now\n            )\n        )\n        new_bookings = _serialize_bookings(\n            new_booking_table.objects.filter(\n                startdatetime__gt=now\n            )\n        )\n\n        ddiff = DeepDiff(old_bookings, new_bookings, ignore_order=True)\n\n        webhooks = Webhook.objects.all()\n        #  assumption: list of webhooks will be longer than ddiff\n\n        num_bookings_added = 0\n        num_bookings_removed = 0\n        if \"iterable_item_added\" in ddiff:\n                num_bookings_added = len(\n                    ddiff[\"iterable_item_added\"].values()\n                )\n\n        if \"iterable_item_removed\" in ddiff:\n                num_bookings_removed = len(\n                    ddiff[\"iterable_item_removed\"].values()\n                )\n\n        self.stdout.write(\n            \"{} bookings added\\n{} bookings removed.\".format(\n                num_bookings_added,\n                num_bookings_removed\n            )\n        )\n\n        def webhook_map(webhook):\n            def webhook_filter(booking):\n                return (\n                    (\n                        webhook.siteid == '' or\n                        booking[\"siteid\"] == webhook.siteid\n                    ) and\n                    (\n                        webhook.roomid == '' or\n                        booking[\"roomid\"] == webhook.roomid\n                    ) and\n                    (\n                        webhook.contact == '' or\n                        # mimick SQL 'like'\n                        webhook.contact in str(booking[\"contact\"])\n                    )\n                )\n            output = {\n                \"webhook_in_db\": webhook,\n                \"url\": webhook.url,\n                \"verification_secret\": webhook.verification_secret\n            }\n            if \"iterable_item_added\" in ddiff:\n                bookings_added = list(filter(\n                    webhook_filter, ddiff[\"iterable_item_added\"].values()\n                ))\n                if bookings_added != []:\n                    output[\"bookings_added\"] = bookings_added\n            if \"iterable_item_removed\" in ddiff:\n                bookings_removed = list(filter(\n                    webhook_filter, ddiff[\"iterable_item_removed\"].values()\n                ))\n                if bookings_removed != []:\n                    output[\"bookings_removed\"] = bookings_removed\n\n            return output\n\n        webhooks_to_enact = list(map(webhook_map, webhooks))\n\n        unsent_requests = []\n        for idx, webhook in enumerate(webhooks_to_enact):\n            payload = {\n                \"service\": \"roombookings\",\n                \"name\": \"bookings_changed\",\n                \"verification_secret\": webhook[\"verification_secret\"],\n                \"content\": {}\n            }\n\n            if \"bookings_added\" in webhook:\n                payload[\"content\"][\"bookings_added\"] = (\n                    webhook[\"bookings_added\"]\n                )\n            if \"bookings_removed\" in webhook:\n                payload[\"content\"][\"bookings_removed\"] = (\n                    webhook[\"bookings_removed\"]\n                )\n\n            webhooks_to_enact[idx][\"payload\"] = payload\n\n            if payload[\"content\"] != {}:\n                unsent_requests.append(\n                    grequests.post(\n                        webhook[\"url\"], json=payload, headers={\n                            \"User-Agent\": \"uclapi-bot/1\"\n                        }\n                    )\n                )\n        self.stdout.write(\n            \"Triggering {} webhooks.\".format(len(unsent_requests))\n        )\n        grequests.map(unsent_requests)\n\n        for webhook in webhooks_to_enact:\n            if webhook[\"payload\"][\"content\"] != {}:\n                webhook_in_db = webhook[\"webhook_in_db\"]\n                webhook_in_db.last_fired = timezone.now()\n                webhook_in_db.save()\n\n                new_webhook_history_entry = WebhookTriggerHistory(\n                    webhook=webhook_in_db,\n                    payload=webhook[\"payload\"]\n                )\n                new_webhook_history_entry.save()\n\n        self.stdout.write(\"Webhooks triggered.\")\n", "path": "backend/uclapi/roombookings/management/commands/trigger_webhooks.py"}]}