From fb6c409a9af5b8a686e977ee2251c359071e0ec3 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Sun, 6 Nov 2022 21:30:07 -0700 Subject: Rework task system and fetching. I can taste how close follow is to working. --- users/tasks/__init__.py | 0 users/tasks/follow.py | 28 ++++++++++++++++++++++++++++ users/tasks/identity.py | 11 +++++++++++ users/tasks/inbox.py | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 users/tasks/__init__.py create mode 100644 users/tasks/follow.py create mode 100644 users/tasks/identity.py create mode 100644 users/tasks/inbox.py (limited to 'users/tasks') diff --git a/users/tasks/__init__.py b/users/tasks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/users/tasks/follow.py b/users/tasks/follow.py new file mode 100644 index 0000000..3260124 --- /dev/null +++ b/users/tasks/follow.py @@ -0,0 +1,28 @@ +from core.ld import canonicalise +from core.signatures import HttpSignature +from users.models import Follow + + +async def handle_follow_request(task_handler): + """ + Request a follow from a remote server + """ + follow = await Follow.objects.select_related( + "source", "source__domain", "target" + ).aget(pk=task_handler.subject) + # Construct the request + request = canonicalise( + { + "@context": "https://www.w3.org/ns/activitystreams", + "id": follow.uri, + "type": "Follow", + "actor": follow.source.actor_uri, + "object": follow.target.actor_uri, + } + ) + # Sign it and send it + response = await HttpSignature.signed_request( + follow.target.inbox_uri, request, follow.source + ) + print(response) + print(response.content) diff --git a/users/tasks/identity.py b/users/tasks/identity.py new file mode 100644 index 0000000..f5cd214 --- /dev/null +++ b/users/tasks/identity.py @@ -0,0 +1,11 @@ +from asgiref.sync import sync_to_async + +from users.models import Identity + + +async def handle_identity_fetch(task_handler): + # Get the actor URI via webfinger + actor_uri, handle = await Identity.fetch_webfinger(task_handler.subject) + # Get or create the identity, then fetch + identity = await sync_to_async(Identity.by_actor_uri_with_create)(actor_uri) + await identity.fetch_actor() diff --git a/users/tasks/inbox.py b/users/tasks/inbox.py new file mode 100644 index 0000000..ab80648 --- /dev/null +++ b/users/tasks/inbox.py @@ -0,0 +1,36 @@ +from users.models import Follow, Identity + + +async def handle_inbox_item(task_handler): + type = task_handler.payload["type"].lower() + if type == "follow": + await inbox_follow(task_handler.payload) + elif type == "undo": + inner_type = task_handler.payload["object"]["type"].lower() + if inner_type == "follow": + await inbox_unfollow(task_handler.payload["object"]) + else: + raise ValueError("Cannot undo activity of type {inner_type}") + else: + raise ValueError("Cannot handle activity of type {inner_type}") + + +async def inbox_follow(payload): + """ + Handles an incoming follow request + """ + # TODO: Manually approved follows + source = Identity.by_actor_uri_with_create(payload["actor"]) + target = Identity.by_actor_uri(payload["object"]) + # See if this follow already exists + try: + follow = Follow.objects.get(source=source, target=target) + except Follow.DoesNotExist: + follow = Follow.objects.create(source=source, target=target, uri=payload["id"]) + # See if we need to acknowledge it + if not follow.acknowledged: + pass + + +async def inbox_unfollow(payload): + pass -- cgit v1.2.3