kopia lustrzana https://github.com/dukethis/activitypub-example
Store activity sent and received as OrderCollections
GET /@<username>/outbox GET /@<username>/outbox/<activity_id> GET /@<username>/inboxmaster
rodzic
ef46fd4bb9
commit
be1fcfd88e
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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))
|
||||
|
|
Ładowanie…
Reference in New Issue