fix: prefix view templates to avoid Nunjucks name collisions

Rename all views to activitypub-*.njk to prevent collisions with other
plugins that have dashboard.njk (podroll). Fix all new Date() calls to
use .toISOString() per Indiekit convention. Add try-catch in syndicator
to prevent delivery failures from crashing post creation.
This commit is contained in:
Ricardo
2026-02-18 23:10:35 +01:00
parent b551d82a21
commit deb9cb54a3
16 changed files with 25 additions and 20 deletions
+9 -4
View File
@@ -305,10 +305,15 @@ export default class ActivityPubEndpoint {
if (!self._federationHandler) { if (!self._federationHandler) {
return undefined; return undefined;
} }
return self._federationHandler.deliverToFollowers( try {
properties, return await self._federationHandler.deliverToFollowers(
publication, properties,
); publication,
);
} catch (error) {
console.error("[ActivityPub] Syndication failed:", error.message);
return undefined;
}
}, },
}; };
} }
+2 -2
View File
@@ -10,7 +10,7 @@ export function activitiesController(mountPath) {
const collection = application?.collections?.get("ap_activities"); const collection = application?.collections?.get("ap_activities");
if (!collection) { if (!collection) {
return response.render("activities", { return response.render("activitypub-activities", {
title: response.locals.__("activitypub.activities"), title: response.locals.__("activitypub.activities"),
activities: [], activities: [],
mountPath, mountPath,
@@ -30,7 +30,7 @@ export function activitiesController(mountPath) {
const cursor = buildCursor(page, totalPages, mountPath + "/admin/activities"); const cursor = buildCursor(page, totalPages, mountPath + "/admin/activities");
response.render("activities", { response.render("activitypub-activities", {
title: response.locals.__("activitypub.activities"), title: response.locals.__("activitypub.activities"),
activities, activities,
mountPath, mountPath,
+1 -1
View File
@@ -25,7 +25,7 @@ export function dashboardController(mountPath) {
.toArray() .toArray()
: []; : [];
response.render("dashboard", { response.render("activitypub-dashboard", {
title: response.locals.__("activitypub.title"), title: response.locals.__("activitypub.title"),
followerCount, followerCount,
followingCount, followingCount,
+2 -2
View File
@@ -10,7 +10,7 @@ export function followersController(mountPath) {
const collection = application?.collections?.get("ap_followers"); const collection = application?.collections?.get("ap_followers");
if (!collection) { if (!collection) {
return response.render("followers", { return response.render("activitypub-followers", {
title: response.locals.__("activitypub.followers"), title: response.locals.__("activitypub.followers"),
followers: [], followers: [],
followerCount: 0, followerCount: 0,
@@ -31,7 +31,7 @@ export function followersController(mountPath) {
const cursor = buildCursor(page, totalPages, mountPath + "/admin/followers"); const cursor = buildCursor(page, totalPages, mountPath + "/admin/followers");
response.render("followers", { response.render("activitypub-followers", {
title: response.locals.__("activitypub.followers"), title: response.locals.__("activitypub.followers"),
followers, followers,
followerCount: totalCount, followerCount: totalCount,
+2 -2
View File
@@ -10,7 +10,7 @@ export function followingController(mountPath) {
const collection = application?.collections?.get("ap_following"); const collection = application?.collections?.get("ap_following");
if (!collection) { if (!collection) {
return response.render("following", { return response.render("activitypub-following", {
title: response.locals.__("activitypub.following"), title: response.locals.__("activitypub.following"),
following: [], following: [],
followingCount: 0, followingCount: 0,
@@ -31,7 +31,7 @@ export function followingController(mountPath) {
const cursor = buildCursor(page, totalPages, mountPath + "/admin/following"); const cursor = buildCursor(page, totalPages, mountPath + "/admin/following");
response.render("following", { response.render("activitypub-following", {
title: response.locals.__("activitypub.following"), title: response.locals.__("activitypub.following"),
following, following,
followingCount: totalCount, followingCount: totalCount,
+2 -2
View File
@@ -15,7 +15,7 @@ import {
export function migrateGetController(mountPath) { export function migrateGetController(mountPath) {
return async (request, response, next) => { return async (request, response, next) => {
try { try {
response.render("migrate", { response.render("activitypub-migrate", {
title: response.locals.__("activitypub.migrate"), title: response.locals.__("activitypub.migrate"),
mountPath, mountPath,
result: null, result: null,
@@ -91,7 +91,7 @@ export function migratePostController(mountPath, pluginOptions) {
} }
} }
response.render("migrate", { response.render("activitypub-migrate", {
title: response.locals.__("activitypub.migrate"), title: response.locals.__("activitypub.migrate"),
mountPath, mountPath,
result, result,
+1 -1
View File
@@ -221,7 +221,7 @@ export function createFederationHandler(options) {
actorUrl, actorUrl,
objectUrl: activity.object?.id || activity.object, objectUrl: activity.object?.id || activity.object,
summary: `Delivered ${activity.type} to ${delivered}/${inboxes.size} inboxes`, summary: `Delivered ${activity.type} to ${delivered}/${inboxes.size} inboxes`,
receivedAt: new Date(), receivedAt: new Date().toISOString(),
...(storeRawActivities ? { raw: activity } : {}), ...(storeRawActivities ? { raw: activity } : {}),
}); });
+2 -2
View File
@@ -63,7 +63,7 @@ async function handleFollow(activity, collections, context) {
avatar: profile.icon?.url || "", avatar: profile.icon?.url || "",
inbox: profile.inbox || "", inbox: profile.inbox || "",
sharedInbox: profile.endpoints?.sharedInbox || "", sharedInbox: profile.endpoints?.sharedInbox || "",
followedAt: new Date(), followedAt: new Date().toISOString(),
}, },
}, },
{ upsert: true }, { upsert: true },
@@ -286,6 +286,6 @@ async function logActivity(collections, context, record) {
await collections.ap_activities.insertOne({ await collections.ap_activities.insertOne({
...rest, ...rest,
...(context.storeRawActivities ? { raw } : {}), ...(context.storeRawActivities ? { raw } : {}),
receivedAt: new Date(), receivedAt: new Date().toISOString(),
}); });
} }
+1 -1
View File
@@ -32,7 +32,7 @@ export async function getOrCreateKeyPair(collection, actorUrl) {
actorUrl, actorUrl,
publicKeyPem: publicKey, publicKeyPem: publicKey,
privateKeyPem: privateKey, privateKeyPem: privateKey,
createdAt: new Date(), createdAt: new Date().toISOString(),
}); });
return { publicKeyPem: publicKey, privateKeyPem: privateKey }; return { publicKeyPem: publicKey, privateKeyPem: privateKey };
+2 -2
View File
@@ -121,7 +121,7 @@ export async function bulkImportFollowing(handles, collection) {
name: resolved.name, name: resolved.name,
inbox: resolved.inbox, inbox: resolved.inbox,
sharedInbox: resolved.sharedInbox, sharedInbox: resolved.sharedInbox,
followedAt: new Date(), followedAt: new Date().toISOString(),
source: "import", source: "import",
}, },
}, },
@@ -171,7 +171,7 @@ export async function bulkImportFollowers(entries, collection) {
name: actorData.name, name: actorData.name,
inbox: actorData.inbox, inbox: actorData.inbox,
sharedInbox: actorData.sharedInbox, sharedInbox: actorData.sharedInbox,
followedAt: new Date(), followedAt: new Date().toISOString(),
pending: true, // Will be confirmed when they re-follow after Move pending: true, // Will be confirmed when they re-follow after Move
}, },
}, },
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "0.1.2", "version": "0.1.3",
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
"keywords": [ "keywords": [
"indiekit", "indiekit",