diff --git a/src/activitypub/Server.ts b/src/activitypub/Server.ts index c497d2e68..373d7390f 100644 --- a/src/activitypub/Server.ts +++ b/src/activitypub/Server.ts @@ -8,7 +8,8 @@ import { import { Request, Response, Router } from "express"; import { Server, ServerOptions } from "lambert-server"; import path from "path"; -import webfinger from "./webfinger"; +import hostMeta from "./well-known/host-meta"; +import webfinger from "./well-known/webfinger"; export class APServer extends Server { public declare options: ServerOptions; @@ -63,6 +64,7 @@ export class APServer extends Server { }); this.app.use("/.well-known/webfinger", webfinger); + this.app.use("/.well-known/host-meta", hostMeta); this.app.use(ErrorHandler); diff --git a/src/activitypub/routes/user.ts b/src/activitypub/routes/user.ts index 3366d7115..d68df4d18 100644 --- a/src/activitypub/routes/user.ts +++ b/src/activitypub/routes/user.ts @@ -1,6 +1,5 @@ import { route } from "@spacebar/api"; -import { Config, User } from "@spacebar/util"; -import { APPerson } from "activitypub-types"; +import { User } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -11,29 +10,5 @@ router.get("/:id", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ where: { id } }); - const { webDomain } = Config.get().federation; - - const ret: APPerson = { - "@context": "https://www.w3.org/ns/activitystreams", - type: "Person", - id: `https://${webDomain}/fed/user/${user.id}`, - name: user.username, - preferredUsername: user.username, - summary: user.bio, - icon: user.avatar - ? [ - `${Config.get().cdn.endpointPublic}/avatars/${user.id}/${ - user.avatar - }`, - ] - : undefined, - - inbox: `https://${webDomain}/fed/user/${user.id}/inbox`, - outbox: `https://${webDomain}/fed/user/${user.id}/outbox`, - followers: `https://${webDomain}/fed/user/${user.id}/followers`, - following: `https://${webDomain}/fed/user/${user.id}/following`, - liked: `https://${webDomain}/fed/user/${user.id}/likeds`, - }; - - return res.json(ret); + return res.json(user.toAP()); }); diff --git a/src/activitypub/well-known/host-meta.ts b/src/activitypub/well-known/host-meta.ts new file mode 100644 index 000000000..2de2014ce --- /dev/null +++ b/src/activitypub/well-known/host-meta.ts @@ -0,0 +1,20 @@ +import { route } from "@spacebar/api"; +import { Config } from "@spacebar/util"; +import { Request, Response, Router } from "express"; + +const router = Router(); +export default router; + +router.get("/", route({}), async (req: Request, res: Response) => { + res.setHeader("Content-Type", "application/xrd+xml"); + + const { webDomain } = Config.get().federation; + + const ret = ` + + + `; + + return res.send(ret); +}); diff --git a/src/activitypub/webfinger/index.ts b/src/activitypub/well-known/webfinger.ts similarity index 91% rename from src/activitypub/webfinger/index.ts rename to src/activitypub/well-known/webfinger.ts index f1b496244..c24a1477b 100644 --- a/src/activitypub/webfinger/index.ts +++ b/src/activitypub/well-known/webfinger.ts @@ -58,6 +58,10 @@ router.get( type: "application/activity+json", href: `https://${webDomain}/fed/${type}/${resourceId}`, }, + // { + // rel: "http://ostatus.org/schema/1.0/subscribe", + // href: `"https://${webDomain}/fed/authorize-follow?acct={uri}"`, + // }, ], }); }, diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index 93265d071..33528d906 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -500,8 +500,6 @@ export class Channel extends BaseClass { inbox: `https://${webDomain}/fed/channel/${this.id}/inbox`, outbox: `https://${webDomain}/fed/channel/${this.id}/outbox`, followers: `https://${webDomain}/fed/channel/${this.id}/followers`, - following: `https://${webDomain}/fed/channel/${this.id}/following`, - liked: `https://${webDomain}/fed/channel/${this.id}/likeds`, }; } } diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index c6582b00a..4263d39de 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import { APPerson } from "activitypub-types"; import { Request } from "express"; import { Column, @@ -271,6 +272,30 @@ export class User extends BaseClass { return user as UserPrivate; } + toAP(): APPerson { + const { webDomain } = Config.get().federation; + + return { + "@context": "https://www.w3.org/ns/activitystreams", + type: "Person", + id: `https://${webDomain}/fed/user/${user.id}`, + name: this.username, + preferredUsername: this.username, + summary: this.bio, + icon: this.avatar + ? [ + `${Config.get().cdn.endpointPublic}/avatars/${ + this.id + }/${this.avatar}`, + ] + : undefined, + + inbox: `https://${webDomain}/fed/user/${this.id}/inbox`, + outbox: `https://${webDomain}/fed/user/${this.id}/outbox`, + followers: `https://${webDomain}/fed/user/${this.id}/followers`, + }; + } + static async getPublicUser(user_id: string, opts?: FindOneOptions) { return await User.findOneOrFail({ where: { id: user_id }, diff --git a/src/util/schemas/responses/WebfingerResponse.ts b/src/util/schemas/responses/WebfingerResponse.ts index a3186a031..6b0ab0f9d 100644 --- a/src/util/schemas/responses/WebfingerResponse.ts +++ b/src/util/schemas/responses/WebfingerResponse.ts @@ -1,6 +1,6 @@ interface WebfingerLink { rel: string; - type: string; + type?: string; href: string; template?: string; }