prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Support rescheduling of offensive messages
  When a message trips the filter on the bot it is removed after a period of time. During this period it is a record in the database.
  
  When this deletion date is reached the bot will attempt to remove the message from Discord and remove the record from the offensive message table. We currently handle for the message being not found (deleted) but if another error occurs resulting in the message not being deleted we still continue to delete the database record, causing the message to be left around.
  
  We should allow the bot to perform a PATCH request to the deleted message endpoint to update the delete time and reschedule if something has failed (for example, a hiccup on Discord's end).
  
  However, we must also bear in mind that permanent rescheduling could potentially leave lingering records in our database if a case is discovered where a message which cannot be deleted is rescheduled repetitively.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pydis_site/apps/api/viewsets/bot/offensive_message.py`
  Content:
  ```
  1 from rest_framework.mixins import (
  2     CreateModelMixin,
  3     DestroyModelMixin,
  4     ListModelMixin
  5 )
  6 from rest_framework.viewsets import GenericViewSet
  7 
  8 from pydis_site.apps.api.models.bot.offensive_message import OffensiveMessage
  9 from pydis_site.apps.api.serializers import OffensiveMessageSerializer
  10 
  11 
  12 class OffensiveMessageViewSet(
  13     CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet
  14 ):
  15     """
  16     View providing CRUD access to offensive messages.
  17 
  18     ## Routes
  19     ### GET /bot/offensive-messages
  20     Returns all offensive messages in the database.
  21 
  22     #### Response format
  23     >>> [
  24     ...     {
  25     ...         'id': '631953598091100200',
  26     ...         'channel_id': '291284109232308226',
  27     ...         'delete_date': '2019-11-01T21:51:15.545000Z'
  28     ...     },
  29     ...     ...
  30     ... ]
  31 
  32     #### Status codes
  33     - 200: returned on success
  34 
  35     ### POST /bot/offensive-messages
  36     Create a new offensive message object.
  37 
  38     #### Request body
  39     >>> {
  40     ...     'id': int,
  41     ...     'channel_id': int,
  42     ...     'delete_date': datetime.datetime  # ISO-8601-formatted date
  43     ... }
  44 
  45     #### Status codes
  46     - 201: returned on success
  47     - 400: if the body format is invalid
  48 
  49     ### DELETE /bot/offensive-messages/<id:int>
  50     Delete the offensive message object with the given `id`.
  51 
  52     #### Status codes
  53     - 204: returned on success
  54     - 404: if a offensive message object with the given `id` does not exist
  55 
  56     ## Authentication
  57     Requires an API token.
  58     """
  59 
  60     serializer_class = OffensiveMessageSerializer
  61     queryset = OffensiveMessage.objects.all()
  62
  ```
  --- 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/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py
  --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py
  +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py
  @@ -1,6 +1,7 @@
   from rest_framework.mixins import (
       CreateModelMixin,
       DestroyModelMixin,
  +    UpdateModelMixin,
       ListModelMixin
   )
   from rest_framework.viewsets import GenericViewSet
  @@ -10,7 +11,7 @@
   
   
   class OffensiveMessageViewSet(
  -    CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet
  +    CreateModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet
   ):
       """
       View providing CRUD access to offensive messages.
  @@ -46,6 +47,16 @@
       - 201: returned on success
       - 400: if the body format is invalid
   
  +    ### PATCH /bot/offensive-messages/<id:int>
  +    Perform a partial update of the offensive message with the given `id`.
  +    Intended to allow rescheduling the deletion date in case the bot's attempt
  +    to delete the message failed due to another error than the message already
  +    being deleted.
  +
  +    #### Status codes
  +    - 200: returned on success
  +    - 404: if a offensive message object with the given `id` does not exist
  +
       ### DELETE /bot/offensive-messages/<id:int>
       Delete the offensive message object with the given `id`.
  
verification_info: {"golden_diff": "diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py\n--- a/pydis_site/apps/api/viewsets/bot/offensive_message.py\n+++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py\n@@ -1,6 +1,7 @@\n from rest_framework.mixins import (\n     CreateModelMixin,\n     DestroyModelMixin,\n+    UpdateModelMixin,\n     ListModelMixin\n )\n from rest_framework.viewsets import GenericViewSet\n@@ -10,7 +11,7 @@\n \n \n class OffensiveMessageViewSet(\n-    CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet\n+    CreateModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet\n ):\n     \"\"\"\n     View providing CRUD access to offensive messages.\n@@ -46,6 +47,16 @@\n     - 201: returned on success\n     - 400: if the body format is invalid\n \n+    ### PATCH /bot/offensive-messages/<id:int>\n+    Perform a partial update of the offensive message with the given `id`.\n+    Intended to allow rescheduling the deletion date in case the bot's attempt\n+    to delete the message failed due to another error than the message already\n+    being deleted.\n+\n+    #### Status codes\n+    - 200: returned on success\n+    - 404: if a offensive message object with the given `id` does not exist\n+\n     ### DELETE /bot/offensive-messages/<id:int>\n     Delete the offensive message object with the given `id`.\n", "issue": "Support rescheduling of offensive messages\nWhen a message trips the filter on the bot it is removed after a period of time. During this period it is a record in the database.\r\n\r\nWhen this deletion date is reached the bot will attempt to remove the message from Discord and remove the record from the offensive message table. We currently handle for the message being not found (deleted) but if another error occurs resulting in the message not being deleted we still continue to delete the database record, causing the message to be left around.\r\n\r\nWe should allow the bot to perform a PATCH request to the deleted message endpoint to update the delete time and reschedule if something has failed (for example, a hiccup on Discord's end).\r\n\r\nHowever, we must also bear in mind that permanent rescheduling could potentially leave lingering records in our database if a case is discovered where a message which cannot be deleted is rescheduled repetitively.\n", "before_files": [{"content": "from rest_framework.mixins import (\n    CreateModelMixin,\n    DestroyModelMixin,\n    ListModelMixin\n)\nfrom rest_framework.viewsets import GenericViewSet\n\nfrom pydis_site.apps.api.models.bot.offensive_message import OffensiveMessage\nfrom pydis_site.apps.api.serializers import OffensiveMessageSerializer\n\n\nclass OffensiveMessageViewSet(\n    CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet\n):\n    \"\"\"\n    View providing CRUD access to offensive messages.\n\n    ## Routes\n    ### GET /bot/offensive-messages\n    Returns all offensive messages in the database.\n\n    #### Response format\n    >>> [\n    ...     {\n    ...         'id': '631953598091100200',\n    ...         'channel_id': '291284109232308226',\n    ...         'delete_date': '2019-11-01T21:51:15.545000Z'\n    ...     },\n    ...     ...\n    ... ]\n\n    #### Status codes\n    - 200: returned on success\n\n    ### POST /bot/offensive-messages\n    Create a new offensive message object.\n\n    #### Request body\n    >>> {\n    ...     'id': int,\n    ...     'channel_id': int,\n    ...     'delete_date': datetime.datetime  # ISO-8601-formatted date\n    ... }\n\n    #### Status codes\n    - 201: returned on success\n    - 400: if the body format is invalid\n\n    ### DELETE /bot/offensive-messages/<id:int>\n    Delete the offensive message object with the given `id`.\n\n    #### Status codes\n    - 204: returned on success\n    - 404: if a offensive message object with the given `id` does not exist\n\n    ## Authentication\n    Requires an API token.\n    \"\"\"\n\n    serializer_class = OffensiveMessageSerializer\n    queryset = OffensiveMessage.objects.all()\n", "path": "pydis_site/apps/api/viewsets/bot/offensive_message.py"}], "after_files": [{"content": "from rest_framework.mixins import (\n    CreateModelMixin,\n    DestroyModelMixin,\n    UpdateModelMixin,\n    ListModelMixin\n)\nfrom rest_framework.viewsets import GenericViewSet\n\nfrom pydis_site.apps.api.models.bot.offensive_message import OffensiveMessage\nfrom pydis_site.apps.api.serializers import OffensiveMessageSerializer\n\n\nclass OffensiveMessageViewSet(\n    CreateModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet\n):\n    \"\"\"\n    View providing CRUD access to offensive messages.\n\n    ## Routes\n    ### GET /bot/offensive-messages\n    Returns all offensive messages in the database.\n\n    #### Response format\n    >>> [\n    ...     {\n    ...         'id': '631953598091100200',\n    ...         'channel_id': '291284109232308226',\n    ...         'delete_date': '2019-11-01T21:51:15.545000Z'\n    ...     },\n    ...     ...\n    ... ]\n\n    #### Status codes\n    - 200: returned on success\n\n    ### POST /bot/offensive-messages\n    Create a new offensive message object.\n\n    #### Request body\n    >>> {\n    ...     'id': int,\n    ...     'channel_id': int,\n    ...     'delete_date': datetime.datetime  # ISO-8601-formatted date\n    ... }\n\n    #### Status codes\n    - 201: returned on success\n    - 400: if the body format is invalid\n\n    ### PATCH /bot/offensive-messages/<id:int>\n    Perform a partial update of the offensive message with the given `id`.\n    Intended to allow rescheduling the deletion date in case the bot's attempt\n    to delete the message failed due to another error than the message already\n    being deleted.\n\n    #### Status codes\n    - 200: returned on success\n    - 404: if a offensive message object with the given `id` does not exist\n\n    ### DELETE /bot/offensive-messages/<id:int>\n    Delete the offensive message object with the given `id`.\n\n    #### Status codes\n    - 204: returned on success\n    - 404: if a offensive message object with the given `id` does not exist\n\n    ## Authentication\n    Requires an API token.\n    \"\"\"\n\n    serializer_class = OffensiveMessageSerializer\n    queryset = OffensiveMessage.objects.all()\n", "path": "pydis_site/apps/api/viewsets/bot/offensive_message.py"}]}