mirror of
https://code.eliotberriot.com/funkwhale/funkwhale.git
synced 2025-10-03 23:49:16 +02:00
Resolve "Per-user libraries" (use !368 instead)
This commit is contained in:
parent
b0ca181016
commit
2ea21994ee
144 changed files with 6749 additions and 5347 deletions
|
@ -1,3 +1,9 @@
|
|||
import uuid
|
||||
|
||||
from funkwhale_api.common import utils as funkwhale_utils
|
||||
|
||||
PUBLIC_ADDRESS = "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
ACTIVITY_TYPES = [
|
||||
"Accept",
|
||||
"Add",
|
||||
|
@ -58,4 +64,145 @@ def accept_follow(follow):
|
|||
from . import serializers
|
||||
|
||||
serializer = serializers.AcceptFollowSerializer(follow)
|
||||
return deliver(serializer.data, to=[follow.actor.url], on_behalf_of=follow.target)
|
||||
return deliver(serializer.data, to=[follow.actor.fid], on_behalf_of=follow.target)
|
||||
|
||||
|
||||
def receive(activity, on_behalf_of):
|
||||
from . import models
|
||||
from . import serializers
|
||||
from . import tasks
|
||||
|
||||
# we ensure the activity has the bare minimum structure before storing
|
||||
# it in our database
|
||||
serializer = serializers.BaseActivitySerializer(
|
||||
data=activity, context={"actor": on_behalf_of, "local_recipients": True}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
copy = serializer.save()
|
||||
# we create inbox items for further delivery
|
||||
items = [
|
||||
models.InboxItem(activity=copy, actor=r, type="to")
|
||||
for r in serializer.validated_data["recipients"]["to"]
|
||||
if hasattr(r, "fid")
|
||||
]
|
||||
items += [
|
||||
models.InboxItem(activity=copy, actor=r, type="cc")
|
||||
for r in serializer.validated_data["recipients"]["cc"]
|
||||
if hasattr(r, "fid")
|
||||
]
|
||||
models.InboxItem.objects.bulk_create(items)
|
||||
# at this point, we have the activity in database. Even if we crash, it's
|
||||
# okay, as we can retry later
|
||||
tasks.dispatch_inbox.delay(activity_id=copy.pk)
|
||||
return copy
|
||||
|
||||
|
||||
class Router:
|
||||
def __init__(self):
|
||||
self.routes = []
|
||||
|
||||
def connect(self, route, handler):
|
||||
self.routes.append((route, handler))
|
||||
|
||||
def register(self, route):
|
||||
def decorator(handler):
|
||||
self.connect(route, handler)
|
||||
return handler
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class InboxRouter(Router):
|
||||
def dispatch(self, payload, context):
|
||||
"""
|
||||
Receives an Activity payload and some context and trigger our
|
||||
business logic
|
||||
"""
|
||||
for route, handler in self.routes:
|
||||
if match_route(route, payload):
|
||||
return handler(payload, context=context)
|
||||
|
||||
|
||||
class OutboxRouter(Router):
|
||||
def dispatch(self, routing, context):
|
||||
"""
|
||||
Receives a routing payload and some business objects in the context
|
||||
and may yield data that should be persisted in the Activity model
|
||||
for further delivery.
|
||||
"""
|
||||
from . import models
|
||||
from . import tasks
|
||||
|
||||
for route, handler in self.routes:
|
||||
if match_route(route, routing):
|
||||
activities_data = []
|
||||
for e in handler(context):
|
||||
# a route can yield zero, one or more activity payloads
|
||||
if e:
|
||||
activities_data.append(e)
|
||||
|
||||
inbox_items_by_activity_uuid = {}
|
||||
prepared_activities = []
|
||||
for activity_data in activities_data:
|
||||
to = activity_data.pop("to", [])
|
||||
cc = activity_data.pop("cc", [])
|
||||
a = models.Activity(**activity_data)
|
||||
a.uuid = uuid.uuid4()
|
||||
to_items, new_to = prepare_inbox_items(to, "to")
|
||||
cc_items, new_cc = prepare_inbox_items(cc, "cc")
|
||||
if not to_items and not cc_items:
|
||||
continue
|
||||
inbox_items_by_activity_uuid[str(a.uuid)] = to_items + cc_items
|
||||
if new_to:
|
||||
a.payload["to"] = new_to
|
||||
if new_cc:
|
||||
a.payload["cc"] = new_cc
|
||||
prepared_activities.append(a)
|
||||
|
||||
activities = models.Activity.objects.bulk_create(prepared_activities)
|
||||
activities = [a for a in activities if a]
|
||||
|
||||
final_inbox_items = []
|
||||
for a in activities:
|
||||
try:
|
||||
prepared_inbox_items = inbox_items_by_activity_uuid[str(a.uuid)]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
for ii in prepared_inbox_items:
|
||||
ii.activity = a
|
||||
final_inbox_items.append(ii)
|
||||
|
||||
# create all inbox items, in bulk
|
||||
models.InboxItem.objects.bulk_create(final_inbox_items)
|
||||
|
||||
for a in activities:
|
||||
funkwhale_utils.on_commit(
|
||||
tasks.dispatch_outbox.delay, activity_id=a.pk
|
||||
)
|
||||
return activities
|
||||
|
||||
|
||||
def match_route(route, payload):
|
||||
for key, value in route.items():
|
||||
if payload.get(key) != value:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def prepare_inbox_items(recipient_list, type):
|
||||
from . import models
|
||||
|
||||
items = []
|
||||
new_list = [] # we return a list of actors url instead
|
||||
|
||||
for r in recipient_list:
|
||||
if r != PUBLIC_ADDRESS:
|
||||
item = models.InboxItem(actor=r, type=type)
|
||||
items.append(item)
|
||||
new_list.append(r.fid)
|
||||
else:
|
||||
new_list.append(r)
|
||||
|
||||
return items, new_list
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue