Docs and helpers (#38)

* improve docs & helpers around publisher dids

* add docs to env
This commit is contained in:
Daniel Holmgren 2023-05-30 20:20:04 -05:00 committed by GitHub
parent e849ac7f66
commit cbdac3417e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 33 additions and 10 deletions

View File

@ -13,5 +13,10 @@ FEEDGEN_SUBSCRIPTION_ENDPOINT="wss://bsky.social"
# Set this to the hostname that you intend to run the service at # Set this to the hostname that you intend to run the service at
FEEDGEN_HOSTNAME="example.com" 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 # Only use this if you want a service did different from did:web
# FEEDGEN_SERVICE_DID="did:plc:abcde..." # FEEDGEN_SERVICE_DID="did:plc:abcde..."

View File

@ -1,10 +1,6 @@
# ATProto Feed Generator # ATProto Feed Generator
🚧 Work in Progress 🚧 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.
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!
## Overview ## 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. 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 ### 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`. 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`.

View File

@ -8,7 +8,7 @@ import * as whatsAlf from './whats-alf'
type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise<AlgoOutput> type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise<AlgoOutput>
const algos: Record<string, AlgoHandler> = { const algos: Record<string, AlgoHandler> = {
[whatsAlf.uri]: whatsAlf.handler, [whatsAlf.shortname]: whatsAlf.handler,
} }
export default algos export default algos

View File

@ -2,7 +2,8 @@ import { InvalidRequestError } from '@atproto/xrpc-server'
import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton'
import { AppContext } from '../config' 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) => { export const handler = async (ctx: AppContext, params: QueryParams) => {
let builder = ctx.db let builder = ctx.db

View File

@ -14,4 +14,5 @@ export type Config = {
sqliteLocation: string sqliteLocation: string
subscriptionEndpoint: string subscriptionEndpoint: string
serviceDid: string serviceDid: string
publisherDid: string
} }

View File

@ -13,6 +13,8 @@ const run = async () => {
subscriptionEndpoint: subscriptionEndpoint:
maybeStr(process.env.FEEDGEN_SUBSCRIPTION_ENDPOINT) ?? maybeStr(process.env.FEEDGEN_SUBSCRIPTION_ENDPOINT) ??
'wss://bsky.social', 'wss://bsky.social',
publisherDid:
maybeStr(process.env.FEEDGEN_PUBLISHER_DID) ?? 'did:example:alice',
hostname, hostname,
serviceDid, serviceDid,
}) })

View File

@ -1,10 +1,17 @@
import { Server } from '../lexicon' import { Server } from '../lexicon'
import { AppContext } from '../config' import { AppContext } from '../config'
import algos from '../algos' import algos from '../algos'
import { AtUri } from '@atproto/uri'
export default function (server: Server, ctx: AppContext) { export default function (server: Server, ctx: AppContext) {
server.app.bsky.feed.describeFeedGenerator(async () => { 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 { return {
encoding: 'application/json', encoding: 'application/json',
body: { body: {

View File

@ -3,11 +3,17 @@ import { Server } from '../lexicon'
import { AppContext } from '../config' import { AppContext } from '../config'
import algos from '../algos' import algos from '../algos'
import { validateAuth } from '../auth' import { validateAuth } from '../auth'
import { AtUri } from '@atproto/uri'
export default function (server: Server, ctx: AppContext) { export default function (server: Server, ctx: AppContext) {
server.app.bsky.feed.getFeedSkeleton(async ({ params, req }) => { server.app.bsky.feed.getFeedSkeleton(async ({ params, req }) => {
const algo = algos[params.feed] const feedUri = new AtUri(params.feed)
if (!algo) { const algo = algos[feedUri.rkey]
if (
feedUri.hostname !== ctx.cfg.publisherDid ||
feedUri.collection !== 'app.bsky.feed.generator' ||
!algo
) {
throw new InvalidRequestError( throw new InvalidRequestError(
'Unsupported algorithm', 'Unsupported algorithm',
'UnsupportedAlgorithm', 'UnsupportedAlgorithm',