fix: Accept(Follow) handler not matching incoming accepts
Two issues prevented Accept activities from transitioning ap_following docs from refollow:sent to federation: 1. accept.getObject() often returns null because remote servers reference our outgoing Follow by URL, which Fedify can't resolve back. The strict instanceof Follow check caused early return on every Accept. Now we proceed to the MongoDB match if getObject() returns null or throws. 2. Batch processor sent Follow to entry.actorUrl but never updated the stored URL to the canonical form after resolving the remote actor. Now updates actorUrl to remoteActor.id.href so Accept handler matches.
This commit is contained in:
+17
-8
@@ -233,23 +233,32 @@ async function processOneFollow(options, entry) {
|
||||
throw new Error("Could not resolve remote actor");
|
||||
}
|
||||
|
||||
// Send Follow activity
|
||||
// Use the canonical actor URL (may differ from imported URL)
|
||||
const canonicalUrl = remoteActor.id?.href || entry.actorUrl;
|
||||
|
||||
// Send Follow activity using canonical URL
|
||||
const follow = new Follow({
|
||||
actor: ctx.getActorUri(handle),
|
||||
object: new URL(entry.actorUrl),
|
||||
object: new URL(canonicalUrl),
|
||||
});
|
||||
|
||||
await ctx.sendActivity({ identifier: handle }, remoteActor, follow);
|
||||
|
||||
// Mark as sent
|
||||
await collections.ap_following.updateOne(
|
||||
{ _id: entry._id },
|
||||
{
|
||||
$set: {
|
||||
// Mark as sent — update actorUrl to canonical form so Accept handler
|
||||
// can match when the remote server responds
|
||||
const updateFields = {
|
||||
source: "refollow:sent",
|
||||
refollowLastAttempt: new Date().toISOString(),
|
||||
refollowError: null,
|
||||
},
|
||||
};
|
||||
if (canonicalUrl !== entry.actorUrl) {
|
||||
updateFields.actorUrl = canonicalUrl;
|
||||
}
|
||||
|
||||
await collections.ap_following.updateOne(
|
||||
{ _id: entry._id },
|
||||
{
|
||||
$set: updateFields,
|
||||
$inc: { refollowAttempts: 1 },
|
||||
},
|
||||
);
|
||||
|
||||
+16
-1
@@ -125,8 +125,23 @@ export function registerInboxListeners(inboxChain, options) {
|
||||
const actorUrl = actorObj?.id?.href || "";
|
||||
if (!actorUrl) return;
|
||||
|
||||
// Check if the inner object is a Follow. Some servers send the full
|
||||
// Follow object, others send only a reference URL that Fedify can't
|
||||
// resolve (since the original Follow was our outgoing activity).
|
||||
let isFollow = false;
|
||||
try {
|
||||
const inner = await accept.getObject();
|
||||
if (!(inner instanceof Follow)) return;
|
||||
isFollow = inner instanceof Follow;
|
||||
// If inner resolved to a non-Follow activity, skip
|
||||
if (inner && !isFollow) {
|
||||
console.info(
|
||||
`[ActivityPub] Accept from ${actorUrl}: inner is ${inner.constructor?.name}, not Follow — skipping`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// getObject() failed — proceed anyway if we have a pending follow
|
||||
}
|
||||
|
||||
// Match against our following list for refollow or microsub-reader follows
|
||||
const result = await collections.ap_following.findOneAndUpdate(
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rmdes/indiekit-endpoint-activitypub",
|
||||
"version": "1.0.14",
|
||||
"version": "1.0.15",
|
||||
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
||||
"keywords": [
|
||||
"indiekit",
|
||||
|
||||
Reference in New Issue
Block a user