kopia lustrzana https://github.com/dukethis/activitypub-example
Implement outbox: accept Create activities.
Post /@<username>/outbox For now delivery is not implemented.master
rodzic
8c11541674
commit
fd8b0d20ca
|
@ -1,2 +1,3 @@
|
|||
from .objects import *
|
||||
from .verbs import *
|
||||
|
||||
|
|
|
@ -57,6 +57,11 @@ class Object(object):
|
|||
def to_activitystream(self):
|
||||
return self
|
||||
|
||||
class Note(Object):
|
||||
|
||||
attributes = Object.attributes + ["content", "actor"]
|
||||
type = "Note"
|
||||
|
||||
class Actor(Object):
|
||||
|
||||
attributes = Object.attributes + [
|
||||
|
@ -87,6 +92,7 @@ ALLOWED_TYPES = {
|
|||
"Object": Object,
|
||||
"Actor": Actor,
|
||||
"Person": Person,
|
||||
"Note": Note,
|
||||
}
|
||||
|
||||
def as_activitystream(obj):
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
from activitypub.activities.objects import ALLOWED_TYPES, Object, Actor
|
||||
from activitypub.activities.objects import Person, Note
|
||||
from activitypub.activities import errors
|
||||
|
||||
from copy import copy
|
||||
|
||||
class Activity(Object):
|
||||
|
||||
attributes = Object.attributes + ["actor", "object"]
|
||||
type = "Activity"
|
||||
|
||||
def get_audience(self):
|
||||
audience = []
|
||||
for attr in ["to", "bto", "cc", "bcc", "audience"]:
|
||||
value = getattr(self, attr, None)
|
||||
if not value:
|
||||
continue
|
||||
|
||||
if isinstance(value, str):
|
||||
value = [value]
|
||||
audience += value
|
||||
return set(audience)
|
||||
|
||||
def strip_audience(self):
|
||||
new = copy(self)
|
||||
if getattr(new, "bto", None):
|
||||
delattr(new, "bto")
|
||||
if getattr(new, "bcc", None):
|
||||
delattr(new, "bcc")
|
||||
return new
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
class Create(Activity):
|
||||
|
||||
type = "Create"
|
||||
|
||||
def validate(self):
|
||||
msg = None
|
||||
if not getattr(self, "actor", None):
|
||||
msg = "Invalid Create activity, actor is missing"
|
||||
elif not getattr(self, "object", None):
|
||||
msg = "Invalid Create activity, object is missing"
|
||||
elif not isinstance(self.actor, Actor) and not isinstance(self.actor, str):
|
||||
msg = "Invalid actor type, must be an Actor or a string"
|
||||
elif not isinstance(self.object, Object):
|
||||
msg = "Invalid object type, must be an Object"
|
||||
|
||||
if msg:
|
||||
raise errors.ASValidateException(msg)
|
||||
|
||||
ALLOWED_TYPES.update({
|
||||
"Activity": Activity,
|
||||
"Create": Create,
|
||||
})
|
||||
|
|
@ -54,6 +54,29 @@ class Person(Model):
|
|||
})
|
||||
return json
|
||||
|
||||
class Note(Model):
|
||||
ap_id = TextField(null=True)
|
||||
remote = BooleanField(default=False)
|
||||
|
||||
person = ForeignKey(Person, related_name='notes')
|
||||
content = CharField(max_length=500)
|
||||
likes = ManyToManyField(Person, related_name='liked')
|
||||
|
||||
@property
|
||||
def uris(self):
|
||||
if self.remote:
|
||||
ap_id = self.ap_id
|
||||
else:
|
||||
ap_id = uri("note", self.person.username, self.id)
|
||||
return URIs(id=ap_id)
|
||||
|
||||
def to_activitystream(self):
|
||||
return {
|
||||
"id": self.uris.id,
|
||||
"content": self.content,
|
||||
"actor": self.person.uris.id,
|
||||
}
|
||||
|
||||
@receiver(post_save, sender=Person)
|
||||
@receiver(post_save, sender=Note)
|
||||
def save_ap_id(sender, instance, created, **kwargs):
|
||||
|
|
|
@ -5,6 +5,7 @@ from activitypub.views import person, note, new_note, notes, inbox, outbox
|
|||
from activitypub.views import followers, noop
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^@(\w+)/outbox', outbox, name="outbox"),
|
||||
url(r'^@([^/]+)$', person, name="person"),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
||||
|
|
|
@ -15,3 +15,40 @@ def person(request, username):
|
|||
person = get_object_or_404(Person, username=username)
|
||||
return JsonResponse(activities.Person(person).to_json(context=True))
|
||||
|
||||
@csrf_exempt
|
||||
def outbox(request, username):
|
||||
if request.method != "POST":
|
||||
return HttpResponseNotAllowed(["POST"])
|
||||
|
||||
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
|
||||
activity = activities.Create(
|
||||
to=person.uris.followers,
|
||||
actor=person.uris.id,
|
||||
object=obj
|
||||
)
|
||||
|
||||
activity.validate()
|
||||
|
||||
if activity.type == "Create":
|
||||
if activity.object.type != "Note":
|
||||
raise Exception("Sorry, you can only create Notes objects")
|
||||
|
||||
content = activity.object.content
|
||||
note = Note(content=content, person=person)
|
||||
note.save()
|
||||
|
||||
# TODO: check for actor being the right actor object
|
||||
activity.object.id = note.uris.id
|
||||
deliver(activity)
|
||||
return HttpResponseRedirect(note.uris.id)
|
||||
|
||||
raise Exception("Invalid Request")
|
||||
|
||||
def deliver(activity):
|
||||
pass
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue