Store activity sent and received as OrderCollections

GET /@<username>/outbox
GET /@<username>/outbox/<activity_id>
GET /@<username>/inbox
master
Romain Gauthier 2017-08-03 02:16:52 +02:00
rodzic ef46fd4bb9
commit be1fcfd88e
3 zmienionych plików z 60 dodań i 10 usunięć

Wyświetl plik

@ -1,5 +1,7 @@
import json
from django.db.models import Model, ForeignKey, CharField, TextField, BooleanField
from django.db.models import ManyToManyField
from django.db.models import BinaryField, DateField, ManyToManyField
from django.db.models.signals import post_save
from django.dispatch import receiver
@ -79,8 +81,33 @@ class Note(Model):
"actor": self.person.uris.id,
}
class Activity(Model):
ap_id = TextField()
payload = BinaryField()
created_at = DateField(auto_now_add=True)
person = ForeignKey(Person, related_name='activities')
remote = BooleanField(default=False)
@property
def uris(self):
if self.remote:
ap_id = self.ap_id
else:
ap_id = uri("activity", self.person.username, self.id)
return URIs(id=ap_id)
def to_activitystream(self):
payload = self.payload.decode("utf-8")
data = json.loads(payload)
data.update({
"id": self.uris.id
})
return data
@receiver(post_save, sender=Person)
@receiver(post_save, sender=Note)
@receiver(post_save, sender=Activity)
def save_ap_id(sender, instance, created, **kwargs):
if created and not instance.remote:
instance.ap_id = instance.uris.id

Wyświetl plik

@ -2,7 +2,7 @@ from django.conf.urls import url
from django.contrib import admin
from activitypub.views import person, note, notes, inbox, outbox
from activitypub.views import followers, following
from activitypub.views import followers, following, activity
urlpatterns = [
url(r'^@(\w+)/notes/(\w+)', note, name="note"),
@ -10,6 +10,7 @@ urlpatterns = [
url(r'^@(\w+)/following', following, name="following"),
url(r'^@(\w+)/followers', followers, name="followers"),
url(r'^@(\w+)/inbox', inbox, name="inbox"),
url(r'^@(\w+)/outbox/(\w+)', activity, name="activity"),
url(r'^@(\w+)/outbox', outbox, name="outbox"),
url(r'^@([^/]+)$', person, name="person"),
url(r'^@([^/]+)/notes', notes),

Wyświetl plik

@ -8,7 +8,7 @@ from django.urls import reverse
from django.shortcuts import get_object_or_404, render
from django.views.decorators.csrf import csrf_exempt
from activitypub.models import Person, Note
from activitypub.models import Person, Note, Activity
from activitypub import activities
from activitypub.activities import as_activitystream
@ -25,12 +25,15 @@ def note(request, username, note_id):
@csrf_exempt
def outbox(request, username):
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])
person = get_object_or_404(Person, username=username)
if request.method == "GET":
objects = person.activities.filter(remote=False).order_by('-created_at')
collection = activities.OrderedCollection(objects)
return JsonResponse(collection.to_json(context=True))
payload = request.body.decode("utf-8")
activity = json.loads(payload, object_hook=as_activitystream)
person = get_object_or_404(Person, username=username)
if activity.type == "Note":
obj = activity
@ -52,7 +55,9 @@ def outbox(request, username):
# TODO: check for actor being the right actor object
activity.object.id = note.uris.id
activity.id = store(activity, person)
deliver(activity)
return HttpResponseRedirect(note.uris.id)
if activity.type == "Follow":
@ -64,16 +69,24 @@ def outbox(request, username):
activity.actor = person.uris.id
activity.to = followed.uris.id
activity.id = store(activity, person)
deliver(activity)
return HttpResponse() # TODO: code 202
raise Exception("Invalid Request")
def store(activity, person, remote=False):
payload = bytes(json.dumps(activity.to_json()), "utf-8")
obj = Activity(payload=payload, person=person, remote=remote)
if remote:
obj.ap_id = activity.id
obj.save()
return obj.ap_id
def deliver(activity):
audience = activity.get_audience()
activity = activity.strip_audience()
audience = get_final_audience(audience)
print("audience", audience)
for ap_id in audience:
deliver_to(ap_id, activity)
@ -125,18 +138,21 @@ def get_or_create_remote_person(ap_id):
@csrf_exempt
def inbox(request, username):
person = get_object_or_404(Person, username=username)
if request.method != "POST":
return HttpResponseNotAllowed(["POST"])
if request.method == "GET":
objects = person.activities.filter(remote=True).order_by('-created_at')
collection = activities.OrderedCollection(objects)
return JsonResponse(collection.to_json(context=True))
payload = request.body.decode("utf-8")
activity = json.loads(payload, object_hook=as_activitystream)
activity.validate()
print(activity)
if activity.type == "Create":
handle_note(activity)
elif activity.type == "Follow":
handle_follow(activity)
store(activity, person, remote=True)
return HttpResponse()
def handle_note(activity):
@ -192,3 +208,9 @@ def following(request, username):
person = get_object_or_404(Person, username=username)
following = activities.OrderedCollection(person.following.all())
return JsonResponse(following.to_json(context=True))
def activity(request, username, aid):
activity = get_object_or_404(Activity, pk=aid)
payload = activity.payload.decode("utf-8")
activity = json.loads(payload, object_hook=as_activitystream)
return JsonResponse(activity.to_json(context=True))