foxhole/app/actor.py

83 lines
1.9 KiB
Python
Raw Normal View History

2023-03-18 14:51:36 +01:00
#!/usr/bin/env python3
2023-07-29 04:56:39 +02:00
"""Actor stuff."""
2023-03-21 07:24:57 +01:00
import typing
2023-07-29 04:56:39 +02:00
from urllib.parse import urlparse
from sqlalchemy import select
2023-03-18 14:51:36 +01:00
from loguru import logger
2023-07-29 04:56:39 +02:00
import app.activitypub as ap
2023-03-21 07:24:57 +01:00
from app import models
2023-07-29 04:56:39 +02:00
from app.database import AsyncSession
2023-03-21 07:24:57 +01:00
if typing.TYPE_CHECKING:
from app.models import Actor as ActorModel
2023-03-18 14:51:36 +01:00
async def fetch_actor(
2023-07-29 14:49:01 +02:00
db_session: AsyncSession,
actor_id: str,
2023-03-21 07:24:57 +01:00
) -> "ActorModel":
2023-07-29 04:56:39 +02:00
"""Fetch actor on db, if not exist will be grabed and stored
in db."""
2023-03-18 14:51:36 +01:00
exist_actor = (
await db_session.scalars(
2023-03-21 07:24:57 +01:00
select(models.Actor).where(
models.Actor.ap_id == actor_id
2023-03-18 14:51:36 +01:00
)
)
).one_or_none()
2023-07-29 04:56:39 +02:00
if exist_actor:
2023-04-01 11:17:01 +02:00
return exist_actor
2023-03-18 14:51:36 +01:00
2023-07-29 04:56:39 +02:00
ap_object = await ap.fetch(actor_id)
exist_actor = await save_actor(ap_object, db_session)
return exist_actor
2023-03-18 14:51:36 +01:00
async def save_actor(
2023-07-29 14:49:01 +02:00
ap_object: dict,
db_session: AsyncSession
2023-03-21 07:24:57 +01:00
) -> "ActorModel":
2023-07-29 04:56:39 +02:00
"""Save actor to db."""
2023-03-18 14:51:36 +01:00
logger.info("save actor " + ap_object["id"])
2023-03-21 07:24:57 +01:00
actor = models.Actor(
2023-03-18 14:51:36 +01:00
ap_id=ap_object["id"],
ap_actor=ap_object,
ap_type=ap_object["type"],
handle=_handle(ap_object),
)
db_session.add(actor)
await db_session.flush()
await db_session.refresh(actor)
return actor
2023-07-29 04:56:39 +02:00
2023-07-29 14:49:01 +02:00
def _handle(
ap_object: dict,
2023-03-18 14:51:36 +01:00
) -> str:
ap_id = urlparse(ap_object["id"])
if not ap_id.hostname:
raise ValueError(f"Invalid actor ID {ap_id}")
handle = '@' + ap_object["preferredUsername"] + '@' + ap_id.hostname
return handle
2023-04-01 18:13:16 +02:00
async def get_public_key(
db_session: AsyncSession,
key_id: str
) -> str:
2023-07-29 04:56:39 +02:00
"""Give key id and reutrn public key."""
2023-04-01 18:13:16 +02:00
existing_actor = (
await db_session.scalars(
2023-07-29 14:49:01 +02:00
select(models.Actor).where(
models.Actor.ap_id == key_id.split("#")[0])
2023-04-01 18:13:16 +02:00
)
).one_or_none()
public_key = existing_actor.ap_object["publicKey"]["publicKeyPem"]
return public_key