Display Webmention as replies when applicable

This commit is contained in:
Thomas Sileo 2022-11-18 20:20:58 +01:00
parent ae8029cd22
commit 120f92a9ed
5 changed files with 124 additions and 6 deletions

View file

@ -1,5 +1,6 @@
import datetime
from dataclasses import dataclass
from typing import Any
from typing import Optional
from loguru import logger
@ -7,7 +8,9 @@ from loguru import logger
from app import media
from app.models import InboxObject
from app.models import Webmention
from app.models import WebmentionType
from app.utils.url import make_abs
from app.utils.datetime import parse_isoformat
@dataclass
@ -36,7 +39,9 @@ class Face:
try:
return cls(
ap_actor_id=None,
url=webmention.source,
url=(
item["properties"]["url"][0] if item["properties"].get("url") else webmention.source
),
name=item["properties"]["name"][0],
picture_url=media.resized_media_url(
make_abs(
@ -81,3 +86,66 @@ def merge_faces(faces: list[Face]) -> list[Face]:
key=lambda f: f.created_at,
reverse=True,
)[:10]
def _parse_face(webmention: Webmention, items: list[dict[str, Any]]) -> Face | None:
for item in items:
if item["type"][0] == "h-card":
try:
return Face(
ap_actor_id=None,
url=(
items["properties"]["url"][0] if item["properties"].get("url") else webmention.source
),
name=item["properties"]["name"][0],
picture_url=media.resized_media_url(
make_abs(
item["properties"]["photo"][0], webmention.source
), # type: ignore
50,
),
created_at=webmention.created_at, # type: ignore
)
except Exception:
logger.exception(
f"Failed to build Face for webmention id={webmention.id}"
)
break
@dataclass
class WebmentionReply:
face: Face
content: str
url: str
published_at: datetime.datetime
@classmethod
def from_webmention(cls, webmention: Webmention) -> "WebmentionReply":
if webmention.webmention_type != WebmentionType.REPLY:
raise ValueError(f"Unexpected webmention {webmention.id}")
items = webmention.source_microformats.get("items", []) # type: ignore
for item in items:
if item["type"][0] == "h-entry":
try:
face = _parse_face(webmention, item["properties"].get("author", []))
if not face:
logger.info(
"Failed to build WebmentionReply/Face for "
f"webmention id={webmention.id}"
)
break
return cls(
face=face,
content=item["properties"]["content"][0]["html"],
url=item["properties"]["url"][0],
published_at=parse_isoformat(
item["properties"]["published"][0]
).replace(tzinfo=None),
)
except Exception:
logger.exception(
f"Failed to build Face for webmention id={webmention.id}"
)
break