Route outbound Follow through EventProcessor for retry
send_follow now emits a Follow activity via emit_activity() instead of inline HTTP POST. New ap_follow_handler delivers to the remote inbox; EventProcessor retries on failure. Wildcard delivery handler skips Follow type to avoid duplicate broadcast. Also add /social/ index page to per-app social blueprint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -686,42 +686,21 @@ class SqlFederationService:
|
||||
session.add(follow)
|
||||
await session.flush()
|
||||
|
||||
# Send Follow activity
|
||||
domain = _domain()
|
||||
actor_url = f"https://{domain}/users/{local_username}"
|
||||
follow_id = f"{actor_url}/activities/{uuid.uuid4()}"
|
||||
|
||||
follow_activity = {
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": follow_id,
|
||||
"type": "Follow",
|
||||
"actor": actor_url,
|
||||
"object": remote_actor_url,
|
||||
}
|
||||
|
||||
import json
|
||||
import httpx
|
||||
from shared.utils.http_signatures import sign_request
|
||||
from urllib.parse import urlparse
|
||||
|
||||
body_bytes = json.dumps(follow_activity).encode()
|
||||
parsed = urlparse(remote.inbox_url)
|
||||
headers = sign_request(
|
||||
private_key_pem=actor.private_key_pem,
|
||||
key_id=f"{actor_url}#main-key",
|
||||
method="POST",
|
||||
path=parsed.path,
|
||||
host=parsed.netloc,
|
||||
body=body_bytes,
|
||||
# Emit Follow activity — EventProcessor delivers with retries
|
||||
from shared.events.bus import emit_activity
|
||||
await emit_activity(
|
||||
session,
|
||||
activity_type="Follow",
|
||||
actor_uri=f"https://{_domain()}/users/{local_username}",
|
||||
object_type="Actor",
|
||||
object_data={
|
||||
"target_inbox": remote.inbox_url,
|
||||
"target_actor_url": remote_actor_url,
|
||||
"following_id": follow.id,
|
||||
},
|
||||
visibility="public",
|
||||
actor_profile_id=actor.id,
|
||||
)
|
||||
headers["Content-Type"] = "application/activity+json"
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=15) as client:
|
||||
await client.post(remote.inbox_url, content=body_bytes, headers=headers)
|
||||
except Exception:
|
||||
import logging
|
||||
logging.getLogger(__name__).exception("Failed to send Follow to %s", remote.inbox_url)
|
||||
|
||||
async def get_following(
|
||||
self, session: AsyncSession, username: str,
|
||||
|
||||
Reference in New Issue
Block a user