a Django-based indieweb.org site https://00dani.me/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.5KB

  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