Compare commits
3 Commits
decoupling
...
9a8b556c13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a8b556c13 | ||
|
|
a626dd849d | ||
|
|
d0b1edea7a |
@@ -25,6 +25,15 @@
|
|||||||
{% endcall %}
|
{% endcall %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# Container nav widgets (market links, etc.) #}
|
||||||
|
{% if container_nav_widgets %}
|
||||||
|
{% for wdata in container_nav_widgets %}
|
||||||
|
{% with ctx=wdata.ctx %}
|
||||||
|
{% include wdata.widget.template with context %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# Admin link #}
|
{# Admin link #}
|
||||||
{% if g.rights.admin %}
|
{% if g.rights.admin %}
|
||||||
{% from 'macros/admin_nav.html' import admin_nav_item %}
|
{% from 'macros/admin_nav.html' import admin_nav_item %}
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
{% endcall %}
|
{% endcall %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if container_nav_widgets %}
|
||||||
|
{% for wdata in container_nav_widgets %}
|
||||||
|
{% with ctx=wdata.ctx %}
|
||||||
|
{% include wdata.widget.template with context %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# Admin link #}
|
{# Admin link #}
|
||||||
{% if g.rights.admin %}
|
{% if g.rights.admin %}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ def _build_activity_json(activity: APActivity, actor: ActorProfile, domain: str)
|
|||||||
obj.setdefault("type", "Tombstone")
|
obj.setdefault("type", "Tombstone")
|
||||||
else:
|
else:
|
||||||
# Create/Update: full object with attribution
|
# Create/Update: full object with attribution
|
||||||
obj["id"] = object_id
|
# Prefer stable id from object_data (set by try_publish), fall back to activity-derived
|
||||||
|
obj.setdefault("id", object_id)
|
||||||
obj.setdefault("type", activity.object_type)
|
obj.setdefault("type", activity.object_type)
|
||||||
obj.setdefault("attributedTo", actor_url)
|
obj.setdefault("attributedTo", actor_url)
|
||||||
obj.setdefault("published", activity.published.isoformat() if activity.published else None)
|
obj.setdefault("published", activity.published.isoformat() if activity.published else None)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ which creates the APActivity in the same DB transaction. AP delivery
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
@@ -48,10 +49,20 @@ async def try_publish(
|
|||||||
if existing:
|
if existing:
|
||||||
if activity_type == "Create" and existing.activity_type != "Delete":
|
if activity_type == "Create" and existing.activity_type != "Delete":
|
||||||
return # already published (allow re-Create after Delete/unpublish)
|
return # already published (allow re-Create after Delete/unpublish)
|
||||||
|
if activity_type == "Update" and existing.activity_type == "Update":
|
||||||
|
return # already updated (Ghost fires duplicate webhooks)
|
||||||
if activity_type == "Delete" and existing.activity_type == "Delete":
|
if activity_type == "Delete" and existing.activity_type == "Delete":
|
||||||
return # already deleted
|
return # already deleted
|
||||||
elif activity_type == "Delete":
|
elif activity_type in ("Delete", "Update"):
|
||||||
return # never published, nothing to delete
|
return # never published, nothing to delete/update
|
||||||
|
|
||||||
|
# Stable object ID: same source always gets the same object id so
|
||||||
|
# Mastodon treats Create/Update/Delete as the same post.
|
||||||
|
domain = os.getenv("AP_DOMAIN", "rose-ash.com")
|
||||||
|
object_data["id"] = (
|
||||||
|
f"https://{domain}/users/{actor.preferred_username}"
|
||||||
|
f"/objects/{source_type.lower()}/{source_id}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await services.federation.publish_activity(
|
await services.federation.publish_activity(
|
||||||
|
|||||||
Reference in New Issue
Block a user