forked from forks/microblog.pub
Start support for acking/federating replies via Read activities
This commit is contained in:
parent
801d0effa9
commit
af6f7c1a5a
4 changed files with 64 additions and 6 deletions
27
app.py
27
app.py
|
@ -1,5 +1,4 @@
|
|||
import json
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
import logging
|
||||
import os
|
||||
import traceback
|
||||
|
@ -30,6 +29,7 @@ from little_boxes.errors import ActivityGoneError
|
|||
from little_boxes.errors import Error
|
||||
from little_boxes.httpsig import verify_request
|
||||
from little_boxes.webfinger import get_remote_follow_template
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
|
||||
import blueprints.admin
|
||||
import blueprints.indieauth
|
||||
|
@ -827,7 +827,30 @@ def inbox():
|
|||
|
||||
# We fetched the remote data successfully
|
||||
data = remote_data
|
||||
activity = ap.parse_activity(data)
|
||||
try:
|
||||
activity = ap.parse_activity(data)
|
||||
except ValueError:
|
||||
logger.exception("failed to parse activity for req {g.request_id}: {data!r}")
|
||||
|
||||
# Track/store the payload for analysis
|
||||
ip, geoip = _get_ip()
|
||||
|
||||
DB.trash.insert(
|
||||
{
|
||||
"activity": data,
|
||||
"meta": {
|
||||
"ts": datetime.now().timestamp(),
|
||||
"ip_address": ip,
|
||||
"geoip": geoip,
|
||||
"tb": traceback.format_exc(),
|
||||
"headers": dict(request.headers),
|
||||
"request_id": g.request_id,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
return Response(status=201)
|
||||
|
||||
logger.debug(f"inbox activity={g.request_id}/{activity}/{data}")
|
||||
|
||||
post_to_inbox(activity)
|
||||
|
|
|
@ -34,9 +34,12 @@ from core import feed
|
|||
from core.activitypub import activity_url
|
||||
from core.activitypub import new_context
|
||||
from core.activitypub import post_to_outbox
|
||||
from core.db import update_one_activity
|
||||
from core.meta import Box
|
||||
from core.meta import MetaKey
|
||||
from core.meta import _meta
|
||||
from core.meta import by_object_id
|
||||
from core.meta import by_type
|
||||
from core.shared import MY_PERSON
|
||||
from core.shared import _Response
|
||||
from core.shared import csrf
|
||||
|
@ -178,6 +181,31 @@ def api_boost() -> _Response:
|
|||
return _user_api_response(activity=announce_id)
|
||||
|
||||
|
||||
@blueprint.route("/ack_reply", methods=["POST"])
|
||||
@api_required
|
||||
def api_ack_reply() -> _Response:
|
||||
reply_iri = _user_api_arg("reply_iri")
|
||||
obj = ap.fetch_remote_activity(reply_iri)
|
||||
if obj.has_type(ap.ActivityType.CREATE):
|
||||
obj = obj.get_object()
|
||||
# TODO(tsileo): tweak the adressing?
|
||||
update_one_activity(
|
||||
{**by_type(ap.ActivityType.CREATE), **by_object_id(obj.id)},
|
||||
{"$set": {"meta.reply_acked": True}},
|
||||
)
|
||||
read = ap.Read(
|
||||
actor=MY_PERSON.id,
|
||||
object=obj.id,
|
||||
to=[MY_PERSON.followers],
|
||||
cc=[ap.AS_PUBLIC, obj.get_actor().id],
|
||||
published=now(),
|
||||
context=new_context(obj),
|
||||
)
|
||||
|
||||
read_id = post_to_outbox(read)
|
||||
return _user_api_response(activity=read_id)
|
||||
|
||||
|
||||
@blueprint.route("/mark_notifications_as_read", methods=["POST"])
|
||||
@api_required
|
||||
def api_mark_notification_as_read() -> _Response:
|
||||
|
|
|
@ -66,10 +66,6 @@ class Tasks:
|
|||
# TODO(tsileo): log invalid emoji
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def ack_reply(reply_iri: str) -> None:
|
||||
p.push({"reply_iri": reply_iri}, "/task/ack_reply")
|
||||
|
||||
@staticmethod
|
||||
def post_to_remote_inbox(payload: str, recp: str) -> None:
|
||||
p.push({"payload": payload, "to": recp}, "/task/post_to_remote_inbox")
|
||||
|
|
|
@ -126,6 +126,17 @@
|
|||
{% for item in inbox_data %}
|
||||
{% if 'actor' in item.meta %}
|
||||
{% if item | has_type('Create') %}
|
||||
{% if request.path.startswith("/admin") and not item.meta.reply_acked and item.meta.object_visibility | visibility_is_public %}
|
||||
<div style="margin-left:70px;padding-bottom:5px;margin-bottom:15px;display:inline-block;">
|
||||
<form action="/api/ack_reply" class="action-form" method="POST">
|
||||
<input type="hidden" name="redirect" value="{{ request.path }}"/>
|
||||
<input type="hidden" name="reply_iri" value="{{ item.meta.object_id }}"/>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="bar-item">ack reply</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{{ utils.display_note(item.activity.object, ui=True, meta=item.meta) }}
|
||||
{% else %}
|
||||
{% if item | has_type('Announce') %}
|
||||
|
|
Loading…
Reference in a new issue