a Django-based indieweb.org site https://00dani.me/

create.py 2.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. from django.urls import reverse
  2. from django.http import HttpResponse
  3. from urllib.parse import urljoin
  4. from entries.jobs import ping_hub, send_mentions
  5. from entries.models import Cat, Entry
  6. from entries.kinds import Article, Note, Reply, Like, Repost
  7. from lemoncurry import utils
  8. from .. import error
  9. def form_to_mf2(request):
  10. properties = {}
  11. post = request.POST
  12. for key in post.keys():
  13. if key.endswith('[]'):
  14. key = key[:-2]
  15. if key == 'access_token':
  16. continue
  17. properties[key] = post.getlist(key) + post.getlist(key + '[]')
  18. type = []
  19. if 'h' in properties:
  20. type = ['h-' + p for p in properties['h']]
  21. del properties['h']
  22. return {'type': type, 'properties': properties}
  23. def create(request):
  24. normalise = {
  25. 'application/json': lambda r: r.json,
  26. 'application/x-www-form-urlencoded': form_to_mf2,
  27. }
  28. if 'create' not in request.token:
  29. raise error.bad_scope('create')
  30. if request.content_type not in normalise:
  31. raise error.unsupported_type(request.content_type)
  32. body = normalise[request.content_type](request)
  33. if 'type' not in body:
  34. raise error.bad_req('mf2 object type required')
  35. if body['type'] != ['h-entry']:
  36. raise error.bad_req('only h-entry supported')
  37. entry = Entry(author=request.token.user)
  38. props = body.get('properties', {})
  39. kind = Note
  40. if 'name' in props:
  41. entry.name = '\n'.join(props['name'])
  42. kind = Article
  43. if 'content' in props:
  44. entry.content = '\n'.join(
  45. c if isinstance(c, str) else c['html']
  46. for c in props['content']
  47. )
  48. if 'in-reply-to' in props:
  49. entry.in_reply_to = props['in-reply-to']
  50. kind = Reply
  51. if 'like-of' in props:
  52. entry.like_of = props['like-of']
  53. kind = Like
  54. if 'repost-of' in props:
  55. entry.repost_of = props['repost-of']
  56. kind = Repost
  57. cats = [Cat.objects.from_name(c) for c in props.get('category', [])]
  58. entry.kind = kind.id
  59. entry.save()
  60. entry.cats.set(cats)
  61. entry.save()
  62. for url in props.get('syndication', []):
  63. entry.syndications.create(url=url)
  64. base = utils.origin(request)
  65. perma = urljoin(base, entry.url)
  66. short = urljoin(base, entry.short_url)
  67. ping_hub.delay(*entry.affected_urls)
  68. send_mentions.delay(perma)
  69. res = HttpResponse(status=201)
  70. res['Location'] = perma
  71. res['Link'] = '<{}>; rel="shortlink"'.format(short)
  72. return res