sedi-relay/relay/processors.py
2022-05-06 07:04:51 +00:00

123 lines
2.9 KiB
Python

import asyncio
import logging
from uuid import uuid4
from . import app, misc
async def handle_relay(actor, data, request):
cache = app['cache'].objects
object_id = misc.distill_object_id(data)
if object_id in cache:
logging.verbose(f'already relayed {object_id} as {cache[object_id]}')
return
logging.verbose(f'Relaying post from {actor["id"]}')
activity_id = f"https://{request.host}/activities/{uuid4()}"
message = {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Announce",
"to": [f"https://{request.host}/followers"],
"actor": f"https://{request.host}/actor",
"object": object_id,
"id": activity_id
}
logging.debug(f'>> relay: {message}')
inboxes = misc.distill_inboxes(actor, object_id)
futures = [misc.request(inbox, data=message) for inbox in inboxes]
asyncio.ensure_future(asyncio.gather(*futures))
cache[object_id] = activity_id
async def handle_forward(actor, data, request):
cache = app['cache'].objects
object_id = misc.distill_object_id(data)
if object_id in cache:
logging.verbose(f'already forwarded {object_id}')
return
logging.verbose(f'Forwarding post from {actor["id"]}')
logging.debug(f'>> Relay {data}')
inboxes = misc.distill_inboxes(actor['id'], object_id)
futures = [misc.request(inbox, data=data) for inbox in inboxes]
asyncio.ensure_future(asyncio.gather(*futures))
cache[object_id] = object_id
async def handle_follow(actor, data, request):
config = app['config']
database = app['database']
inbox = misc.get_actor_inbox(actor)
if inbox not in database.inboxes:
database.add_inbox(inbox)
database.save()
asyncio.ensure_future(misc.follow_remote_actor(actor['id']))
message = {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Accept",
"to": [actor["id"]],
"actor": config.actor,
# this is wrong per litepub, but mastodon < 2.4 is not compliant with that profile.
"object": {
"type": "Follow",
"id": data["id"],
"object": config.actor,
"actor": actor["id"]
},
"id": f"https://{request.host}/activities/{uuid4()}",
}
asyncio.ensure_future(misc.request(inbox, message))
async def handle_undo(actor, data, request):
## If the activity being undone is an Announce, forward it insteead
if data['object']['type'] == 'Announce':
await handle_forward(actor, data, request)
return
elif data['object']['type'] != 'Follow':
return
database = app['database']
inbox = database.get_inbox(actor['id'])
if not inbox:
return
database.del_inbox(inbox)
database.save()
await misc.unfollow_remote_actor(actor['id'])
processors = {
'Announce': handle_relay,
'Create': handle_relay,
'Delete': handle_forward,
'Follow': handle_follow,
'Undo': handle_undo,
'Update': handle_forward,
}
async def run_processor(request, data, actor):
logging.verbose(f'New activity from actor: {actor["id"]} {data["type"]}')
return await processors[data['type']](actor, data, request)