126 lines
2.9 KiB
Python
126 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, 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):
|
|
if data['type'] not in processors:
|
|
return
|
|
|
|
logging.verbose(f'New activity from actor: {actor["id"]} {data["type"]}')
|
|
return await processors[data['type']](actor, data, request)
|