Improved CW/sensitive support
parent
d4c80dedeb
commit
626a165411
14
app/admin.py
14
app/admin.py
|
@ -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),
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
19
app/boxes.py
19
app/boxes.py
|
@ -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:
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
Loading…
Reference in New Issue