Return images and summary in actor
This commit is contained in:
parent
291d7e404e
commit
2a3690d1c1
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
*.psql
|
*.psql
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
.venv
|
.venv
|
||||||
|
/*.env
|
||||||
/media/
|
/media/
|
||||||
notes.md
|
notes.md
|
||||||
|
@ -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))
|
||||||
|
17
core/ld.py
17
core/ld.py
@ -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"
|
||||||
|
@ -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")
|
||||||
|
@ -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},
|
||||||
),
|
),
|
||||||
|
@ -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 %}
|
||||||
|
@ -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">
|
||||||
|
@ -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) ###
|
||||||
|
Reference in New Issue
Block a user