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
25
app.py
25
app.py
|
@ -1,5 +1,4 @@
|
||||||
import json
|
import json
|
||||||
from werkzeug.exceptions import InternalServerError
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -30,6 +29,7 @@ from little_boxes.errors import ActivityGoneError
|
||||||
from little_boxes.errors import Error
|
from little_boxes.errors import Error
|
||||||
from little_boxes.httpsig import verify_request
|
from little_boxes.httpsig import verify_request
|
||||||
from little_boxes.webfinger import get_remote_follow_template
|
from little_boxes.webfinger import get_remote_follow_template
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
import blueprints.admin
|
import blueprints.admin
|
||||||
import blueprints.indieauth
|
import blueprints.indieauth
|
||||||
|
@ -827,7 +827,30 @@ def inbox():
|
||||||
|
|
||||||
# We fetched the remote data successfully
|
# We fetched the remote data successfully
|
||||||
data = remote_data
|
data = remote_data
|
||||||
|
try:
|
||||||
activity = ap.parse_activity(data)
|
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}")
|
logger.debug(f"inbox activity={g.request_id}/{activity}/{data}")
|
||||||
|
|
||||||
post_to_inbox(activity)
|
post_to_inbox(activity)
|
||||||
|
|
|
@ -34,9 +34,12 @@ from core import feed
|
||||||
from core.activitypub import activity_url
|
from core.activitypub import activity_url
|
||||||
from core.activitypub import new_context
|
from core.activitypub import new_context
|
||||||
from core.activitypub import post_to_outbox
|
from core.activitypub import post_to_outbox
|
||||||
|
from core.db import update_one_activity
|
||||||
from core.meta import Box
|
from core.meta import Box
|
||||||
from core.meta import MetaKey
|
from core.meta import MetaKey
|
||||||
from core.meta import _meta
|
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 MY_PERSON
|
||||||
from core.shared import _Response
|
from core.shared import _Response
|
||||||
from core.shared import csrf
|
from core.shared import csrf
|
||||||
|
@ -178,6 +181,31 @@ def api_boost() -> _Response:
|
||||||
return _user_api_response(activity=announce_id)
|
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"])
|
@blueprint.route("/mark_notifications_as_read", methods=["POST"])
|
||||||
@api_required
|
@api_required
|
||||||
def api_mark_notification_as_read() -> _Response:
|
def api_mark_notification_as_read() -> _Response:
|
||||||
|
|
|
@ -66,10 +66,6 @@ class Tasks:
|
||||||
# TODO(tsileo): log invalid emoji
|
# TODO(tsileo): log invalid emoji
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def ack_reply(reply_iri: str) -> None:
|
|
||||||
p.push({"reply_iri": reply_iri}, "/task/ack_reply")
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def post_to_remote_inbox(payload: str, recp: str) -> None:
|
def post_to_remote_inbox(payload: str, recp: str) -> None:
|
||||||
p.push({"payload": payload, "to": recp}, "/task/post_to_remote_inbox")
|
p.push({"payload": payload, "to": recp}, "/task/post_to_remote_inbox")
|
||||||
|
|
|
@ -126,6 +126,17 @@
|
||||||
{% for item in inbox_data %}
|
{% for item in inbox_data %}
|
||||||
{% if 'actor' in item.meta %}
|
{% if 'actor' in item.meta %}
|
||||||
{% if item | has_type('Create') %}
|
{% 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) }}
|
{{ utils.display_note(item.activity.object, ui=True, meta=item.meta) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if item | has_type('Announce') %}
|
{% if item | has_type('Announce') %}
|
||||||
|
|
Loading…
Reference in a new issue