diff --git a/relay/manage.py b/relay/manage.py index 2031cb8..3b55717 100644 --- a/relay/manage.py +++ b/relay/manage.py @@ -235,18 +235,16 @@ def cli_software_ban(name, fetch_nodeinfo): return click.echo('Banned all relay software') if fetch_nodeinfo: - software = asyncio.run(misc.fetch_nodeinfo(name)) + nodeinfo = asyncio.run(misc.fetch_nodeinfo(name)) if not software: click.echo(f'Failed to fetch software name from domain: {name}') - name = software - - if config.ban_software(name): + if config.ban_software(nodeinfo.swname): app.config.save() - return click.echo(f'Banned software: {name}') + return click.echo(f'Banned software: {nodeinfo.swname}') - click.echo(f'Software already banned: {name}') + click.echo(f'Software already banned: {nodeinfo.swname}') @cli_software.command('unban') @@ -265,18 +263,16 @@ def cli_software_unban(name, fetch_nodeinfo): return click.echo('Unbanned all relay software') if fetch_nodeinfo: - software = asyncio.run(misc.fetch_nodeinfo(name)) + nodeinfo = asyncio.run(misc.fetch_nodeinfo(name)) - if not software: + if not nodeinfo: click.echo(f'Failed to fetch software name from domain: {name}') - name = software - - if app.config.unban_software(name): + if app.config.unban_software(nodeinfo.swname): app.config.save() - return click.echo(f'Unbanned software: {name}') + return click.echo(f'Unbanned software: {nodeinfo.swname}') - click.echo(f'Software wasn\'t banned: {name}') + click.echo(f'Software wasn\'t banned: {nodeinfo.swname}') diff --git a/relay/misc.py b/relay/misc.py index e5f362e..980caf3 100644 --- a/relay/misc.py +++ b/relay/misc.py @@ -141,12 +141,11 @@ async def fetch_nodeinfo(domain): nodeinfo = await request(nodeinfo_url, sign_headers=False, activity=False) - try: - return nodeinfo['software']['name'] - - except KeyError: + if not nodeinfo: return False + return Nodeinfo(nodeinfo) + async def request(uri, data=None, force=False, sign_headers=True, activity=True): ## If a get request and not force, try to use the cache first @@ -459,6 +458,12 @@ class Message(DotDict): return self.object +class Nodeinfo(DotDict): + @property + def swname(self): + return self.software.name + + class Response(AiohttpResponse): @classmethod def new(cls, body='', status=200, headers=None, ctype='text'): diff --git a/relay/processors.py b/relay/processors.py index 69f8b59..a6ced5a 100644 --- a/relay/processors.py +++ b/relay/processors.py @@ -6,7 +6,7 @@ from uuid import uuid4 from . import misc -async def handle_relay(request, actor, data, software): +async def handle_relay(request, actor, data, nodeinfo): if data.objectid in request.app.cache.objects: logging.verbose(f'already relayed {data.objectid}') return @@ -27,7 +27,7 @@ async def handle_relay(request, actor, data, software): request.app.cache.objects[data.objectid] = message.id -async def handle_forward(request, actor, data, software): +async def handle_forward(request, actor, data, nodeinfo): if data.id in request.app.cache.objects: logging.verbose(f'already forwarded {data.id}') return @@ -47,7 +47,7 @@ async def handle_forward(request, actor, data, software): request.app.cache.objects[data.id] = message.id -async def handle_follow(request, actor, data, software): +async def handle_follow(request, actor, data, nodeinfo): if not request.app.database.add_inbox(actor.shared_inbox, data.id): request.app.database.set_followid(actor.id, data.id) @@ -65,7 +65,7 @@ async def handle_follow(request, actor, data, software): # Are Akkoma and Pleroma the only two that expect a follow back? # Ignoring only Mastodon for now - if software != 'mastodon': + if nodeinfo.swname != 'mastodon': await misc.request( actor.shared_inbox, misc.Message.new_follow( @@ -75,10 +75,10 @@ async def handle_follow(request, actor, data, software): ) -async def handle_undo(request, actor, data, software): +async def handle_undo(request, actor, data, nodeinfo): ## If the object is not a Follow, forward it if data['object']['type'] != 'Follow': - return await handle_forward(request, actor, data, software) + return await handle_forward(request, actor, data, nodeinfo) if not request.app.database.del_inbox(actor.domain, data.id): return @@ -104,9 +104,9 @@ processors = { } -async def run_processor(request, actor, data, software): +async def run_processor(request, actor, data, nodeinfo): if data.type not in processors: return logging.verbose(f'New "{data.type}" from actor: {actor.id}') - return await processors[data.type](request, actor, data, software) + return await processors[data.type](request, actor, data, nodeinfo) diff --git a/relay/views.py b/relay/views.py index 8d6be5e..44a1686 100644 --- a/relay/views.py +++ b/relay/views.py @@ -100,7 +100,7 @@ async def inbox(request): return Response.new_error(400, 'failed to parse message', 'json') actor = await misc.request(signature.keyid) - software = await misc.fetch_nodeinfo(actor.domain) + nodeinfo = await misc.fetch_nodeinfo(actor.domain) ## reject if actor is empty if not actor: @@ -118,8 +118,8 @@ async def inbox(request): return Response.new_error(403, 'access denied', 'json') ## reject if software used by actor is banned - if config.is_banned_software(software): - logging.verbose(f'Rejected actor for using specific software: {software}') + if config.is_banned_software(nodeinfo.swname): + logging.verbose(f'Rejected actor for using specific software: {nodeinfo.swname}') return Response.new_error(403, 'access denied', 'json') ## reject if the signature is invalid @@ -134,7 +134,7 @@ async def inbox(request): logging.debug(f">> payload {data}") - await run_processor(request, actor, data, software) + await run_processor(request, actor, data, nodeinfo) return Response.new(status=202)