lemoncurry/webmention/views.py

67 lines
2.1 KiB
Python

from django.http import HttpResponse
from django.urls import resolve, reverse, Resolver404
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_POST
from entries.models import Entry
from lemoncurry.utils import bad_req
from urllib.parse import urljoin, urlparse
from .models import State, Webmention
@csrf_exempt
@require_POST
def accept(request):
if 'source' not in request.POST:
return bad_req('missing source url')
source_url = request.POST['source']
if 'target' not in request.POST:
return bad_req('missing target url')
target_url = request.POST['target']
source = urlparse(source_url)
target = urlparse(target_url)
if source.scheme not in ('http', 'https'):
return bad_req('unsupported source scheme')
if target.scheme not in ('http', 'https'):
return bad_req('unsupported target scheme')
if target.netloc != request.site.domain:
return bad_req('target not on this site')
origin = 'https://' + target.netloc
try:
match = resolve(target.path)
except Resolver404:
return bad_req('target not found')
if match.view_name != 'entries:entry':
return bad_req('target does not accept webmentions')
try:
entry = Entry.objects.get(pk=match.kwargs['id'])
except Entry.DoesNotExist:
return bad_req('target not found')
try:
mention = Webmention.objects.get(source=source_url, target=target_url)
except Webmention.DoesNotExist:
mention = Webmention()
mention.source = source_url
mention.target = target_url
mention.entry = entry
mention.state = State.PENDING
mention.save()
status_url = reverse('webmention:status', kwargs={'id': mention.id})
res = HttpResponse(status=201)
res['Location'] = urljoin(origin, status_url)
return res
@require_GET
def status(request, mention_id):
mention = get_object_or_404(Webmention.objects, pk=mention_id)
return HttpResponse(mention.get_state_display())