Admin fixes and improved OG meta support
parent
1f54a6a6ac
commit
f560821be0
|
@ -270,6 +270,9 @@ async def admin_outbox(
|
||||||
joinedload(models.OutboxObject.relates_to_inbox_object),
|
joinedload(models.OutboxObject.relates_to_inbox_object),
|
||||||
joinedload(models.OutboxObject.relates_to_outbox_object),
|
joinedload(models.OutboxObject.relates_to_outbox_object),
|
||||||
joinedload(models.OutboxObject.relates_to_actor),
|
joinedload(models.OutboxObject.relates_to_actor),
|
||||||
|
joinedload(models.OutboxObject.outbox_object_attachments).options(
|
||||||
|
joinedload(models.OutboxObjectAttachment.upload)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.order_by(models.OutboxObject.ap_published_at.desc())
|
.order_by(models.OutboxObject.ap_published_at.desc())
|
||||||
.limit(page_size)
|
.limit(page_size)
|
||||||
|
@ -317,7 +320,11 @@ async def get_notifications(
|
||||||
.options(
|
.options(
|
||||||
joinedload(models.Notification.actor),
|
joinedload(models.Notification.actor),
|
||||||
joinedload(models.Notification.inbox_object),
|
joinedload(models.Notification.inbox_object),
|
||||||
joinedload(models.Notification.outbox_object),
|
joinedload(models.Notification.outbox_object).options(
|
||||||
|
joinedload(
|
||||||
|
models.OutboxObject.outbox_object_attachments
|
||||||
|
).options(joinedload(models.OutboxObjectAttachment.upload)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.order_by(models.Notification.created_at.desc())
|
.order_by(models.Notification.created_at.desc())
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,6 @@ from app.actor import LOCAL_ACTOR
|
||||||
from app.actor import Actor
|
from app.actor import Actor
|
||||||
from app.actor import RemoteActor
|
from app.actor import RemoteActor
|
||||||
from app.media import proxied_media_url
|
from app.media import proxied_media_url
|
||||||
from app.utils import opengraph
|
|
||||||
|
|
||||||
|
|
||||||
class Object:
|
class Object:
|
||||||
|
@ -199,13 +198,9 @@ class RemoteObject(Object):
|
||||||
)
|
)
|
||||||
|
|
||||||
self._og_meta = None
|
self._og_meta = None
|
||||||
if self.ap_type == "Note":
|
|
||||||
self._og_meta = opengraph.og_meta_from_note(self._raw_object)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def og_meta(self) -> list[dict[str, Any]] | None:
|
def og_meta(self) -> list[dict[str, Any]] | None:
|
||||||
if self._og_meta:
|
|
||||||
return [og_meta.dict() for og_meta in self._og_meta]
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -30,6 +30,7 @@ from app.database import now
|
||||||
from app.outgoing_activities import new_outgoing_activity
|
from app.outgoing_activities import new_outgoing_activity
|
||||||
from app.source import markdownify
|
from app.source import markdownify
|
||||||
from app.uploads import upload_to_attachment
|
from app.uploads import upload_to_attachment
|
||||||
|
from app.utils import opengraph
|
||||||
|
|
||||||
AnyboxObject = models.InboxObject | models.OutboxObject
|
AnyboxObject = models.InboxObject | models.OutboxObject
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ async def save_outbox_object(
|
||||||
ap_context=ra.ap_context,
|
ap_context=ra.ap_context,
|
||||||
ap_object=ra.ap_object,
|
ap_object=ra.ap_object,
|
||||||
visibility=ra.visibility,
|
visibility=ra.visibility,
|
||||||
og_meta=ra.og_meta,
|
og_meta=await opengraph.og_meta_from_note(ra.ap_object),
|
||||||
relates_to_inbox_object_id=relates_to_inbox_object_id,
|
relates_to_inbox_object_id=relates_to_inbox_object_id,
|
||||||
relates_to_outbox_object_id=relates_to_outbox_object_id,
|
relates_to_outbox_object_id=relates_to_outbox_object_id,
|
||||||
relates_to_actor_id=relates_to_actor_id,
|
relates_to_actor_id=relates_to_actor_id,
|
||||||
|
|
|
@ -168,6 +168,26 @@
|
||||||
|
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro display_og_meta(object) %}
|
||||||
|
{% if object.og_meta %}
|
||||||
|
{% for og_meta in object.og_meta %}
|
||||||
|
<div style="display:flex;column-gap: 20px;margin:20px 0;">
|
||||||
|
{% if og_meta.image %}
|
||||||
|
<div>
|
||||||
|
<img src="{{ og_meta.image | media_proxy_url }}" style="max-width:200px;">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="{{ og_meta.url }}">{{ og_meta.title }}</a>
|
||||||
|
{% if og_meta.description %}<p>{{ og_meta.description }}</p>{% endif %}
|
||||||
|
<small style="display:block;">{{ og_meta.site_name }}</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
{% macro display_attachments(object) %}
|
{% macro display_attachments(object) %}
|
||||||
{% if object.attachments and object.sensitive and not request.query_params.show_sensitive == object.permalink_id %}
|
{% if object.attachments and object.sensitive and not request.query_params.show_sensitive == object.permalink_id %}
|
||||||
{{ sensitive_button(object.permalink_id )}}
|
{{ sensitive_button(object.permalink_id )}}
|
||||||
|
@ -206,6 +226,8 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{{ display_og_meta(object) }}
|
||||||
|
|
||||||
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | format_date }}</time></a>
|
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | format_date }}</time></a>
|
||||||
{{ object.visibility.value }}
|
{{ object.visibility.value }}
|
||||||
{% if object.is_from_outbox %}
|
{% if object.is_from_outbox %}
|
||||||
|
@ -248,8 +270,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="padding-left:60px">
|
||||||
|
{{ display_og_meta(object) }}
|
||||||
|
</div>
|
||||||
<div class="activity-attachment">
|
<div class="activity-attachment">
|
||||||
{{ display_attachments(object) }}
|
|
||||||
|
{{ display_attachments(object) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="activity-bar">
|
<div class="activity-bar">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import re
|
import re
|
||||||
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
@ -60,14 +61,16 @@ def _urls_from_note(note: ap.RawObject) -> set[str]:
|
||||||
return urls
|
return urls
|
||||||
|
|
||||||
|
|
||||||
def _og_meta_from_url(url: str) -> OpenGraphMeta | None:
|
async def _og_meta_from_url(url: str) -> OpenGraphMeta | None:
|
||||||
resp = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
url,
|
resp = await client.get(
|
||||||
headers={
|
url,
|
||||||
"User-Agent": config.USER_AGENT,
|
headers={
|
||||||
},
|
"User-Agent": config.USER_AGENT,
|
||||||
follow_redirects=True,
|
},
|
||||||
)
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
||||||
if not (ct := resp.headers.get("content-type")) or not ct.startswith("text/html"):
|
if not (ct := resp.headers.get("content-type")) or not ct.startswith("text/html"):
|
||||||
|
@ -76,14 +79,14 @@ def _og_meta_from_url(url: str) -> OpenGraphMeta | None:
|
||||||
return _scrap_og_meta(resp.text)
|
return _scrap_og_meta(resp.text)
|
||||||
|
|
||||||
|
|
||||||
def og_meta_from_note(note: ap.RawObject) -> list[OpenGraphMeta]:
|
async def og_meta_from_note(note: ap.RawObject) -> list[dict[str, Any]]:
|
||||||
og_meta = []
|
og_meta = []
|
||||||
urls = _urls_from_note(note)
|
urls = _urls_from_note(note)
|
||||||
for url in urls:
|
for url in urls:
|
||||||
try:
|
try:
|
||||||
maybe_og_meta = _og_meta_from_url(url)
|
maybe_og_meta = await _og_meta_from_url(url)
|
||||||
if maybe_og_meta:
|
if maybe_og_meta:
|
||||||
og_meta.append(maybe_og_meta)
|
og_meta.append(maybe_og_meta.dict())
|
||||||
except httpx.HTTPError:
|
except httpx.HTTPError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue