From cbdac3417ee3f257e062b63640b474594d23fe5e Mon Sep 17 00:00:00 2001 From: Daniel Holmgren Date: Tue, 30 May 2023 20:20:04 -0500 Subject: [PATCH] Docs and helpers (#38) * improve docs & helpers around publisher dids * add docs to env --- .env.example | 5 +++++ README.md | 11 ++++++----- src/algos/index.ts | 2 +- src/algos/whats-alf.ts | 3 ++- src/config.ts | 1 + src/index.ts | 2 ++ src/methods/describe-generator.ts | 9 ++++++++- src/methods/feed-generation.ts | 10 ++++++++-- 8 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 49f71dc..5139bb5 100644 --- a/.env.example +++ b/.env.example @@ -13,5 +13,10 @@ FEEDGEN_SUBSCRIPTION_ENDPOINT="wss://bsky.social" # Set this to the hostname that you intend to run the service at FEEDGEN_HOSTNAME="example.com" +# Set this to the DID of the account you'll use to publish the feed +# You can find your accounts DID by going to +# https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=${YOUR_HANDLE} +FEEDGEN_PUBLISHER_DID="did:plc:abcde...." + # Only use this if you want a service did different from did:web # FEEDGEN_SERVICE_DID="did:plc:abcde..." \ No newline at end of file diff --git a/README.md b/README.md index 732c63e..a9f0dad 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # ATProto Feed Generator -🚧 Work in Progress 🚧 - -We are actively developing Feed Generator integration into the Bluesky Personal Data Server (PDS). Though we are reasonably confident about the general shape and interfaces laid out here, these interfaces and implementation details _are_ subject to change. - -In the meantime, we've put together this starter kit for devs. It doesn't do everything, but it should be enough to get you familiar with the system and started building! +This is a starter kit for creating ATProto Feed Generators. It's not feature complete, but should give you a good starting ground off of which to build and deploy a feed. ## Overview @@ -44,6 +40,11 @@ Next, you will need to do two things: We've taken care of setting this server up with a did:web. However, you're free to switch this out for did:plc if you like - you may want to if you expect this Feed Generator to be long-standing and possibly migrating domains. +### Deploying your feed +Your feed will need to be accessible at the value supplied to the `FEEDGEN_HOSTNAME` environment variable. + +The service must be set up to respond to HTTPS queries over port 443. + ### Publishing your feed To publish your feed, go to the script at `scripts/publishFeedGen.ts` and fill in the variables at the top. Examples are included, and some are optional. To publish your feed generator, simply run `yarn publishFeed`. diff --git a/src/algos/index.ts b/src/algos/index.ts index 910c0e9..b7ee48a 100644 --- a/src/algos/index.ts +++ b/src/algos/index.ts @@ -8,7 +8,7 @@ import * as whatsAlf from './whats-alf' type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise const algos: Record = { - [whatsAlf.uri]: whatsAlf.handler, + [whatsAlf.shortname]: whatsAlf.handler, } export default algos diff --git a/src/algos/whats-alf.ts b/src/algos/whats-alf.ts index 0afcadd..a131547 100644 --- a/src/algos/whats-alf.ts +++ b/src/algos/whats-alf.ts @@ -2,7 +2,8 @@ import { InvalidRequestError } from '@atproto/xrpc-server' import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' import { AppContext } from '../config' -export const uri = 'at://did:example:alice/app.bsky.feed.generator/whats-alf' +// max 15 chars +export const shortname = 'whats-alf' export const handler = async (ctx: AppContext, params: QueryParams) => { let builder = ctx.db diff --git a/src/config.ts b/src/config.ts index 98c22e6..3b521f7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -14,4 +14,5 @@ export type Config = { sqliteLocation: string subscriptionEndpoint: string serviceDid: string + publisherDid: string } diff --git a/src/index.ts b/src/index.ts index aa34a97..34c6107 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,8 @@ const run = async () => { subscriptionEndpoint: maybeStr(process.env.FEEDGEN_SUBSCRIPTION_ENDPOINT) ?? 'wss://bsky.social', + publisherDid: + maybeStr(process.env.FEEDGEN_PUBLISHER_DID) ?? 'did:example:alice', hostname, serviceDid, }) diff --git a/src/methods/describe-generator.ts b/src/methods/describe-generator.ts index 3155e4f..cbd87a8 100644 --- a/src/methods/describe-generator.ts +++ b/src/methods/describe-generator.ts @@ -1,10 +1,17 @@ import { Server } from '../lexicon' import { AppContext } from '../config' import algos from '../algos' +import { AtUri } from '@atproto/uri' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.describeFeedGenerator(async () => { - const feeds = Object.keys(algos).map((uri) => ({ uri })) + const feeds = Object.keys(algos).map((shortname) => ({ + uri: AtUri.make( + ctx.cfg.publisherDid, + 'app.bsky.feed.generator', + shortname, + ).toString(), + })) return { encoding: 'application/json', body: { diff --git a/src/methods/feed-generation.ts b/src/methods/feed-generation.ts index 0096a97..0e114ec 100644 --- a/src/methods/feed-generation.ts +++ b/src/methods/feed-generation.ts @@ -3,11 +3,17 @@ import { Server } from '../lexicon' import { AppContext } from '../config' import algos from '../algos' import { validateAuth } from '../auth' +import { AtUri } from '@atproto/uri' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getFeedSkeleton(async ({ params, req }) => { - const algo = algos[params.feed] - if (!algo) { + const feedUri = new AtUri(params.feed) + const algo = algos[feedUri.rkey] + if ( + feedUri.hostname !== ctx.cfg.publisherDid || + feedUri.collection !== 'app.bsky.feed.generator' || + !algo + ) { throw new InvalidRequestError( 'Unsupported algorithm', 'UnsupportedAlgorithm',