mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
fix(mastodon-api): pass createdAt for follower/following accounts; URL-type AP lookup
- In accounts.js: all places that build an actor object from ap_followers or ap_following docs now include `createdAt: f.createdAt || undefined`. Previously the field was omitted, causing serializeAccount() to fall back to `new Date().toISOString()`, making every follower/following appear to have joined "just now" in the Mastodon client. Affected: GET /api/v1/accounts/:id/followers, /following, /lookup, and the resolveActorData() fallback used by GET /api/v1/accounts/:id. - In resolve-account.js: HTTP actor URLs are now passed to lookupWithSecurity() as a native URL object instead of a bare string, matching Fedify's preferred type. The acct:user@domain WebFinger path remains a string (new URL() would misparse the @ as a user-info separator under WHATWG rules). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,9 @@ export async function resolveRemoteAccount(acct, pluginOptions, baseUrl) {
|
||||
{ handle, publicationUrl },
|
||||
);
|
||||
|
||||
// Determine lookup URI
|
||||
// Determine lookup URI.
|
||||
// acct:user@domain — kept as a string; Fedify resolves it via WebFinger.
|
||||
// HTTP URLs — converted to URL objects for type-correct AP object fetch.
|
||||
let actorUri;
|
||||
if (acct.includes("@")) {
|
||||
const parts = acct.replace(/^@/, "").split("@");
|
||||
@@ -33,7 +35,7 @@ export async function resolveRemoteAccount(acct, pluginOptions, baseUrl) {
|
||||
if (!username || !domain) return null;
|
||||
actorUri = `acct:${username}@${domain}`;
|
||||
} else if (acct.startsWith("http")) {
|
||||
actorUri = acct;
|
||||
actorUri = new URL(acct);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ router.get("/api/v1/accounts/lookup", async (req, res, next) => {
|
||||
if (follower) {
|
||||
return res.json(
|
||||
serializeAccount(
|
||||
{ name: follower.name, url: follower.actorUrl, photo: follower.avatar, handle: follower.handle, bannerUrl: follower.banner || "" },
|
||||
{ name: follower.name, url: follower.actorUrl, photo: follower.avatar, handle: follower.handle, bannerUrl: follower.banner || "", createdAt: follower.createdAt || undefined },
|
||||
{ baseUrl },
|
||||
),
|
||||
);
|
||||
@@ -128,7 +128,7 @@ router.get("/api/v1/accounts/lookup", async (req, res, next) => {
|
||||
if (following) {
|
||||
return res.json(
|
||||
serializeAccount(
|
||||
{ name: following.name, url: following.actorUrl, photo: following.avatar, handle: following.handle },
|
||||
{ name: following.name, url: following.actorUrl, photo: following.avatar, handle: following.handle, createdAt: following.createdAt || undefined },
|
||||
{ baseUrl },
|
||||
),
|
||||
);
|
||||
@@ -396,7 +396,7 @@ router.get("/api/v1/accounts/:id/followers", async (req, res, next) => {
|
||||
|
||||
const accounts = followers.map((f) =>
|
||||
serializeAccount(
|
||||
{ name: f.name, url: f.actorUrl, photo: f.avatar, handle: f.handle, bannerUrl: f.banner || "" },
|
||||
{ name: f.name, url: f.actorUrl, photo: f.avatar, handle: f.handle, bannerUrl: f.banner || "", createdAt: f.createdAt || undefined },
|
||||
{ baseUrl },
|
||||
),
|
||||
);
|
||||
@@ -429,7 +429,7 @@ router.get("/api/v1/accounts/:id/following", async (req, res, next) => {
|
||||
|
||||
const accounts = following.map((f) =>
|
||||
serializeAccount(
|
||||
{ name: f.name, url: f.actorUrl, photo: f.avatar, handle: f.handle, bannerUrl: f.banner || "" },
|
||||
{ name: f.name, url: f.actorUrl, photo: f.avatar, handle: f.handle, bannerUrl: f.banner || "", createdAt: f.createdAt || undefined },
|
||||
{ baseUrl },
|
||||
),
|
||||
);
|
||||
@@ -786,6 +786,7 @@ async function resolveActorData(id, collections) {
|
||||
photo: f.avatar,
|
||||
handle: f.handle,
|
||||
bannerUrl: f.banner || "",
|
||||
createdAt: f.createdAt || undefined,
|
||||
},
|
||||
actorUrl: f.actorUrl,
|
||||
};
|
||||
@@ -803,6 +804,7 @@ async function resolveActorData(id, collections) {
|
||||
photo: f.avatar,
|
||||
handle: f.handle,
|
||||
bannerUrl: f.banner || "",
|
||||
createdAt: f.createdAt || undefined,
|
||||
},
|
||||
actorUrl: f.actorUrl,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user