202 lines
5.5 KiB
Python
202 lines
5.5 KiB
Python
import asyncio
|
|
|
|
from aputils import Attachment, Message, ObjectType
|
|
from basgi import HttpError, Request, Response, router
|
|
|
|
from ..processors import process_message
|
|
|
|
|
|
def ensure_signed(request: Request) -> None:
|
|
if request.state.signature is None:
|
|
raise HttpError(400, "Missing 'signature' header")
|
|
|
|
|
|
@router.get("BarksharkSocial", "/actor")
|
|
async def handle_instance_actor_get(request: Request) -> Response:
|
|
config = request.app.state.config
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user(config.host, config.host)) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
instance = user.get_instance(s)
|
|
|
|
actor_data = {
|
|
"id": user.actor,
|
|
"inbox": user.inbox,
|
|
"outbox": f"{user.actor}/outbox",
|
|
"preferred_username": user.username,
|
|
"url": user.page_url,
|
|
"manually_approves_followers": user.locked,
|
|
"published": user.created,
|
|
"endpoints": {
|
|
"sharedInbox": instance.shared_inbox
|
|
},
|
|
"public_key": {
|
|
"id": f"{user.actor}#main-key",
|
|
"owner": user.actor,
|
|
"publicKeyPem": user.public_key
|
|
}
|
|
}
|
|
|
|
data = Message.new(ObjectType.APPLICATION, actor_data, [
|
|
"https://w3id.org/security/v1",
|
|
{
|
|
"toot": "http://joinmastodon.org/ns#",
|
|
"schema": "http://schema.org#",
|
|
"PropertyValue": "schema:PropertyValue",
|
|
"value": "schema:value",
|
|
"publicKeyBase64": "toot:publicKeyBase64",
|
|
"messageType": "toot:messageType",
|
|
"suspended": "toot:suspended"
|
|
}
|
|
])
|
|
|
|
return Response.new_activity(200, data)
|
|
|
|
|
|
@router.post("BarksharkSocial", "/inbox")
|
|
async def handle_instance_actor_post(request: Request) -> Response:
|
|
ensure_signed(request)
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user(request.app.state.config.host)) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
message = Message.parse(await request.body())
|
|
asyncio.create_task(process_message(request, message, user))
|
|
return Response(200, "uvu")
|
|
|
|
|
|
@router.get("BarksharkSocial", "/relay")
|
|
async def handle_relay_get(request: Request) -> Response:
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user("relay")) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
data = Message.new_actor(
|
|
ObjectType.APPLICATION,
|
|
user.username,
|
|
user.actor,
|
|
user.public_key,
|
|
user.inbox,
|
|
published = user.created.isoformat()
|
|
)
|
|
|
|
del data["outbox"]
|
|
return Response.new_activity(200, data)
|
|
|
|
|
|
@router.post("BarksharkSocial", "/relay")
|
|
async def handle_relay_post(request: Request) -> Response:
|
|
ensure_signed(request)
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user("relay")) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
message = Message.parse(await request.body())
|
|
asyncio.create_task(process_message(request, message, user))
|
|
return Response(200, "uvu")
|
|
|
|
|
|
@router.get("BarksharkSocial", "/user/{username}")
|
|
async def handle_actor(request: Request) -> Response:
|
|
ensure_signed(request)
|
|
|
|
config = request.app.state.config
|
|
username = request.params["username"]
|
|
|
|
if username in {config.host, "relay"}:
|
|
raise HttpError(400, "Invalid user")
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user(username, None)) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
instance = user.get_instance(s)
|
|
|
|
data = {
|
|
"@context": [
|
|
"https://www.w3.org/ns/activitystreams",
|
|
"https://w3id.org/security/v1",
|
|
{
|
|
"toot": "http://joinmastodon.org/ns#",
|
|
"schema": "http://schema.org#",
|
|
"PropertyValue": "schema:PropertyValue",
|
|
"value": "schema:value",
|
|
"publicKeyBase64": "toot:publicKeyBase64",
|
|
"messageType": "toot:messageType",
|
|
"suspended": "toot:suspended"
|
|
}
|
|
],
|
|
"type": ObjectType.PERSON if not user.is_bot else ObjectType.SERVICE,
|
|
"id": user.actor,
|
|
"name": user.display_name,
|
|
"summary": user.bio,
|
|
"url": user.page_url,
|
|
"inbox": user.inbox,
|
|
"outbox": f"{user.actor}/outbox",
|
|
"preferredUsername": user.username,
|
|
"manuallyApprovesFollowers": user.locked,
|
|
"discoverable": False,
|
|
"indexable": False,
|
|
"published": user.created.to_string(),
|
|
"attachment": [],
|
|
"endpoints": {
|
|
"sharedInbox": instance.shared_inbox
|
|
},
|
|
"publicKey": {
|
|
"id": f"{user.actor}#main-key",
|
|
"owner": user.actor,
|
|
"publicKeyPem": user.public_key
|
|
}
|
|
}
|
|
|
|
for key, value in user.info.items():
|
|
data["attachment"].append(Attachment.new_field(key, value))
|
|
|
|
return Response.new_activity(200, data)
|
|
|
|
|
|
@router.post("BarksharkSocial", "/user/{username}/inbox")
|
|
async def handle_user_actor(request: Request) -> Response:
|
|
ensure_signed(request)
|
|
|
|
config = request.app.state.config
|
|
username = request.params["username"]
|
|
|
|
if username in {config.host, "relay"}:
|
|
raise HttpError(400, "Invalid user")
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (user := s.get_user(username, config.host)) is None:
|
|
raise HttpError(404, "User not found")
|
|
|
|
message = Message.parse(await request.body())
|
|
asyncio.create_task(process_message(request, message, user))
|
|
return Response(200, "uvu")
|
|
|
|
|
|
@router.get("BarksharkSocial", "/activity/follow/{id}")
|
|
async def handle_activity_follow(request: Request) -> Response:
|
|
ensure_signed(request)
|
|
|
|
with request.app.state.database.session(False) as s:
|
|
if (follow := s.get_follow(request.params["id"])) is None:
|
|
raise HttpError(404, "Follow activity not found")
|
|
|
|
if (source := s.get_user_by_id(follow.sourceid)) is None:
|
|
raise HttpError(404, "Follow activity not found")
|
|
|
|
if (target := s.get_user_by_id(follow.targetid)) is None:
|
|
raise HttpError(404, "Follow activity not found")
|
|
|
|
data = Message.new(ObjectType.FOLLOW, {
|
|
"id": follow.followid,
|
|
"actor": source.actor,
|
|
"object": target.actor
|
|
})
|
|
|
|
return Response.new_activity(200, data)
|