import logging
import subprocess
from aiohttp.web import HTTPUnauthorized, Response, json_response
from . import __version__
from .application import app
from .http_debug import STATS
from .misc import request
from .processors import run_processor
try:
commit_label = subprocess.check_output(["git", "rev-parse", "HEAD"]).strip().decode('ascii')
except:
commit_label = '???'
async def home(request):
targets = '
'.join(app['database'].hostnames)
text = """
ActivityPub Relay at {host}
This is an Activity Relay for fediverse instances.
{note}
You may subscribe to this relay with the address: https://{host}/actor
To host your own relay, you may download the code at this address: https://git.pleroma.social/pleroma/relay
List of {count} registered instances:
{targets}
""".format(host=request.host, note=app['config'].note, targets=targets, count=len(app['database'].inboxes))
return Response(
status = 200,
content_type = 'text/html',
charset = 'utf-8',
text = text
)
async def actor(request):
database = app['database']
data = {
"@context": "https://www.w3.org/ns/activitystreams",
"endpoints": {
"sharedInbox": f"https://{request.host}/inbox"
},
"followers": f"https://{request.host}/followers",
"following": f"https://{request.host}/following",
"inbox": f"https://{request.host}/inbox",
"name": "ActivityRelay",
"type": "Application",
"id": f"https://{request.host}/actor",
"publicKey": {
"id": f"https://{request.host}/actor#main-key",
"owner": f"https://{request.host}/actor",
"publicKeyPem": database.pubkey
},
"summary": "ActivityRelay bot",
"preferredUsername": "relay",
"url": f"https://{request.host}/actor"
}
return json_response(data, content_type='application/activity+json')
async def inbox(request):
config = app['config']
database = app['database']
if len(config.blocked_software):
software = await fetch_nodeinfo(instance)
if software and software.lower() in config.blocked_software:
raise HTTPUnauthorized(body='relays have been blocked', content_type='text/plain')
if not request['data'] or not request['validated']:
raise HTTPUnauthorized(body='access denied', content_type='text/plain')
if request['data']['type'] != 'Follow' and request['actor']['id'] not in database.inboxes:
raise HTTPUnauthorized(body='access denied', content_type='text/plain')
elif config.whitelist_enabled and not request['data'].is_whitelisted(request['actor']['id']):
raise HTTPUnauthorized(body='access denied', content_type='text/plain')
logging.debug(f">> payload {request['data']}")
await run_processor(request, request['data'], request['actor'])
return Response(body=b'{}', content_type='application/activity+json')
async def webfinger(request):
config = app['config']
subject = request.query['resource']
if subject != f'acct:relay@{request.host}':
return json_response({'error': 'user not found'}, status=404)
data = {
'subject': subject,
'aliases': [config.actor],
'links': [
{'href': config.actor, 'rel': 'self', 'type': 'application/activity+json'},
{'href': config.actor, 'rel': 'self', 'type': 'application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"'}
]
}
return json_response(data)
async def nodeinfo_2_0(request):
data = {
# XXX - is this valid for a relay?
'openRegistrations': True,
'protocols': ['activitypub'],
'services': {
'inbound': [],
'outbound': []
},
'software': {
'name': 'activityrelay',
'version': f'{__version__} {commit_label}'
},
'usage': {
'localPosts': 0,
'users': {
'total': 1
}
},
'metadata': {
'peers': app['database'].hostnames
},
'version': '2.0'
}
return json_response(data)
async def nodeinfo_wellknown(request):
data = {
'links': [
{
'rel': 'http://nodeinfo.diaspora.software/ns/schema/2.0',
'href': f'https://{request.host}/nodeinfo/2.0.json'
}
]
}
return json_response(data)
async def stats(request):
return json_response(STATS)