Return images and summary in actor

pull/3/head
Andrew Godwin 2022-11-17 19:31:00 -07:00
rodzic 291d7e404e
commit 2a3690d1c1
8 zmienionych plików z 54 dodań i 9 usunięć

1
.gitignore vendored
Wyświetl plik

@ -1,5 +1,6 @@
*.psql *.psql
*.sqlite3 *.sqlite3
.venv .venv
/*.env
/media/ /media/
notes.md notes.md

Wyświetl plik

@ -20,12 +20,13 @@ def sanitize_post(post_html: str) -> str:
Only allows a, br, p and span tags, and class attributes. Only allows a, br, p and span tags, and class attributes.
""" """
cleaner = bleach.Cleaner( cleaner = bleach.Cleaner(
tags=["a", "br", "p", "span"], tags=["br", "p"],
attributes={ # type:ignore attributes={ # type:ignore
"a": allow_a, "a": allow_a,
"p": ["class"], "p": ["class"],
"span": ["class"], "span": ["class"],
}, },
filters=[LinkifyFilter], filters=[LinkifyFilter],
strip=True,
) )
return mark_safe(cleaner.clean(post_html)) return mark_safe(cleaner.clean(post_html))

Wyświetl plik

@ -1,4 +1,5 @@
import datetime import datetime
import os
import urllib.parse as urllib_parse import urllib.parse as urllib_parse
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
@ -436,3 +437,19 @@ def parse_ld_date(value: Optional[str]) -> Optional[datetime.datetime]:
return datetime.datetime.strptime(value, DATETIME_FORMAT).replace( return datetime.datetime.strptime(value, DATETIME_FORMAT).replace(
tzinfo=datetime.timezone.utc tzinfo=datetime.timezone.utc
) )
def media_type_from_filename(filename):
_, extension = os.path.splitext(filename)
if extension == ".png":
return "image/png"
elif extension in [".jpg", ".jpeg"]:
return "image/png"
elif extension == ".gif":
return "image/gif"
elif extension == ".apng":
return "image/apng"
elif extension == ".webp":
return "image/webp"
else:
return "application/octet-stream"

Wyświetl plik

@ -108,5 +108,7 @@ STATICFILES_DIRS = [
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ["*"]
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_URL = "/media/" # Note that this MUST be a fully qualified URL in production
MEDIA_URL = os.environ.get("TAKAHE_MEDIA_URL", "/media/")
MEDIA_ROOT = os.environ.get("TAKAHE_MEDIA_ROOT", BASE_DIR / "media")

Wyświetl plik

@ -1,5 +1,3 @@
import re
from django.conf import settings as djsettings from django.conf import settings as djsettings
from django.contrib import admin as djadmin from django.contrib import admin as djadmin
from django.urls import path, re_path from django.urls import path, re_path
@ -99,7 +97,7 @@ urlpatterns = [
path("djadmin/", djadmin.site.urls), path("djadmin/", djadmin.site.urls),
# Media files # Media files
re_path( re_path(
r"^%s(?P<path>.*)$" % re.escape(djsettings.MEDIA_URL.lstrip("/")), r"^media/(?P<path>.*)$",
serve, serve,
kwargs={"document_root": djsettings.MEDIA_ROOT}, kwargs={"document_root": djsettings.MEDIA_ROOT},
), ),

Wyświetl plik

@ -2,7 +2,9 @@
{% load activity_tags %} {% load activity_tags %}
<div class="post" data-takahe-id="{{ post.id }}"> <div class="post" data-takahe-id="{{ post.id }}">
<img src="{{ post.author.local_icon_url }}" class="icon"> <a href="{{ post.author.urls.view }}">
<img src="{{ post.author.local_icon_url }}" class="icon">
</a>
<time> <time>
{% if post.visibility == 0 %} {% if post.visibility == 0 %}

Wyświetl plik

@ -28,6 +28,12 @@
{{ identity.name_or_handle }} <small>@{{ identity.handle }}</small> {{ identity.name_or_handle }} <small>@{{ identity.handle }}</small>
</h1> </h1>
{% if identity.summary %}
<div class="summary">
{{ identity.safe_summary }}
</div>
{% endif %}
{% if not identity.local %} {% if not identity.local %}
{% if identity.outdated and not identity.name %} {% if identity.outdated and not identity.name %}
<p class="system-note"> <p class="system-note">

Wyświetl plik

@ -8,10 +8,12 @@ from asgiref.sync import async_to_sync, sync_to_async
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric import rsa
from django.db import models from django.db import models
from django.template.defaultfilters import linebreaks_filter
from django.templatetags.static import static from django.templatetags.static import static
from django.utils import timezone from django.utils import timezone
from core.ld import canonicalise from core.html import sanitize_post
from core.ld import canonicalise, media_type_from_filename
from core.uploads import upload_namer from core.uploads import upload_namer
from stator.models import State, StateField, StateGraph, StatorModel from stator.models import State, StateField, StateGraph, StatorModel
from users.models.domain import Domain from users.models.domain import Domain
@ -139,6 +141,10 @@ class Identity(StatorModel):
elif self.image_uri: elif self.image_uri:
return self.image_uri return self.image_uri
@property
def safe_summary(self):
return sanitize_post(self.summary)
### Alternate constructors/fetchers ### ### Alternate constructors/fetchers ###
@classmethod @classmethod
@ -223,7 +229,19 @@ class Identity(StatorModel):
if self.name: if self.name:
response["name"] = self.name response["name"] = self.name
if self.summary: if self.summary:
response["summary"] = self.summary response["summary"] = str(linebreaks_filter(self.summary))
if self.icon:
response["icon"] = {
"type": "Image",
"mediaType": media_type_from_filename(self.icon.name),
"url": self.icon.url,
}
if self.image:
response["image"] = {
"type": "Image",
"mediaType": media_type_from_filename(self.image.name),
"url": self.image.url,
}
return response return response
### ActivityPub (inbound) ### ### ActivityPub (inbound) ###