Improved CW/sensitive support

This commit is contained in:
Thomas Sileo 2022-06-28 21:10:22 +02:00
parent d4c80dedeb
commit 626a165411
6 changed files with 97 additions and 36 deletions

View file

@ -199,12 +199,22 @@ def admin_inbox(
else None else None
) )
actors_metadata = get_actors_metadata(
db,
[
inbox_object.actor
for inbox_object in inbox
if inbox_object.ap_type == "Follow"
],
)
return templates.render_template( return templates.render_template(
db, db,
request, request,
"admin_inbox.html", "admin_inbox.html",
{ {
"inbox": inbox, "inbox": inbox,
"actors_metadata": actors_metadata,
"next_cursor": next_cursor, "next_cursor": next_cursor,
}, },
) )
@ -475,6 +485,8 @@ def admin_actions_new(
content: str = Form(), content: str = Form(),
redirect_url: str = Form(), redirect_url: str = Form(),
in_reply_to: str | None = Form(None), in_reply_to: str | None = Form(None),
content_warning: str | None = Form(None),
is_sensitive: bool = Form(False),
visibility: str = Form(), visibility: str = Form(),
csrf_check: None = Depends(verify_csrf_token), csrf_check: None = Depends(verify_csrf_token),
db: Session = Depends(get_db), db: Session = Depends(get_db),
@ -491,6 +503,8 @@ def admin_actions_new(
uploads=uploads, uploads=uploads,
in_reply_to=in_reply_to or None, in_reply_to=in_reply_to or None,
visibility=ap.VisibilityEnum[visibility], visibility=ap.VisibilityEnum[visibility],
content_warning=content_warning or None,
is_sensitive=True if content_warning else is_sensitive,
) )
return RedirectResponse( return RedirectResponse(
request.url_for("outbox_by_public_id", public_id=public_id), request.url_for("outbox_by_public_id", public_id=public_id),

View file

@ -131,6 +131,10 @@ class Object:
return content return content
@property
def summary(self) -> str | None:
return self.ap_object.get("summary")
@property @property
def permalink_id(self) -> str: def permalink_id(self) -> str:
return ( return (

View file

@ -231,6 +231,8 @@ def send_create(
uploads: list[tuple[models.Upload, str]], uploads: list[tuple[models.Upload, str]],
in_reply_to: str | None, in_reply_to: str | None,
visibility: ap.VisibilityEnum, visibility: ap.VisibilityEnum,
content_warning: str | None = None,
is_sensitive: bool = False,
) -> str: ) -> str:
note_id = allocate_outbox_id() note_id = allocate_outbox_id()
published = now().replace(microsecond=0).isoformat().replace("+00:00", "Z") published = now().replace(microsecond=0).isoformat().replace("+00:00", "Z")
@ -285,9 +287,9 @@ def send_create(
"conversation": context, "conversation": context,
"url": outbox_object_id(note_id), "url": outbox_object_id(note_id),
"tag": tags, "tag": tags,
"summary": None, "summary": content_warning,
"inReplyTo": in_reply_to, "inReplyTo": in_reply_to,
"sensitive": False, "sensitive": is_sensitive,
"attachment": attachments, "attachment": attachments,
} }
outbox_object = save_outbox_object(db, note_id, note, source=source) outbox_object = save_outbox_object(db, note_id, note, source=source)
@ -550,10 +552,9 @@ def _handle_create_activity(
def save_to_inbox(db: Session, raw_object: ap.RawObject) -> None: def save_to_inbox(db: Session, raw_object: ap.RawObject) -> None:
try: try:
actor = fetch_actor(db, raw_object["actor"]) actor = fetch_actor(db, ap.get_id(raw_object["actor"]))
except httpx.HTTPStatusError: except httpx.HTTPStatusError:
logger.exception("Failed to fetch actor") logger.exception("Failed to fetch actor")
# XXX: Delete 410 when we never seen the actor
return return
ap_published_at = now() ap_published_at = now()
@ -561,6 +562,16 @@ def save_to_inbox(db: Session, raw_object: ap.RawObject) -> None:
ap_published_at = isoparse(raw_object["published"]) ap_published_at = isoparse(raw_object["published"])
ra = RemoteObject(ap.unwrap_activity(raw_object), actor=actor) ra = RemoteObject(ap.unwrap_activity(raw_object), actor=actor)
if (
db.query(models.InboxObject)
.filter(models.InboxObject.ap_id == ra.ap_id)
.count()
> 0
):
logger.info(f"Received duplicate {ra.ap_type} activity: {ra.ap_id}")
return
relates_to_inbox_object: models.InboxObject | None = None relates_to_inbox_object: models.InboxObject | None = None
relates_to_outbox_object: models.OutboxObject | None = None relates_to_outbox_object: models.OutboxObject | None = None
if ra.activity_object_ap_id: if ra.activity_object_ap_id:

View file

@ -10,7 +10,11 @@
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %} {% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
{{ utils.display_object(inbox_object) }} {{ utils.display_object(inbox_object) }}
{% elif inbox_object.ap_type == "Follow" %} {% elif inbox_object.ap_type == "Follow" %}
{{ utils.display_object(inbox_object) }} <div class="actor-action">
{{ inbox_object.actor.display_name }} followed you
<span>{{ inbox_object.ap_published_at | timeago }}</span>
</div>
{{ utils.display_actor(inbox_object.actor, actors_metadata) }}
{% else %} {% else %}
Implement {{ inbox_object.ap_type }} Implement {{ inbox_object.ap_type }}
{% endif %} {% endif %}

View file

@ -25,6 +25,12 @@
{% endfor %} {% endfor %}
<textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" style="font-size:1.2em;width:95%;">{{ content }}</textarea> <textarea name="content" rows="10" cols="50" autofocus="autofocus" designMode="on" style="font-size:1.2em;width:95%;">{{ content }}</textarea>
<p>
<input type="text" name="content_warning" placeholder="content warning (will mark the post as sensitive)" style="width:300px;">
</p>
<p>
<input type="checkbox" name="is_sensitive" id="is_sensitive"> <label for="is_sensitive">Mark attachment(s) as sentive</label>
</p>
<input type="hidden" name="in_reply_to" value="{{ request.query_params.in_reply_to }}"> <input type="hidden" name="in_reply_to" value="{{ request.query_params.in_reply_to }}">
<p> <p>
<input name="files" type="file" multiple> <input name="files" type="file" multiple>

View file

@ -88,6 +88,17 @@
</form> </form>
{% endmacro %} {% endmacro %}
{% macro show_more_button(permalink_id) %}
<form action="" method="GET">
<input type="hidden" name="show_more" value="{{ permalink_id }}">
{% for k, v in request.query_params.items() %}
<input type="hidden" name="{{k}}" value="{{v}}">
{% endfor %}
<button type="submit">show more</button>
</form>
{% endmacro %}
{% macro admin_reply_button(ap_object_id) %} {% macro admin_reply_button(ap_object_id) %}
<form action="/admin/new" method="GET"> <form action="/admin/new" method="GET">
<input type="hidden" name="in_reply_to" value="{{ ap_object_id }}"> <input type="hidden" name="in_reply_to" value="{{ ap_object_id }}">
@ -157,15 +168,43 @@
{% endmacro %} {% endmacro %}
{% macro display_attachments(object) %}
{% if object.attachments and object.sensitive and not request.query_params.show_sensitive == object.permalink_id %}
{{ sensitive_button(object.permalink_id )}}
{% endif %}
{% if object.attachments and (not object.sensitive or (object.sensitive and request.query_params["show_sensitive"] == object.permalink_id)) %}
{% for attachment in object.attachments %}
{% if attachment.type == "Image" or (attachment | has_media_type("image")) %}
<img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} alt="{{ attachment.name }}"{% endif %} class="attachment">
{% elif attachment.type == "Video" or (attachment | has_media_type("video")) %}
<video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachmeent"></video>
{% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %}
<audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} style="width:480px;" class="attachment"></audio>
{% else %}
<a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a>
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
{% macro display_object_expanded(object) %} {% macro display_object_expanded(object) %}
<div class="activity-expanded h-entry"> <div class="activity-expanded h-entry">
{{ display_actor(object.actor, {}) }} {{ display_actor(object.actor, {}) }}
<div class="e-content"> {% if object.summary %}
{{ object.content | clean_html(object) | safe }} <p class="p-summary">{{ object.summary | clean_html(object) | safe }}</p>
</div> {% endif %}
{% if object.sensitive and object.summary and not request.query_params.show_more == object.permalink_id %}
{{ show_more_button(object.permalink_id) }}
{% endif %}
{% if not object.sensitive or (object.sensitive and object.summary and request.query_params.show_more == object.permalink_id) %}
<div class="e-content">
{{ object.content | clean_html(object) | safe }}
</div>
{% endif %}
<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 }}
@ -177,6 +216,7 @@
{{ object.announces_count }} shares {{ object.announces_count }} shares
{% endif %} {% endif %}
{{ display_attachments(object) }}
</div> </div>
@ -194,32 +234,24 @@
{{ object.visibility.value }} {{ object.visibility.value }}
<a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | timeago }}</time></a> <a href="{{ object.url }}" class="u-url u-uid"><time class="dt-published" datetime="{{ object.ap_published_at }}">{{ object.ap_published_at | timeago }}</time></a>
</span> </span>
{% if object.summary %}
<p class="p-summary">{{ object.summary | clean_html(object) | safe }}</p>
{% endif %}
{% if object.sensitive and object.summary and not request.query_params.show_more == object.permalink_id %}
{{ show_more_button(object.permalink_id) }}
{% endif %}
{% if not object.sensitive or (object.sensitive and object.summary and request.query_params.show_more == object.permalink_id) %}
<div class="activity-main e-content"> <div class="activity-main e-content">
{{ object.content | clean_html(object) | safe }} {{ object.content | clean_html(object) | safe }}
</div> </div>
</div>
</div>
{% if object.attachments and object.sensitive and not request.query_params["show_sensitive"] == object.permalink_id %}
<div class="activity-attachment">
{{ sensitive_button(object.permalink_id )}}
</div>
{% endif %} {% endif %}
</div>
</div>
{% if object.attachments and (not object.sensitive or (object.sensitive and request.query_params["show_sensitive"] == object.permalink_id)) %}
<div class="activity-attachment"> <div class="activity-attachment">
{% for attachment in object.attachments %} {{ display_attachments(object) }}
{% if attachment.type == "Image" or (attachment | has_media_type("image")) %}
<img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} alt="{{ attachment.name }}"{% endif %} class="attachment">
{% elif attachment.type == "Video" or (attachment | has_media_type("video")) %}
<video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachmeent"></video>
{% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %}
<audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} style="width:480px;" class="attachment"></audio>
{% else %}
<a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a>
{% endif %}
{% endfor %}
</div> </div>
{% endif %}
<div class="activity-bar"> <div class="activity-bar">
{% if object.is_from_outbox %} {% if object.is_from_outbox %}
<div class="bar-item"> <div class="bar-item">
@ -285,15 +317,5 @@
</div> </div>
</div> </div>
{% elif object.ap_type == "Follow" %}
{% if object.is_from_inbox %}
<div class="actor-action">
{{ object.actor.display_name }} followed you
<span>{{ object.ap_published_at | timeago }}</span>
</div>
{{ display_actor(object.actor, {}) }}
{% endif %}
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}