fix: fetch remote AP object in search resolve when not in local timeline
Deploy Indiekit Server / deploy (push) Successful in 1m21s
Deploy Indiekit Server / deploy (push) Successful in 1m21s
The v1 ap-search-url-resolve patch only found posts already stored in ap_timeline. Threads posts (and any not yet federated here) were never there, so boost/like still failed with "Failed to load post." New ap-search-url-resolve-remote patch: when the local lookup misses, fetch the AP object remotely via lookupWithSecurity → extractObjectData → addTimelineItem, then return the stored status to the client. This makes like/boost work for any public post reachable from the federation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -219,6 +219,63 @@ for (const f of SEARCH_CANDIDATES) {
|
||||
}
|
||||
if (!searchDone) console.log(`[postinstall] ${SCRIPT}: ap-search-url-resolve — no target file found or no changes`);
|
||||
|
||||
// ── patch-ap-search-url-resolve-remote: fetch AP object when not in local timeline ──
|
||||
// The v1 patch only looked up posts already in ap_timeline. Posts from Threads
|
||||
// (or any instance not yet federated to this server) were never stored there, so
|
||||
// the resolve block returned nothing. This patch adds an `else if` that fetches
|
||||
// the AP object remotely via lookupWithSecurity, stores it via extractObjectData +
|
||||
// addTimelineItem, then returns it. This makes like/boost work on any public post,
|
||||
// not just ones already in the local timeline.
|
||||
|
||||
const SEARCH_REMOTE_MARKER = "// [patch] ap-search-url-resolve-remote";
|
||||
// Anchor: the two consecutive closing braces at the end of the v1 URL-resolve block.
|
||||
// They appear exactly once in the patched search.js.
|
||||
const SEARCH_REMOTE_OLD = ` } // [patch] ap-search-url-resolve
|
||||
} // [patch] ap-search-url-resolve`;
|
||||
const SEARCH_REMOTE_NEW = [
|
||||
` } else if (pluginOptions.federation) { ${SEARCH_REMOTE_MARKER}`,
|
||||
` try { ${SEARCH_REMOTE_MARKER}`,
|
||||
` const { lookupWithSecurity } = await import("../../lookup-helpers.js"); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const { extractObjectData } = await import("../../timeline-store.js"); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const { addTimelineItem } = await import("../../storage/timeline.js"); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const _rCtx = pluginOptions.federation.createContext(new URL(pluginOptions.publicationUrl), { handle: pluginOptions.handle, publicationUrl: pluginOptions.publicationUrl }); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const _rDl = await _rCtx.getDocumentLoader({ identifier: pluginOptions.handle }); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const _rObj = await lookupWithSecurity(_rCtx, new URL(query), { documentLoader: _rDl }); ${SEARCH_REMOTE_MARKER}`,
|
||||
` if (_rObj) { ${SEARCH_REMOTE_MARKER}`,
|
||||
` const _rData = await extractObjectData(_rObj, { documentLoader: _rDl }); ${SEARCH_REMOTE_MARKER}`,
|
||||
` const _rStored = await addTimelineItem(collections, _rData); ${SEARCH_REMOTE_MARKER}`,
|
||||
` if (_rStored) { ${SEARCH_REMOTE_MARKER}`,
|
||||
` results.statuses.push(serializeStatus(_rStored, { ${SEARCH_REMOTE_MARKER}`,
|
||||
` baseUrl, favouritedIds: new Set(), rebloggedIds: new Set(), ${SEARCH_REMOTE_MARKER}`,
|
||||
` bookmarkedIds: new Set(), pinnedIds: new Set(), ${SEARCH_REMOTE_MARKER}`,
|
||||
` })); ${SEARCH_REMOTE_MARKER}`,
|
||||
` } ${SEARCH_REMOTE_MARKER}`,
|
||||
` } ${SEARCH_REMOTE_MARKER}`,
|
||||
` } catch (_rErr) { ${SEARCH_REMOTE_MARKER}`,
|
||||
` console.warn(\`[Mastodon API] search resolve remote fetch failed for \${query}: \${_rErr.message}\`); ${SEARCH_REMOTE_MARKER}`,
|
||||
` } ${SEARCH_REMOTE_MARKER}`,
|
||||
` } // [patch] ap-search-url-resolve`,
|
||||
` } // [patch] ap-search-url-resolve`,
|
||||
].join("\n");
|
||||
|
||||
let searchRemoteDone = false;
|
||||
for (const f of SEARCH_CANDIDATES) {
|
||||
if (!(await fileExists(f))) continue;
|
||||
const src = await readFile(f, "utf8");
|
||||
if (src.includes(SEARCH_REMOTE_MARKER)) {
|
||||
console.log(`[postinstall] ${SCRIPT}: ap-search-url-resolve-remote already applied in ${f}`);
|
||||
searchRemoteDone = true; break;
|
||||
}
|
||||
if (!src.includes(SEARCH_REMOTE_OLD)) {
|
||||
console.warn(`[postinstall] ${SCRIPT}: ap-search-url-resolve-remote — anchor not found in ${f} (v1 patch not applied?)`);
|
||||
continue;
|
||||
}
|
||||
await writeFile(f, src.replace(SEARCH_REMOTE_OLD, SEARCH_REMOTE_NEW), "utf8");
|
||||
console.log(`[postinstall] ${SCRIPT}: applied ap-search-url-resolve-remote to ${f}`);
|
||||
total++; searchRemoteDone = true; break;
|
||||
}
|
||||
if (!searchRemoteDone) console.log(`[postinstall] ${SCRIPT}: ap-search-url-resolve-remote — no target file found or no changes`);
|
||||
|
||||
// ── patch-ap-resolve-actor-timeout: cap actor lookup at 8 s + log failures ───
|
||||
// When Mastodon client clicks a @mention handle, /api/v1/accounts/lookup calls
|
||||
// resolveRemoteAccount → lookupWithSecurity → ctx.lookupObject (no timeout).
|
||||
|
||||
Reference in New Issue
Block a user