sedi-relay/relay/processors.py

134 lines
3.5 KiB
Python
Raw Normal View History

2022-05-06 07:04:51 +00:00
import asyncio
import logging
from uuid import uuid4
2022-11-07 12:54:32 +00:00
from . import misc
2022-05-06 07:04:51 +00:00
async def handle_relay(request):
if request.message.objectid in request.cache.objects:
logging.verbose(f'already relayed {request.message.objectid}')
2022-05-06 07:04:51 +00:00
return
2022-11-07 10:30:13 +00:00
message = misc.Message.new_announce(
host = request.config.host,
object = request.message.objectid
2022-11-07 10:30:13 +00:00
)
2022-05-06 07:04:51 +00:00
2022-11-20 10:50:14 +00:00
request.cache.objects[request.message.objectid] = message.id
logging.verbose(f'Relaying post from {request.message.actorid}')
2022-05-06 07:04:51 +00:00
logging.debug(f'>> relay: {message}')
inboxes = misc.distill_inboxes(request.actor, request.message.objectid)
2022-05-06 07:04:51 +00:00
2022-11-20 10:50:14 +00:00
if request.config.workers > 0:
for inbox in inboxes:
request.app.push_message(inbox, message)
else:
futures = [misc.request(inbox, data=message) for inbox in inboxes]
asyncio.ensure_future(asyncio.gather(*futures))
2022-05-06 07:04:51 +00:00
async def handle_forward(request):
if request.message.id in request.cache.objects:
logging.verbose(f'already forwarded {request.message.id}')
2022-05-06 07:04:51 +00:00
return
2022-11-07 10:30:13 +00:00
message = misc.Message.new_announce(
host = request.config.host,
object = request.message
2022-11-07 10:30:13 +00:00
)
2022-11-06 06:11:36 +00:00
2022-11-20 10:50:14 +00:00
request.cache.objects[request.message.id] = message.id
logging.verbose(f'Forwarding post from {request.actor.id}')
logging.debug(f'>> Relay {request.message}')
2022-05-06 07:04:51 +00:00
2022-11-20 10:50:14 +00:00
inboxes = misc.distill_inboxes(request.actor, request.message.objectid)
2022-05-06 07:04:51 +00:00
2022-11-20 10:50:14 +00:00
if request.config.workers > 0:
for inbox in inboxes:
request.app.push_message(inbox, message)
else:
futures = [misc.request(inbox, data=message) for inbox in inboxes]
asyncio.ensure_future(asyncio.gather(*futures))
2022-05-06 07:04:51 +00:00
async def handle_follow(request):
nodeinfo = await misc.fetch_nodeinfo(request.actor.domain)
software = nodeinfo.swname if nodeinfo else None
2022-05-06 07:04:51 +00:00
## reject if software used by actor is banned
if request.config.is_banned_software(software):
return logging.verbose(f'Rejected follow from actor for using specific software: actor={request.actor.id}, software={software}')
request.database.add_inbox(request.actor.shared_inbox, request.message.id, software)
request.database.save()
2022-05-06 07:04:51 +00:00
2022-11-07 10:30:13 +00:00
await misc.request(
request.actor.shared_inbox,
2022-11-07 10:30:13 +00:00
misc.Message.new_response(
host = request.config.host,
actor = request.actor.id,
followid = request.message.id,
2022-11-07 10:30:13 +00:00
accept = True
)
)
# Are Akkoma and Pleroma the only two that expect a follow back?
# Ignoring only Mastodon for now
if software != 'mastodon':
2022-11-16 19:22:50 +00:00
await misc.request(
request.actor.shared_inbox,
2022-11-07 10:30:13 +00:00
misc.Message.new_follow(
host = request.config.host,
actor = request.actor.id
2022-11-07 10:30:13 +00:00
)
)
async def handle_undo(request):
2022-11-06 00:15:40 +00:00
## If the object is not a Follow, forward it
if request.message.object.type != 'Follow':
return await handle_forward(request)
2022-05-06 07:04:51 +00:00
if not request.database.del_inbox(request.actor.domain, request.message.id):
2022-05-06 07:04:51 +00:00
return
request.database.save()
2022-05-06 07:04:51 +00:00
2022-11-07 10:30:13 +00:00
message = misc.Message.new_unfollow(
host = request.config.host,
actor = request.actor.id,
follow = request.message
2022-11-07 10:30:13 +00:00
)
await misc.request(request.actor.shared_inbox, message)
2022-05-06 07:04:51 +00:00
processors = {
'Announce': handle_relay,
'Create': handle_relay,
'Delete': handle_forward,
'Follow': handle_follow,
'Undo': handle_undo,
'Update': handle_forward,
}
async def run_processor(request):
if request.message.type not in processors:
return
if request.instance and not request.instance.get('software'):
nodeinfo = await misc.fetch_nodeinfo(request.instance.domain)
if nodeinfo:
request.instance[nodeinfo] = nodeinfo.swname
request.database.save()
logging.verbose(f'New "{request.message.type}" from actor: {request.actor.id}')
return await processors[request.message.type](request)