diff --git a/lib/mastodon/helpers/account-cache.js b/lib/mastodon/helpers/account-cache.js index 0407855..e061e58 100644 --- a/lib/mastodon/helpers/account-cache.js +++ b/lib/mastodon/helpers/account-cache.js @@ -7,12 +7,18 @@ * LRU-style with TTL — entries expire after 1 hour. */ +import { remoteActorId } from "./id-mapping.js"; + const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour const MAX_ENTRIES = 500; // Map const cache = new Map(); +// Reverse map: accountId (hash) → actorUrl +// Populated alongside the stats cache for follow/unfollow lookups +const idToUrl = new Map(); + /** * Store account stats in cache. * @param {string} actorUrl - The actor's URL (cache key) @@ -28,6 +34,10 @@ export function cacheAccountStats(actorUrl, stats) { } cache.set(actorUrl, { ...stats, cachedAt: Date.now() }); + + // Maintain reverse lookup + const hashId = remoteActorId(actorUrl); + if (hashId) idToUrl.set(hashId, actorUrl); } /** @@ -49,3 +59,12 @@ export function getCachedAccountStats(actorUrl) { return entry; } + +/** + * Reverse lookup: get actor URL from account hash ID. + * @param {string} hashId - The 24-char hex account ID + * @returns {string|null} Actor URL or null + */ +export function getActorUrlFromId(hashId) { + return idToUrl.get(hashId) || null; +} diff --git a/lib/mastodon/routes/accounts.js b/lib/mastodon/routes/accounts.js index a5cfb8e..66239cb 100644 --- a/lib/mastodon/routes/accounts.js +++ b/lib/mastodon/routes/accounts.js @@ -10,6 +10,7 @@ import { serializeStatus } from "../entities/status.js"; import { accountId, remoteActorId } from "../helpers/id-mapping.js"; import { buildPaginationQuery, parseLimit, setPaginationHeaders } from "../helpers/pagination.js"; import { resolveRemoteAccount } from "../helpers/resolve-account.js"; +import { getActorUrlFromId } from "../helpers/account-cache.js"; const router = express.Router(); // eslint-disable-line new-cap @@ -714,6 +715,10 @@ async function resolveActorUrl(id, collections) { return profile.url; } + // Check account cache reverse lookup (populated by resolveRemoteAccount) + const cachedUrl = getActorUrlFromId(id); + if (cachedUrl) return cachedUrl; + // Check followers const followers = await collections.ap_followers.find({}).toArray(); for (const f of followers) { diff --git a/package.json b/package.json index 36083ba..f9408b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rmdes/indiekit-endpoint-activitypub", - "version": "3.7.0", + "version": "3.7.1", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "keywords": [ "indiekit",