2023-12-06 23:58:04 +00:00
|
|
|
import logging
|
2023-11-23 22:17:20 +00:00
|
|
|
|
2023-12-06 23:58:04 +00:00
|
|
|
from django.urls import path
|
|
|
|
from rest_framework.decorators import api_view, permission_classes, authentication_classes
|
|
|
|
from rest_framework import routers, viewsets, serializers, status
|
|
|
|
from rest_framework.response import Response
|
|
|
|
from asgiref.sync import async_to_sync
|
|
|
|
|
|
|
|
from core.settings import MAIL_DOMAIN
|
|
|
|
from mail.models import Email
|
|
|
|
from mail.protocol import send_smtp, make_reply, collect_references
|
|
|
|
from tickets.models import IssueThread
|
2023-11-23 22:17:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IssueSerializer(serializers.ModelSerializer):
|
2023-12-06 03:34:22 +00:00
|
|
|
timeline = serializers.SerializerMethodField()
|
|
|
|
|
2023-11-23 22:17:20 +00:00
|
|
|
class Meta:
|
|
|
|
model = IssueThread
|
2023-12-06 03:51:47 +00:00
|
|
|
fields = ('id', 'timeline', 'name', 'state', 'assigned_to', 'last_activity')
|
|
|
|
read_only_fields = ('id', 'timeline', 'last_activity')
|
2023-12-06 03:34:22 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_timeline(obj):
|
|
|
|
timeline = []
|
|
|
|
for comment in obj.comments.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'comment',
|
|
|
|
'id': comment.id,
|
|
|
|
'timestamp': comment.timestamp,
|
|
|
|
'comment': comment.comment,
|
|
|
|
})
|
|
|
|
for state_change in obj.state_changes.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'state',
|
|
|
|
'id': state_change.id,
|
|
|
|
'timestamp': state_change.timestamp,
|
|
|
|
'state': state_change.state,
|
|
|
|
})
|
|
|
|
for email in obj.emails.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'mail',
|
|
|
|
'id': email.id,
|
|
|
|
'timestamp': email.timestamp,
|
|
|
|
'sender': email.sender,
|
|
|
|
'recipient': email.recipient,
|
|
|
|
'subject': email.subject,
|
|
|
|
'body': email.body,
|
|
|
|
})
|
|
|
|
return sorted(timeline, key=lambda x: x['timestamp'])
|
2023-11-23 22:17:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IssueViewSet(viewsets.ModelViewSet):
|
|
|
|
serializer_class = IssueSerializer
|
|
|
|
queryset = IssueThread.objects.all()
|
|
|
|
permission_classes = []
|
|
|
|
authentication_classes = []
|
|
|
|
|
|
|
|
|
2023-12-06 23:58:04 +00:00
|
|
|
@api_view(['POST'])
|
|
|
|
@permission_classes([])
|
|
|
|
@authentication_classes([])
|
|
|
|
def reply(request, pk):
|
|
|
|
issue = IssueThread.objects.get(pk=pk)
|
|
|
|
# email = issue.reply(request.data['body']) # TODO evaluate if this is a useful abstraction
|
|
|
|
references = collect_references(issue)
|
|
|
|
most_recent = Email.objects.filter(issue_thread=issue, recipient__endswith='@' + MAIL_DOMAIN).order_by(
|
|
|
|
'-timestamp').first()
|
|
|
|
mail = Email.objects.create(
|
|
|
|
issue_thread=issue,
|
|
|
|
sender=most_recent.recipient,
|
|
|
|
recipient=most_recent.sender,
|
|
|
|
subject=f'Re: {most_recent.subject}',
|
|
|
|
body=request.data['message'],
|
|
|
|
in_reply_to=most_recent.reference,
|
|
|
|
)
|
|
|
|
log = logging.getLogger('mail.log')
|
|
|
|
async_to_sync(send_smtp)(make_reply(mail, references), log)
|
|
|
|
|
|
|
|
return Response({'status': 'ok'}, status=status.HTTP_201_CREATED)
|
|
|
|
|
|
|
|
|
2023-11-23 22:17:20 +00:00
|
|
|
router = routers.SimpleRouter()
|
|
|
|
router.register(r'tickets', IssueViewSet, basename='issues')
|
|
|
|
|
2023-12-06 23:58:04 +00:00
|
|
|
urlpatterns = router.urls + [
|
|
|
|
path('tickets/<int:pk>/reply/', reply, name='reply'),
|
|
|
|
]
|