uncia/uncia/views.py

235 lines
5.5 KiB
Python

import asyncio, json
from izzylib import DotDict, logging
from izzylib.http_server_async import View
from . import __version__
from .config import config
from .database import db
from .processing import ProcessData
### Frontend
class UnciaHome(View):
__path__ = '/'
async def get(self, request, response):
with db.session as s:
instances = s.get.instance_list()
response.set_template('page/home.haml', {'instances': instances})
class UnciaAbout(View):
__path__ = '/about'
async def get(self, request, response):
response.set_template('page/about.haml')
class UnciaRegister(View):
__path__ = '/register'
async def get(self, request, response, error=None, message=None, form={}):
data = {
'form': form,
'error': error,
'message': message
}
response.set_template('page/register.haml', data)
async def post(self, request, response):
return await self.get(request, response, form=await request.form())
class UnciaLogin(View):
__path__ = '/login'
async def get(self, request, response, error=None, message=None, form={}):
data = {
'form': form,
'error': error,
'message': message
}
response.set_template('page/login.haml', data)
async def post(self, request, response):
return await self.get(request, response, form=await request.form())
class UnciaLogout(View):
__path__ = '/logout'
async def get(self, request, response):
response.set_redir('/')
class UnciaUser(View):
__path__ = '/user'
async def get(self, request, response):
response.set_template('page/user.haml')
async def post(self, request, response):
return await self.get(request, response)
class UnciaAdmin(View):
__path__ = '/admin'
async def get(self, request, response):
response.set_template('page/admin.haml')
async def post(self, request, response):
return await self.get(request, response)
### ActivityPub and AP-related endpoints
class UnciaActor(View):
__path__ = ['/actor', '/inbox']
async def get(self, request, response):
with db.session as s:
cfg = s.get.config_all()
data = {
'@context': [
'https://www.w3.org/ns/activitystreams',
{'manuallyApprovesFollowers': 'as:manuallyApprovesFollowers'},
],
'id': f'https://{config.host}/actor',
#'followers': f'https://{host}/followers',
#'following': f'https://{host}/following',
'name': cfg.name,
'summary': cfg.description,
'preferredUsername': 'relay',
'type': 'Application',
'inbox': f'https://{config.host}/inbox',
'url': f'https://{config.host}/',
'manuallyApprovesFollowers': cfg.require_approval,
'endpoints': {
'sharedInbox': f"https://{config.host}/inbox"
},
'publicKey': {
'id': f'https://{config.host}/actor#main-key',
'owner': f'https://{config.host}/actor',
'publicKeyPem': cfg.pubkey
}
}
response.set_json(data, activity=True)
async def post(self, request, response):
if not request.actor:
logging.verbose(f'Failed to fetch actor')
response.set_json({'error': 'Failed to fetch actor'})
return
processor = ProcessData(request, response, await request.json())
if processor.valid_type():
loop = asyncio.get_running_loop()
loop.create_task(processor())
else:
headers = {k: request.headers.getone(k) for k in request.headers}
logging.verbose('Message type not handled:', processor.type)
logging.debug(f'Headers: {json.dumps(headers)}')
logging.debug(f'Body: {request.text}')
#return response.json({'error': f'Message type unhandled: {processor.type}'}, status=401)
response.set_json({'message': 'UvU'})
response.status = 202
class UnciaNodeinfo(View):
__path__ = ['/nodeinfo/2.0.json', '/nodeinfo/2.0']
async def get(self, request, response):
with db.session as s:
instances = s.get.instance_list('domain')
domainbans = [row.domain for row in s.get.ban_list('domain')]
userbans = [f"{row.handle}@{row.domain}" for row in s.get.ban_list('user')]
whitelist = [row.domain for row in s.search('whitelist')]
wl_enabled = s.get.config('whitelist')
data = {
'openRegistrations': True,
'protocols': ['activitypub'],
'services': {
'inbound': [],
'outbound': []
},
'software': {
'name': 'unciarelay',
'version': f'{__version__}'
},
'usage': {
'localPosts': 0,
'users': {
'total': 1
}
},
'version': '2.0',
'metadata': {
'require_approval': s.get.config('require_approval'),
'peers': instances,
'email': s.get.config('email'),
'federation': {
'instance_blocks': False if not s.get.config('show_domain_bans') else domainbans,
'user_blocks': False if not s.get.config('show_user_bans') else userbans,
'whitelist': whitelist if s.get.config('show_whitelist') and wl_enabled else wl_enabled
}
}
}
response.set_json(data)
class UnciaWebfinger(View):
__path__ = '/.well-known/webfinger'
async def get(self, request, response):
resource = request.query.get('resource')
if resource != f'acct:relay@{config.host}':
response.status = 404
return
response.set_json({
'subject': f'acct:relay@{config.host}',
'aliases': [
f'https://{config.host}/actor'
],
'links': [
{
'rel': 'self',
'type': 'application/activity+json',
'href': f'https://{config.host}/actor'
}
]
})
class UnciaWellknownNodeinfo(View):
__path__ = '/.well-known/nodeinfo'
async def get(self, request, response):
response.set_json({
'links': [
{
'rel': 'http://nodeinfo.diaspora.software/ns/schema/2.0',
'href': f'https://{config.host}/nodeinfo/2.0.json'
}
]
})