webhooks.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import logging
  2. import pendulum
  3. from django.views.decorators.csrf import csrf_exempt
  4. from rest_framework import status
  5. from rest_framework.decorators import api_view, permission_classes
  6. from rest_framework.permissions import IsAuthenticated
  7. from rest_framework.response import Response
  8. from scrobbles.scrobblers import (
  9. todoist_scrobble_task,
  10. todoist_scrobble_task_finish,
  11. todoist_scrobble_update_task,
  12. )
  13. from profiles.models import UserProfile
  14. logger = logging.getLogger(__name__)
  15. @csrf_exempt
  16. @permission_classes([IsAuthenticated])
  17. @api_view(["POST"])
  18. def todoist_webhook(request):
  19. post_data = request.data
  20. logger.info(
  21. "[todoist_webhook] called",
  22. extra={"post_data": post_data},
  23. )
  24. todoist_task = {}
  25. todoist_note = {}
  26. todoist_type, todoist_event = post_data.get("event_name").split(":")
  27. event_data = post_data.get("event_data", {})
  28. is_item_type = todoist_type == "item"
  29. is_note_type = todoist_type == "note"
  30. new_labels = event_data.get("labels")
  31. old_labels = (
  32. post_data.get("event_data_extra", {})
  33. .get("old_item", {})
  34. .get("labels", [])
  35. )
  36. # TODO Don't hard code status strings in here
  37. is_updated = (
  38. todoist_event in ["updated"]
  39. and "inprogress" in new_labels
  40. and "inprogress" not in old_labels
  41. )
  42. is_added = todoist_event in ["added"]
  43. if is_item_type:
  44. todoist_task = {
  45. "todoist_id": event_data.get("id"),
  46. "todoist_label_list": event_data.get("labels"),
  47. "todoist_type": todoist_type,
  48. "todoist_event": todoist_event,
  49. "updated_at": event_data.get("updated_at"),
  50. "todoist_project_id": event_data.get("project_id"),
  51. "description": event_data.get("content"),
  52. "details": event_data.get("description"),
  53. }
  54. if is_note_type:
  55. task_data = event_data.get("item", {})
  56. todoist_note = {
  57. "todoist_id": task_data.get("id"),
  58. "todoist_label_list": task_data.get("labels"),
  59. "todoist_type": todoist_type,
  60. "todoist_event": todoist_event,
  61. "updated_at": task_data.get("updated_at"),
  62. "details": task_data.get("description"),
  63. "notes": event_data.get("content"),
  64. "is_deleted": True
  65. if event_data.get("is_deleted") == "true"
  66. else False,
  67. }
  68. else:
  69. logger.info(
  70. "[todoist_webhook] ignoring wrong todoist type",
  71. extra={
  72. "todoist_type": todoist_task["todoist_type"],
  73. "todoist_event": todoist_task["todoist_event"],
  74. },
  75. )
  76. return Response({}, status=status.HTTP_304_NOT_MODIFIED)
  77. if is_item_type and new_labels == old_labels:
  78. logger.info(
  79. "[todoist_webhook] ignoring item, labels unchanged",
  80. extra={
  81. "todoist_type": todoist_task["todoist_type"],
  82. "todoist_event": todoist_task["todoist_event"],
  83. },
  84. )
  85. return Response({}, status=status.HTTP_304_NOT_MODIFIED)
  86. user_id = (
  87. UserProfile.objects.filter(todoist_user_id=post_data.get("user_id"))
  88. .first()
  89. .user_id
  90. )
  91. if todoist_task and is_updated:
  92. scrobble = todoist_scrobble_task(todoist_task, user_id)
  93. if todoist_note and is_added:
  94. scrobble = todoist_scrobble_update_task(todoist_note, user_id)
  95. if not scrobble:
  96. return Response(
  97. {"error": "No scrobble found to be updated"},
  98. status=status.HTTP_304_NOT_MODIFIED,
  99. )
  100. logger.info(
  101. "[todoist_webhook] finished",
  102. extra={"scrobble_id": scrobble.id},
  103. )
  104. return Response({"scrobble_id": scrobble.id}, status=status.HTTP_200_OK)