Fixed federation search
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
|
||||
import { fetchWebFinger, getActorUrlFromWebFinger } from './webfinger';
|
||||
|
||||
export interface ActivityPubProfile {
|
||||
id: string;
|
||||
type: string;
|
||||
preferredUsername: string;
|
||||
name?: string;
|
||||
summary?: string;
|
||||
url?: string;
|
||||
icon?: {
|
||||
url: string;
|
||||
} | string;
|
||||
image?: {
|
||||
url: string;
|
||||
} | string;
|
||||
publicKey?: {
|
||||
id: string;
|
||||
owner: string;
|
||||
publicKeyPem: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a remote ActivityPub actor
|
||||
*/
|
||||
export async function fetchRemoteActor(url: string): Promise<ActivityPubProfile | null> {
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'User-Agent': 'Synapsis/1.0 (+https://synapsis.social)',
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.error(`Failed to fetch actor: ${res.status} ${res.statusText}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
// Basic validation
|
||||
if (!data.id || !data.type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data as ActivityPubProfile;
|
||||
} catch (error) {
|
||||
console.error('Error fetching remote actor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a remote user via WebFinger and fetch their profile
|
||||
* @param handle The username (without domain)
|
||||
* @param domain The domain name
|
||||
*/
|
||||
export async function resolveRemoteUser(handle: string, domain: string): Promise<ActivityPubProfile | null> {
|
||||
// 1. WebFinger lookup
|
||||
const webfinger = await fetchWebFinger(handle, domain);
|
||||
if (!webfinger) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. Get Actor URL
|
||||
const actorUrl = getActorUrlFromWebFinger(webfinger);
|
||||
if (!actorUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. Fetch Actor Profile
|
||||
return await fetchRemoteActor(actorUrl);
|
||||
}
|
||||
@@ -106,8 +106,11 @@ export async function fetchWebFinger(
|
||||
* Get the ActivityPub actor URL from a WebFinger response
|
||||
*/
|
||||
export function getActorUrlFromWebFinger(webfinger: WebFingerResponse): string | null {
|
||||
const selfLink = webfinger.links.find(
|
||||
(link) => link.rel === 'self' && link.type === 'application/activity+json'
|
||||
);
|
||||
const selfLink = webfinger.links.find((link) => {
|
||||
if (link.rel !== 'self' || !link.href) return false;
|
||||
if (!link.type) return true;
|
||||
const type = link.type.toLowerCase();
|
||||
return type.includes('activity+json') || type.includes('activitystreams') || type.includes('application/ld+json');
|
||||
});
|
||||
return selfLink?.href ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user