prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Data exposed by webhooks, not shown by /bookings
  An example is Gordon St (22) 4.01 . which is provided by webhooks when bookings change but we do not return it for bookings usually.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `backend/uclapi/roombookings/management/commands/trigger_webhooks.py`
  Content:
  ```
  1 from django.core.management.base import BaseCommand
  2 from roombookings.models import BookingA, BookingB
  3 from timetable.models import Lock
  4 from roombookings.helpers import _serialize_bookings
  5 from dashboard.models import Webhook, WebhookTriggerHistory
  6 from datetime import datetime
  7 from deepdiff import DeepDiff
  8 from django.utils import timezone
  9 from requests_futures.sessions import FuturesSession
  10 
  11 
  12 class Command(BaseCommand):
  13 
  14     help = 'Diff roombooking result sets and notify relevant webhooks'
  15 
  16     def add_arguments(self, parser):
  17         parser.add_argument(
  18             '--debug',
  19             action='store_true',
  20             dest='debug',
  21             help='Print webhook responses',
  22         )
  23 
  24     def handle(self, *args, **options):
  25         self.stdout.write("Triggering webhooks")
  26         session = FuturesSession()
  27 
  28         # currently not locked table is the old one, more recent one is locked
  29         lock = Lock.objects.all()[0]  # there is only ever one lock
  30 
  31         if not lock.a:
  32             old_booking_table = BookingA
  33             new_booking_table = BookingB
  34         else:
  35             old_booking_table = BookingB
  36             new_booking_table = BookingA
  37 
  38         now = datetime.now()
  39 
  40         old_bookings = _serialize_bookings(
  41             old_booking_table.objects.filter(
  42                 startdatetime__gt=now
  43             )
  44         )
  45         new_bookings = _serialize_bookings(
  46             new_booking_table.objects.filter(
  47                 startdatetime__gt=now
  48             )
  49         )
  50 
  51         ddiff = DeepDiff(old_bookings, new_bookings, ignore_order=True)
  52 
  53         webhooks = Webhook.objects.filter(app__deleted=False)
  54         #  assumption: list of webhooks will be longer than ddiff
  55 
  56         num_bookings_added = 0
  57         num_bookings_removed = 0
  58         if "iterable_item_added" in ddiff:
  59                 num_bookings_added = len(
  60                     ddiff["iterable_item_added"].values()
  61                 )
  62 
  63         if "iterable_item_removed" in ddiff:
  64                 num_bookings_removed = len(
  65                     ddiff["iterable_item_removed"].values()
  66                 )
  67 
  68         self.stdout.write(
  69             "{} bookings added\n{} bookings removed.".format(
  70                 num_bookings_added,
  71                 num_bookings_removed
  72             )
  73         )
  74 
  75         def webhook_map(webhook):
  76             def webhook_filter(booking):
  77                 return (
  78                     (
  79                         webhook.siteid == '' or
  80                         booking["siteid"] == webhook.siteid
  81                     ) and
  82                     (
  83                         webhook.roomid == '' or
  84                         booking["roomid"] == webhook.roomid
  85                     ) and
  86                     (
  87                         webhook.contact == '' or
  88                         # mimick SQL 'like'
  89                         webhook.contact in str(booking["contact"])
  90                     )
  91                 )
  92             output = {
  93                 "webhook_in_db": webhook,
  94                 "url": webhook.url,
  95                 "verification_secret": webhook.verification_secret
  96             }
  97             if "iterable_item_added" in ddiff:
  98                 bookings_added = list(filter(
  99                     webhook_filter, ddiff["iterable_item_added"].values()
  100                 ))
  101                 if bookings_added != []:
  102                     output["bookings_added"] = bookings_added
  103             if "iterable_item_removed" in ddiff:
  104                 bookings_removed = list(filter(
  105                     webhook_filter, ddiff["iterable_item_removed"].values()
  106                 ))
  107                 if bookings_removed != []:
  108                     output["bookings_removed"] = bookings_removed
  109 
  110             return output
  111 
  112         webhooks_to_enact = list(map(webhook_map, webhooks))
  113 
  114         unsent_requests = []
  115         for idx, webhook in enumerate(webhooks_to_enact):
  116             payload = {
  117                 "service": "roombookings",
  118                 "name": "bookings_changed",
  119                 "verification_secret": webhook["verification_secret"],
  120                 "content": {}
  121             }
  122 
  123             if "bookings_added" in webhook:
  124                 payload["content"]["bookings_added"] = (
  125                     webhook["bookings_added"]
  126                 )
  127             if "bookings_removed" in webhook:
  128                 payload["content"]["bookings_removed"] = (
  129                     webhook["bookings_removed"]
  130                 )
  131 
  132             webhooks_to_enact[idx]["payload"] = payload
  133 
  134             if payload["content"] != {} and webhook["url"] != "":
  135                 unsent_requests.append(
  136                     session.post(
  137                         webhook["url"], json=payload,
  138                         headers={
  139                             "User-Agent": "uclapi-bot/1"
  140                         }
  141                     )
  142                 )
  143         self.stdout.write(
  144             "Triggering {} webhooks.".format(len(unsent_requests))
  145         )
  146         if("debug" in options):
  147             for i in unsent_requests:
  148                 self.stdout.write(
  149                     'response status {0}'.format(i.result().status_code)
  150                 )
  151 
  152         for webhook in webhooks_to_enact:
  153             if webhook["payload"]["content"] != {}:
  154                 webhook_in_db = webhook["webhook_in_db"]
  155                 webhook_in_db.last_fired = timezone.now()
  156                 webhook_in_db.save()
  157 
  158                 new_webhook_history_entry = WebhookTriggerHistory(
  159                     webhook=webhook_in_db,
  160                     payload=webhook["payload"]
  161                 )
  162                 new_webhook_history_entry.save()
  163 
  164         self.stdout.write("Webhooks triggered.")
  165
  ```
  --- 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()
  
  ```
  
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
  @@ -7,6 +7,7 @@
   from deepdiff import DeepDiff
   from django.utils import timezone
   from requests_futures.sessions import FuturesSession
  +from django.db.models import Q
   
   
   class Command(BaseCommand):
  @@ -39,11 +40,13 @@
   
           old_bookings = _serialize_bookings(
               old_booking_table.objects.filter(
  +                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),
                   startdatetime__gt=now
               )
           )
           new_bookings = _serialize_bookings(
               new_booking_table.objects.filter(
  +                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),
                   startdatetime__gt=now
               )
           )
  
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@@ -7,6 +7,7 @@\n from deepdiff import DeepDiff\n from django.utils import timezone\n from requests_futures.sessions import FuturesSession\n+from django.db.models import Q\n \n \n class Command(BaseCommand):\n@@ -39,11 +40,13 @@\n \n         old_bookings = _serialize_bookings(\n             old_booking_table.objects.filter(\n+                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),\n                 startdatetime__gt=now\n             )\n         )\n         new_bookings = _serialize_bookings(\n             new_booking_table.objects.filter(\n+                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),\n                 startdatetime__gt=now\n             )\n         )\n", "issue": "Data exposed by webhooks, not shown by /bookings\nAn example is Gordon St (22) 4.01 . which is provided by webhooks when bookings change but we do not return it for bookings usually.\n", "before_files": [{"content": "from django.core.management.base import BaseCommand\nfrom roombookings.models import BookingA, BookingB\nfrom timetable.models import Lock\nfrom roombookings.helpers import _serialize_bookings\nfrom dashboard.models import Webhook, WebhookTriggerHistory\nfrom datetime import datetime\nfrom deepdiff import DeepDiff\nfrom django.utils import timezone\nfrom requests_futures.sessions import FuturesSession\n\n\nclass 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 not locked table is the old one, more recent one is locked\n        lock = Lock.objects.all()[0]  # there is only ever one lock\n\n        if not lock.a:\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.filter(app__deleted=False)\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\"] != {} and webhook[\"url\"] != \"\":\n                unsent_requests.append(\n                    session.post(\n                        webhook[\"url\"], json=payload,\n                        headers={\n                            \"User-Agent\": \"uclapi-bot/1\"\n                        }\n                    )\n                )\n        self.stdout.write(\n            \"Triggering {} webhooks.\".format(len(unsent_requests))\n        )\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                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"}], "after_files": [{"content": "from django.core.management.base import BaseCommand\nfrom roombookings.models import BookingA, BookingB\nfrom timetable.models import Lock\nfrom roombookings.helpers import _serialize_bookings\nfrom dashboard.models import Webhook, WebhookTriggerHistory\nfrom datetime import datetime\nfrom deepdiff import DeepDiff\nfrom django.utils import timezone\nfrom requests_futures.sessions import FuturesSession\nfrom django.db.models import Q\n\n\nclass 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 not locked table is the old one, more recent one is locked\n        lock = Lock.objects.all()[0]  # there is only ever one lock\n\n        if not lock.a:\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                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),\n                startdatetime__gt=now\n            )\n        )\n        new_bookings = _serialize_bookings(\n            new_booking_table.objects.filter(\n                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),\n                startdatetime__gt=now\n            )\n        )\n\n        ddiff = DeepDiff(old_bookings, new_bookings, ignore_order=True)\n\n        webhooks = Webhook.objects.filter(app__deleted=False)\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\"] != {} and webhook[\"url\"] != \"\":\n                unsent_requests.append(\n                    session.post(\n                        webhook[\"url\"], json=payload,\n                        headers={\n                            \"User-Agent\": \"uclapi-bot/1\"\n                        }\n                    )\n                )\n        self.stdout.write(\n            \"Triggering {} webhooks.\".format(len(unsent_requests))\n        )\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                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"}]}