Add describeFeedGenerator route + multiple feeds (#19)
* describeFeedGenerator route + multiple feeds * tweak readme
This commit is contained in:
parent
285ef14a68
commit
3606414b79
@ -36,11 +36,11 @@ Next you will need to do two things:
|
|||||||
|
|
||||||
This will subscribe to the repo subscription stream on startup, parse events & index them according to your provided logic.
|
This will subscribe to the repo subscription stream on startup, parse events & index them according to your provided logic.
|
||||||
|
|
||||||
2. Implement feed generation logic in `src/feed-generation.ts`
|
2. Implement feed generation logic in `src/algos`
|
||||||
|
|
||||||
The types are in place and you will just need to return something that satisfies the `SkeletonFeedPost[]` type.
|
|
||||||
|
|
||||||
For inspiration, we've provided a very simple feed algorithm ("whats alf") that returns all posts related to the titular character of the TV show ALF.
|
For inspiration, we've provided a very simple feed algorithm (`whats-alf`) that returns all posts related to the titular character of the TV show ALF.
|
||||||
|
|
||||||
|
You can either edit it or add another algorithm alongside it. The types are in place an dyou will just need to return something that satisfies the `SkeletonFeedPost[]` type.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
14
src/algos/index.ts
Normal file
14
src/algos/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { AppContext } from '../config'
|
||||||
|
import {
|
||||||
|
QueryParams,
|
||||||
|
OutputSchema as AlgoOutput,
|
||||||
|
} from '../lexicon/types/app/bsky/feed/getFeedSkeleton'
|
||||||
|
import * as whatsAlf from './whats-alf'
|
||||||
|
|
||||||
|
type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise<AlgoOutput>
|
||||||
|
|
||||||
|
const algos: Record<string, AlgoHandler> = {
|
||||||
|
[whatsAlf.uri]: whatsAlf.handler,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default algos
|
42
src/algos/whats-alf.ts
Normal file
42
src/algos/whats-alf.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
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'
|
||||||
|
|
||||||
|
export const handler = async (ctx: AppContext, params: QueryParams) => {
|
||||||
|
let builder = ctx.db
|
||||||
|
.selectFrom('post')
|
||||||
|
.selectAll()
|
||||||
|
.orderBy('indexedAt', 'desc')
|
||||||
|
.orderBy('cid', 'desc')
|
||||||
|
.limit(params.limit)
|
||||||
|
|
||||||
|
if (params.cursor) {
|
||||||
|
const [indexedAt, cid] = params.cursor.split('::')
|
||||||
|
if (!indexedAt || !cid) {
|
||||||
|
throw new InvalidRequestError('malformed cursor')
|
||||||
|
}
|
||||||
|
const timeStr = new Date(parseInt(indexedAt, 10)).toISOString()
|
||||||
|
builder = builder
|
||||||
|
.where('post.indexedAt', '<', timeStr)
|
||||||
|
.orWhere((qb) => qb.where('post.indexedAt', '=', timeStr))
|
||||||
|
.where('post.cid', '<', cid)
|
||||||
|
}
|
||||||
|
const res = await builder.execute()
|
||||||
|
|
||||||
|
const feed = res.map((row) => ({
|
||||||
|
post: row.uri,
|
||||||
|
}))
|
||||||
|
|
||||||
|
let cursor: string | undefined
|
||||||
|
const last = res.at(-1)
|
||||||
|
if (last) {
|
||||||
|
cursor = `${new Date(last.indexedAt).getTime()}::${last.cid}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
cursor,
|
||||||
|
feed,
|
||||||
|
}
|
||||||
|
}
|
@ -1,64 +0,0 @@
|
|||||||
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
||||||
import { Server } from './lexicon'
|
|
||||||
import { AppContext } from './config'
|
|
||||||
import { validateAuth } from './auth'
|
|
||||||
|
|
||||||
export default function (server: Server, ctx: AppContext) {
|
|
||||||
server.app.bsky.feed.getFeedSkeleton(async ({ params, req }) => {
|
|
||||||
if (
|
|
||||||
params.feed !== 'at://did:example:alice/app.bsky.feed.generator/whats-alf'
|
|
||||||
) {
|
|
||||||
throw new InvalidRequestError(
|
|
||||||
'Unsupported algorithm',
|
|
||||||
'UnsupportedAlgorithm',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Example of how to check auth if giving user-specific results:
|
|
||||||
*
|
|
||||||
* const requesterDid = await validateAuth(
|
|
||||||
* req,
|
|
||||||
* ctx.cfg.serviceDid,
|
|
||||||
* ctx.didResolver,
|
|
||||||
* )
|
|
||||||
*/
|
|
||||||
|
|
||||||
let builder = ctx.db
|
|
||||||
.selectFrom('post')
|
|
||||||
.selectAll()
|
|
||||||
.orderBy('indexedAt', 'desc')
|
|
||||||
.orderBy('cid', 'desc')
|
|
||||||
.limit(params.limit)
|
|
||||||
|
|
||||||
if (params.cursor) {
|
|
||||||
const [indexedAt, cid] = params.cursor.split('::')
|
|
||||||
if (!indexedAt || !cid) {
|
|
||||||
throw new InvalidRequestError('malformed cursor')
|
|
||||||
}
|
|
||||||
const timeStr = new Date(parseInt(indexedAt, 10)).toISOString()
|
|
||||||
builder = builder
|
|
||||||
.where('post.indexedAt', '<', timeStr)
|
|
||||||
.orWhere((qb) => qb.where('post.indexedAt', '=', timeStr))
|
|
||||||
.where('post.cid', '<', cid)
|
|
||||||
}
|
|
||||||
const res = await builder.execute()
|
|
||||||
|
|
||||||
const feed = res.map((row) => ({
|
|
||||||
post: row.uri,
|
|
||||||
}))
|
|
||||||
|
|
||||||
let cursor: string | undefined
|
|
||||||
const last = res.at(-1)
|
|
||||||
if (last) {
|
|
||||||
cursor = `${new Date(last.indexedAt).getTime()}::${last.cid}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
encoding: 'application/json',
|
|
||||||
body: {
|
|
||||||
cursor,
|
|
||||||
feed,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -67,23 +67,27 @@ import * as ComAtprotoSyncListRepos from './types/com/atproto/sync/listRepos'
|
|||||||
import * as ComAtprotoSyncNotifyOfUpdate from './types/com/atproto/sync/notifyOfUpdate'
|
import * as ComAtprotoSyncNotifyOfUpdate from './types/com/atproto/sync/notifyOfUpdate'
|
||||||
import * as ComAtprotoSyncRequestCrawl from './types/com/atproto/sync/requestCrawl'
|
import * as ComAtprotoSyncRequestCrawl from './types/com/atproto/sync/requestCrawl'
|
||||||
import * as ComAtprotoSyncSubscribeRepos from './types/com/atproto/sync/subscribeRepos'
|
import * as ComAtprotoSyncSubscribeRepos from './types/com/atproto/sync/subscribeRepos'
|
||||||
|
import * as AppBskyActorGetPreferences from './types/app/bsky/actor/getPreferences'
|
||||||
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile'
|
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile'
|
||||||
import * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles'
|
import * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles'
|
||||||
import * as AppBskyActorGetSuggestions from './types/app/bsky/actor/getSuggestions'
|
import * as AppBskyActorGetSuggestions from './types/app/bsky/actor/getSuggestions'
|
||||||
|
import * as AppBskyActorPutPreferences from './types/app/bsky/actor/putPreferences'
|
||||||
import * as AppBskyActorSearchActors from './types/app/bsky/actor/searchActors'
|
import * as AppBskyActorSearchActors from './types/app/bsky/actor/searchActors'
|
||||||
import * as AppBskyActorSearchActorsTypeahead from './types/app/bsky/actor/searchActorsTypeahead'
|
import * as AppBskyActorSearchActorsTypeahead from './types/app/bsky/actor/searchActorsTypeahead'
|
||||||
import * as AppBskyFeedBookmarkFeed from './types/app/bsky/feed/bookmarkFeed'
|
import * as AppBskyFeedDescribeFeedGenerator from './types/app/bsky/feed/describeFeedGenerator'
|
||||||
import * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds'
|
import * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds'
|
||||||
import * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed'
|
import * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed'
|
||||||
import * as AppBskyFeedGetBookmarkedFeeds from './types/app/bsky/feed/getBookmarkedFeeds'
|
|
||||||
import * as AppBskyFeedGetFeed from './types/app/bsky/feed/getFeed'
|
import * as AppBskyFeedGetFeed from './types/app/bsky/feed/getFeed'
|
||||||
|
import * as AppBskyFeedGetFeedGenerator from './types/app/bsky/feed/getFeedGenerator'
|
||||||
import * as AppBskyFeedGetFeedSkeleton from './types/app/bsky/feed/getFeedSkeleton'
|
import * as AppBskyFeedGetFeedSkeleton from './types/app/bsky/feed/getFeedSkeleton'
|
||||||
import * as AppBskyFeedGetLikes from './types/app/bsky/feed/getLikes'
|
import * as AppBskyFeedGetLikes from './types/app/bsky/feed/getLikes'
|
||||||
import * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread'
|
import * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread'
|
||||||
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts'
|
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts'
|
||||||
import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy'
|
import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy'
|
||||||
|
import * as AppBskyFeedGetSavedFeeds from './types/app/bsky/feed/getSavedFeeds'
|
||||||
import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline'
|
import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline'
|
||||||
import * as AppBskyFeedUnbookmarkFeed from './types/app/bsky/feed/unbookmarkFeed'
|
import * as AppBskyFeedSaveFeed from './types/app/bsky/feed/saveFeed'
|
||||||
|
import * as AppBskyFeedUnsaveFeed from './types/app/bsky/feed/unsaveFeed'
|
||||||
import * as AppBskyGraphGetBlocks from './types/app/bsky/graph/getBlocks'
|
import * as AppBskyGraphGetBlocks from './types/app/bsky/graph/getBlocks'
|
||||||
import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers'
|
import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers'
|
||||||
import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows'
|
import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows'
|
||||||
@ -730,6 +734,13 @@ export class ActorNS {
|
|||||||
this._server = server
|
this._server = server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPreferences<AV extends AuthVerifier>(
|
||||||
|
cfg: ConfigOf<AV, AppBskyActorGetPreferences.Handler<ExtractAuth<AV>>>,
|
||||||
|
) {
|
||||||
|
const nsid = 'app.bsky.actor.getPreferences' // @ts-ignore
|
||||||
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
getProfile<AV extends AuthVerifier>(
|
getProfile<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyActorGetProfile.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyActorGetProfile.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
@ -751,6 +762,13 @@ export class ActorNS {
|
|||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
putPreferences<AV extends AuthVerifier>(
|
||||||
|
cfg: ConfigOf<AV, AppBskyActorPutPreferences.Handler<ExtractAuth<AV>>>,
|
||||||
|
) {
|
||||||
|
const nsid = 'app.bsky.actor.putPreferences' // @ts-ignore
|
||||||
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
searchActors<AV extends AuthVerifier>(
|
searchActors<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyActorSearchActors.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyActorSearchActors.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
@ -784,10 +802,13 @@ export class FeedNS {
|
|||||||
this._server = server
|
this._server = server
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkFeed<AV extends AuthVerifier>(
|
describeFeedGenerator<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyFeedBookmarkFeed.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<
|
||||||
|
AV,
|
||||||
|
AppBskyFeedDescribeFeedGenerator.Handler<ExtractAuth<AV>>
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
const nsid = 'app.bsky.feed.bookmarkFeed' // @ts-ignore
|
const nsid = 'app.bsky.feed.describeFeedGenerator' // @ts-ignore
|
||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,13 +826,6 @@ export class FeedNS {
|
|||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
getBookmarkedFeeds<AV extends AuthVerifier>(
|
|
||||||
cfg: ConfigOf<AV, AppBskyFeedGetBookmarkedFeeds.Handler<ExtractAuth<AV>>>,
|
|
||||||
) {
|
|
||||||
const nsid = 'app.bsky.feed.getBookmarkedFeeds' // @ts-ignore
|
|
||||||
return this._server.xrpc.method(nsid, cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
getFeed<AV extends AuthVerifier>(
|
getFeed<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyFeedGetFeed.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyFeedGetFeed.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
@ -819,6 +833,13 @@ export class FeedNS {
|
|||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFeedGenerator<AV extends AuthVerifier>(
|
||||||
|
cfg: ConfigOf<AV, AppBskyFeedGetFeedGenerator.Handler<ExtractAuth<AV>>>,
|
||||||
|
) {
|
||||||
|
const nsid = 'app.bsky.feed.getFeedGenerator' // @ts-ignore
|
||||||
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
getFeedSkeleton<AV extends AuthVerifier>(
|
getFeedSkeleton<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyFeedGetFeedSkeleton.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyFeedGetFeedSkeleton.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
@ -854,6 +875,13 @@ export class FeedNS {
|
|||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSavedFeeds<AV extends AuthVerifier>(
|
||||||
|
cfg: ConfigOf<AV, AppBskyFeedGetSavedFeeds.Handler<ExtractAuth<AV>>>,
|
||||||
|
) {
|
||||||
|
const nsid = 'app.bsky.feed.getSavedFeeds' // @ts-ignore
|
||||||
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
getTimeline<AV extends AuthVerifier>(
|
getTimeline<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyFeedGetTimeline.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyFeedGetTimeline.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
@ -861,10 +889,17 @@ export class FeedNS {
|
|||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
unbookmarkFeed<AV extends AuthVerifier>(
|
saveFeed<AV extends AuthVerifier>(
|
||||||
cfg: ConfigOf<AV, AppBskyFeedUnbookmarkFeed.Handler<ExtractAuth<AV>>>,
|
cfg: ConfigOf<AV, AppBskyFeedSaveFeed.Handler<ExtractAuth<AV>>>,
|
||||||
) {
|
) {
|
||||||
const nsid = 'app.bsky.feed.unbookmarkFeed' // @ts-ignore
|
const nsid = 'app.bsky.feed.saveFeed' // @ts-ignore
|
||||||
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsaveFeed<AV extends AuthVerifier>(
|
||||||
|
cfg: ConfigOf<AV, AppBskyFeedUnsaveFeed.Handler<ExtractAuth<AV>>>,
|
||||||
|
) {
|
||||||
|
const nsid = 'app.bsky.feed.unsaveFeed' // @ts-ignore
|
||||||
return this._server.xrpc.method(nsid, cfg)
|
return this._server.xrpc.method(nsid, cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,6 +835,15 @@ export const schemaDict = {
|
|||||||
resolved: {
|
resolved: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
},
|
},
|
||||||
|
actionType: {
|
||||||
|
type: 'string',
|
||||||
|
knownValues: [
|
||||||
|
'com.atproto.admin.defs#takedown',
|
||||||
|
'com.atproto.admin.defs#flag',
|
||||||
|
'com.atproto.admin.defs#acknowledge',
|
||||||
|
'com.atproto.admin.defs#escalate',
|
||||||
|
],
|
||||||
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
minimum: 1,
|
minimum: 1,
|
||||||
@ -2114,6 +2123,10 @@ export const schemaDict = {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'handle',
|
format: 'handle',
|
||||||
},
|
},
|
||||||
|
did: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'did',
|
||||||
|
},
|
||||||
inviteCode: {
|
inviteCode: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
},
|
},
|
||||||
@ -2165,6 +2178,12 @@ export const schemaDict = {
|
|||||||
{
|
{
|
||||||
name: 'UnsupportedDomain',
|
name: 'UnsupportedDomain',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'UnresolvableDid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'IncompatibleDidDoc',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -3509,6 +3528,66 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
preferences: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'union',
|
||||||
|
refs: [
|
||||||
|
'lex:app.bsky.actor.defs#adultContentPref',
|
||||||
|
'lex:app.bsky.actor.defs#contentLabelPref',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
adultContentPref: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['enabled'],
|
||||||
|
properties: {
|
||||||
|
enabled: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contentLabelPref: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label', 'visibility'],
|
||||||
|
properties: {
|
||||||
|
label: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
visibility: {
|
||||||
|
type: 'string',
|
||||||
|
knownValues: ['show', 'warn', 'hide'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AppBskyActorGetPreferences: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.actor.getPreferences',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'query',
|
||||||
|
description: 'Get private preferences attached to the account.',
|
||||||
|
parameters: {
|
||||||
|
type: 'params',
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['preferences'],
|
||||||
|
properties: {
|
||||||
|
preferences: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.actor.defs#preferences',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AppBskyActorGetProfile: {
|
AppBskyActorGetProfile: {
|
||||||
@ -3655,6 +3734,29 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AppBskyActorPutPreferences: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.actor.putPreferences',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'procedure',
|
||||||
|
description: 'Sets the private preferences attached to the account.',
|
||||||
|
input: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['preferences'],
|
||||||
|
properties: {
|
||||||
|
preferences: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.actor.defs#preferences',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
AppBskyActorSearchActors: {
|
AppBskyActorSearchActors: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.actor.searchActors',
|
id: 'app.bsky.actor.searchActors',
|
||||||
@ -3899,6 +4001,7 @@ export const schemaDict = {
|
|||||||
'lex:app.bsky.embed.record#viewRecord',
|
'lex:app.bsky.embed.record#viewRecord',
|
||||||
'lex:app.bsky.embed.record#viewNotFound',
|
'lex:app.bsky.embed.record#viewNotFound',
|
||||||
'lex:app.bsky.embed.record#viewBlocked',
|
'lex:app.bsky.embed.record#viewBlocked',
|
||||||
|
'lex:app.bsky.feed.defs#generatorView',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4008,29 +4111,6 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AppBskyFeedBookmarkFeed: {
|
|
||||||
lexicon: 1,
|
|
||||||
id: 'app.bsky.feed.bookmarkFeed',
|
|
||||||
defs: {
|
|
||||||
main: {
|
|
||||||
type: 'procedure',
|
|
||||||
description: 'Bookmark a 3rd party feed for use across clients',
|
|
||||||
input: {
|
|
||||||
encoding: 'application/json',
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
required: ['feed'],
|
|
||||||
properties: {
|
|
||||||
feed: {
|
|
||||||
type: 'string',
|
|
||||||
format: 'at-uri',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppBskyFeedDefs: {
|
AppBskyFeedDefs: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.feed.defs',
|
id: 'app.bsky.feed.defs',
|
||||||
@ -4215,12 +4295,16 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
generatorView: {
|
generatorView: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
required: ['uri', 'creator', 'indexedAt'],
|
required: ['uri', 'cid', 'creator', 'indexedAt'],
|
||||||
properties: {
|
properties: {
|
||||||
uri: {
|
uri: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'at-uri',
|
format: 'at-uri',
|
||||||
},
|
},
|
||||||
|
cid: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'cid',
|
||||||
|
},
|
||||||
did: {
|
did: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'did',
|
format: 'did',
|
||||||
@ -4247,6 +4331,10 @@ export const schemaDict = {
|
|||||||
avatar: {
|
avatar: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
},
|
},
|
||||||
|
likeCount: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 0,
|
||||||
|
},
|
||||||
viewer: {
|
viewer: {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
ref: 'lex:app.bsky.feed.defs#generatorViewerState',
|
ref: 'lex:app.bsky.feed.defs#generatorViewerState',
|
||||||
@ -4260,7 +4348,7 @@ export const schemaDict = {
|
|||||||
generatorViewerState: {
|
generatorViewerState: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
subscribed: {
|
saved: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
},
|
},
|
||||||
like: {
|
like: {
|
||||||
@ -4295,6 +4383,62 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AppBskyFeedDescribeFeedGenerator: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.feed.describeFeedGenerator',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'query',
|
||||||
|
description:
|
||||||
|
'Returns information about a given feed generator including TOS & offered feed URIs',
|
||||||
|
output: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['did', 'feeds'],
|
||||||
|
properties: {
|
||||||
|
did: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'did',
|
||||||
|
},
|
||||||
|
feeds: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.feed.describeFeedGenerator#feed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.feed.describeFeedGenerator#links',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
feed: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['uri'],
|
||||||
|
properties: {
|
||||||
|
uri: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'at-uri',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
privacyPolicy: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
termsOfService: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
AppBskyFeedGenerator: {
|
AppBskyFeedGenerator: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.feed.generator',
|
id: 'app.bsky.feed.generator',
|
||||||
@ -4446,50 +4590,6 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AppBskyFeedGetBookmarkedFeeds: {
|
|
||||||
lexicon: 1,
|
|
||||||
id: 'app.bsky.feed.getBookmarkedFeeds',
|
|
||||||
defs: {
|
|
||||||
main: {
|
|
||||||
type: 'query',
|
|
||||||
description:
|
|
||||||
"Retrieve a list of the authenticated user's bookmarked feeds",
|
|
||||||
parameters: {
|
|
||||||
type: 'params',
|
|
||||||
properties: {
|
|
||||||
limit: {
|
|
||||||
type: 'integer',
|
|
||||||
minimum: 1,
|
|
||||||
maximum: 100,
|
|
||||||
default: 50,
|
|
||||||
},
|
|
||||||
cursor: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
encoding: 'application/json',
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
required: ['feeds'],
|
|
||||||
properties: {
|
|
||||||
cursor: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
feeds: {
|
|
||||||
type: 'array',
|
|
||||||
items: {
|
|
||||||
type: 'ref',
|
|
||||||
ref: 'lex:app.bsky.feed.defs#generatorView',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
AppBskyFeedGetFeed: {
|
AppBskyFeedGetFeed: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.feed.getFeed',
|
id: 'app.bsky.feed.getFeed',
|
||||||
@ -4536,6 +4636,51 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
name: 'UnknownFeed',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AppBskyFeedGetFeedGenerator: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.feed.getFeedGenerator',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'query',
|
||||||
|
description:
|
||||||
|
'Get information about a specific feed offered by a feed generator, such as its online status',
|
||||||
|
parameters: {
|
||||||
|
type: 'params',
|
||||||
|
required: ['feed'],
|
||||||
|
properties: {
|
||||||
|
feed: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'at-uri',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['view', 'isOnline', 'isValid'],
|
||||||
|
properties: {
|
||||||
|
view: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.feed.defs#generatorView',
|
||||||
|
},
|
||||||
|
isOnline: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
isValid: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4584,6 +4729,11 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
name: 'UnknownFeed',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4807,6 +4957,49 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AppBskyFeedGetSavedFeeds: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.feed.getSavedFeeds',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'query',
|
||||||
|
description: "Retrieve a list of the authenticated user's saved feeds",
|
||||||
|
parameters: {
|
||||||
|
type: 'params',
|
||||||
|
properties: {
|
||||||
|
limit: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 100,
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
cursor: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['feeds'],
|
||||||
|
properties: {
|
||||||
|
cursor: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
feeds: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'ref',
|
||||||
|
ref: 'lex:app.bsky.feed.defs#generatorView',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
AppBskyFeedGetTimeline: {
|
AppBskyFeedGetTimeline: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.feed.getTimeline',
|
id: 'app.bsky.feed.getTimeline',
|
||||||
@ -5002,13 +5195,36 @@ export const schemaDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AppBskyFeedUnbookmarkFeed: {
|
AppBskyFeedSaveFeed: {
|
||||||
lexicon: 1,
|
lexicon: 1,
|
||||||
id: 'app.bsky.feed.unbookmarkFeed',
|
id: 'app.bsky.feed.saveFeed',
|
||||||
defs: {
|
defs: {
|
||||||
main: {
|
main: {
|
||||||
type: 'procedure',
|
type: 'procedure',
|
||||||
description: 'Remove a bookmark for a 3rd party feed',
|
description: 'Save a 3rd party feed for use across clients',
|
||||||
|
input: {
|
||||||
|
encoding: 'application/json',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['feed'],
|
||||||
|
properties: {
|
||||||
|
feed: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'at-uri',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AppBskyFeedUnsaveFeed: {
|
||||||
|
lexicon: 1,
|
||||||
|
id: 'app.bsky.feed.unsaveFeed',
|
||||||
|
defs: {
|
||||||
|
main: {
|
||||||
|
type: 'procedure',
|
||||||
|
description: 'Unsave a 3rd party feed',
|
||||||
input: {
|
input: {
|
||||||
encoding: 'application/json',
|
encoding: 'application/json',
|
||||||
schema: {
|
schema: {
|
||||||
@ -6029,33 +6245,37 @@ export const ids = {
|
|||||||
ComAtprotoSyncRequestCrawl: 'com.atproto.sync.requestCrawl',
|
ComAtprotoSyncRequestCrawl: 'com.atproto.sync.requestCrawl',
|
||||||
ComAtprotoSyncSubscribeRepos: 'com.atproto.sync.subscribeRepos',
|
ComAtprotoSyncSubscribeRepos: 'com.atproto.sync.subscribeRepos',
|
||||||
AppBskyActorDefs: 'app.bsky.actor.defs',
|
AppBskyActorDefs: 'app.bsky.actor.defs',
|
||||||
|
AppBskyActorGetPreferences: 'app.bsky.actor.getPreferences',
|
||||||
AppBskyActorGetProfile: 'app.bsky.actor.getProfile',
|
AppBskyActorGetProfile: 'app.bsky.actor.getProfile',
|
||||||
AppBskyActorGetProfiles: 'app.bsky.actor.getProfiles',
|
AppBskyActorGetProfiles: 'app.bsky.actor.getProfiles',
|
||||||
AppBskyActorGetSuggestions: 'app.bsky.actor.getSuggestions',
|
AppBskyActorGetSuggestions: 'app.bsky.actor.getSuggestions',
|
||||||
AppBskyActorProfile: 'app.bsky.actor.profile',
|
AppBskyActorProfile: 'app.bsky.actor.profile',
|
||||||
|
AppBskyActorPutPreferences: 'app.bsky.actor.putPreferences',
|
||||||
AppBskyActorSearchActors: 'app.bsky.actor.searchActors',
|
AppBskyActorSearchActors: 'app.bsky.actor.searchActors',
|
||||||
AppBskyActorSearchActorsTypeahead: 'app.bsky.actor.searchActorsTypeahead',
|
AppBskyActorSearchActorsTypeahead: 'app.bsky.actor.searchActorsTypeahead',
|
||||||
AppBskyEmbedExternal: 'app.bsky.embed.external',
|
AppBskyEmbedExternal: 'app.bsky.embed.external',
|
||||||
AppBskyEmbedImages: 'app.bsky.embed.images',
|
AppBskyEmbedImages: 'app.bsky.embed.images',
|
||||||
AppBskyEmbedRecord: 'app.bsky.embed.record',
|
AppBskyEmbedRecord: 'app.bsky.embed.record',
|
||||||
AppBskyEmbedRecordWithMedia: 'app.bsky.embed.recordWithMedia',
|
AppBskyEmbedRecordWithMedia: 'app.bsky.embed.recordWithMedia',
|
||||||
AppBskyFeedBookmarkFeed: 'app.bsky.feed.bookmarkFeed',
|
|
||||||
AppBskyFeedDefs: 'app.bsky.feed.defs',
|
AppBskyFeedDefs: 'app.bsky.feed.defs',
|
||||||
|
AppBskyFeedDescribeFeedGenerator: 'app.bsky.feed.describeFeedGenerator',
|
||||||
AppBskyFeedGenerator: 'app.bsky.feed.generator',
|
AppBskyFeedGenerator: 'app.bsky.feed.generator',
|
||||||
AppBskyFeedGetActorFeeds: 'app.bsky.feed.getActorFeeds',
|
AppBskyFeedGetActorFeeds: 'app.bsky.feed.getActorFeeds',
|
||||||
AppBskyFeedGetAuthorFeed: 'app.bsky.feed.getAuthorFeed',
|
AppBskyFeedGetAuthorFeed: 'app.bsky.feed.getAuthorFeed',
|
||||||
AppBskyFeedGetBookmarkedFeeds: 'app.bsky.feed.getBookmarkedFeeds',
|
|
||||||
AppBskyFeedGetFeed: 'app.bsky.feed.getFeed',
|
AppBskyFeedGetFeed: 'app.bsky.feed.getFeed',
|
||||||
|
AppBskyFeedGetFeedGenerator: 'app.bsky.feed.getFeedGenerator',
|
||||||
AppBskyFeedGetFeedSkeleton: 'app.bsky.feed.getFeedSkeleton',
|
AppBskyFeedGetFeedSkeleton: 'app.bsky.feed.getFeedSkeleton',
|
||||||
AppBskyFeedGetLikes: 'app.bsky.feed.getLikes',
|
AppBskyFeedGetLikes: 'app.bsky.feed.getLikes',
|
||||||
AppBskyFeedGetPostThread: 'app.bsky.feed.getPostThread',
|
AppBskyFeedGetPostThread: 'app.bsky.feed.getPostThread',
|
||||||
AppBskyFeedGetPosts: 'app.bsky.feed.getPosts',
|
AppBskyFeedGetPosts: 'app.bsky.feed.getPosts',
|
||||||
AppBskyFeedGetRepostedBy: 'app.bsky.feed.getRepostedBy',
|
AppBskyFeedGetRepostedBy: 'app.bsky.feed.getRepostedBy',
|
||||||
|
AppBskyFeedGetSavedFeeds: 'app.bsky.feed.getSavedFeeds',
|
||||||
AppBskyFeedGetTimeline: 'app.bsky.feed.getTimeline',
|
AppBskyFeedGetTimeline: 'app.bsky.feed.getTimeline',
|
||||||
AppBskyFeedLike: 'app.bsky.feed.like',
|
AppBskyFeedLike: 'app.bsky.feed.like',
|
||||||
AppBskyFeedPost: 'app.bsky.feed.post',
|
AppBskyFeedPost: 'app.bsky.feed.post',
|
||||||
AppBskyFeedRepost: 'app.bsky.feed.repost',
|
AppBskyFeedRepost: 'app.bsky.feed.repost',
|
||||||
AppBskyFeedUnbookmarkFeed: 'app.bsky.feed.unbookmarkFeed',
|
AppBskyFeedSaveFeed: 'app.bsky.feed.saveFeed',
|
||||||
|
AppBskyFeedUnsaveFeed: 'app.bsky.feed.unsaveFeed',
|
||||||
AppBskyGraphBlock: 'app.bsky.graph.block',
|
AppBskyGraphBlock: 'app.bsky.graph.block',
|
||||||
AppBskyGraphDefs: 'app.bsky.graph.defs',
|
AppBskyGraphDefs: 'app.bsky.graph.defs',
|
||||||
AppBskyGraphFollow: 'app.bsky.graph.follow',
|
AppBskyGraphFollow: 'app.bsky.graph.follow',
|
||||||
|
@ -103,3 +103,44 @@ export function isViewerState(v: unknown): v is ViewerState {
|
|||||||
export function validateViewerState(v: unknown): ValidationResult {
|
export function validateViewerState(v: unknown): ValidationResult {
|
||||||
return lexicons.validate('app.bsky.actor.defs#viewerState', v)
|
return lexicons.validate('app.bsky.actor.defs#viewerState', v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Preferences = (
|
||||||
|
| AdultContentPref
|
||||||
|
| ContentLabelPref
|
||||||
|
| { $type: string; [k: string]: unknown }
|
||||||
|
)[]
|
||||||
|
|
||||||
|
export interface AdultContentPref {
|
||||||
|
enabled: boolean
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isAdultContentPref(v: unknown): v is AdultContentPref {
|
||||||
|
return (
|
||||||
|
isObj(v) &&
|
||||||
|
hasProp(v, '$type') &&
|
||||||
|
v.$type === 'app.bsky.actor.defs#adultContentPref'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateAdultContentPref(v: unknown): ValidationResult {
|
||||||
|
return lexicons.validate('app.bsky.actor.defs#adultContentPref', v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentLabelPref {
|
||||||
|
label: string
|
||||||
|
visibility: 'show' | 'warn' | 'hide' | (string & {})
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isContentLabelPref(v: unknown): v is ContentLabelPref {
|
||||||
|
return (
|
||||||
|
isObj(v) &&
|
||||||
|
hasProp(v, '$type') &&
|
||||||
|
v.$type === 'app.bsky.actor.defs#contentLabelPref'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateContentLabelPref(v: unknown): ValidationResult {
|
||||||
|
return lexicons.validate('app.bsky.actor.defs#contentLabelPref', v)
|
||||||
|
}
|
||||||
|
40
src/lexicon/types/app/bsky/actor/getPreferences.ts
Normal file
40
src/lexicon/types/app/bsky/actor/getPreferences.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* GENERATED CODE - DO NOT MODIFY
|
||||||
|
*/
|
||||||
|
import express from 'express'
|
||||||
|
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||||
|
import { lexicons } from '../../../../lexicons'
|
||||||
|
import { isObj, hasProp } from '../../../../util'
|
||||||
|
import { CID } from 'multiformats/cid'
|
||||||
|
import { HandlerAuth } from '@atproto/xrpc-server'
|
||||||
|
import * as AppBskyActorDefs from './defs'
|
||||||
|
|
||||||
|
export interface QueryParams {}
|
||||||
|
|
||||||
|
export type InputSchema = undefined
|
||||||
|
|
||||||
|
export interface OutputSchema {
|
||||||
|
preferences: AppBskyActorDefs.Preferences
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerInput = undefined
|
||||||
|
|
||||||
|
export interface HandlerSuccess {
|
||||||
|
encoding: 'application/json'
|
||||||
|
body: OutputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandlerError {
|
||||||
|
status: number
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
export type Handler<HA extends HandlerAuth = never> = (ctx: {
|
||||||
|
auth: HA
|
||||||
|
params: QueryParams
|
||||||
|
input: HandlerInput
|
||||||
|
req: express.Request
|
||||||
|
res: express.Response
|
||||||
|
}) => Promise<HandlerOutput> | HandlerOutput
|
36
src/lexicon/types/app/bsky/actor/putPreferences.ts
Normal file
36
src/lexicon/types/app/bsky/actor/putPreferences.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* GENERATED CODE - DO NOT MODIFY
|
||||||
|
*/
|
||||||
|
import express from 'express'
|
||||||
|
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||||
|
import { lexicons } from '../../../../lexicons'
|
||||||
|
import { isObj, hasProp } from '../../../../util'
|
||||||
|
import { CID } from 'multiformats/cid'
|
||||||
|
import { HandlerAuth } from '@atproto/xrpc-server'
|
||||||
|
import * as AppBskyActorDefs from './defs'
|
||||||
|
|
||||||
|
export interface QueryParams {}
|
||||||
|
|
||||||
|
export interface InputSchema {
|
||||||
|
preferences: AppBskyActorDefs.Preferences
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandlerInput {
|
||||||
|
encoding: 'application/json'
|
||||||
|
body: InputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandlerError {
|
||||||
|
status: number
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerOutput = HandlerError | void
|
||||||
|
export type Handler<HA extends HandlerAuth = never> = (ctx: {
|
||||||
|
auth: HA
|
||||||
|
params: QueryParams
|
||||||
|
input: HandlerInput
|
||||||
|
req: express.Request
|
||||||
|
res: express.Response
|
||||||
|
}) => Promise<HandlerOutput> | HandlerOutput
|
@ -6,6 +6,7 @@ import { lexicons } from '../../../../lexicons'
|
|||||||
import { isObj, hasProp } from '../../../../util'
|
import { isObj, hasProp } from '../../../../util'
|
||||||
import { CID } from 'multiformats/cid'
|
import { CID } from 'multiformats/cid'
|
||||||
import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef'
|
import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef'
|
||||||
|
import * as AppBskyFeedDefs from '../feed/defs'
|
||||||
import * as AppBskyActorDefs from '../actor/defs'
|
import * as AppBskyActorDefs from '../actor/defs'
|
||||||
import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
|
import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
|
||||||
import * as AppBskyEmbedImages from './images'
|
import * as AppBskyEmbedImages from './images'
|
||||||
@ -35,6 +36,7 @@ export interface View {
|
|||||||
| ViewRecord
|
| ViewRecord
|
||||||
| ViewNotFound
|
| ViewNotFound
|
||||||
| ViewBlocked
|
| ViewBlocked
|
||||||
|
| AppBskyFeedDefs.GeneratorView
|
||||||
| { $type: string; [k: string]: unknown }
|
| { $type: string; [k: string]: unknown }
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}
|
||||||
|
@ -188,12 +188,14 @@ export function validateBlockedPost(v: unknown): ValidationResult {
|
|||||||
|
|
||||||
export interface GeneratorView {
|
export interface GeneratorView {
|
||||||
uri: string
|
uri: string
|
||||||
|
cid: string
|
||||||
did?: string
|
did?: string
|
||||||
creator: AppBskyActorDefs.ProfileView
|
creator: AppBskyActorDefs.ProfileView
|
||||||
displayName?: string
|
displayName?: string
|
||||||
description?: string
|
description?: string
|
||||||
descriptionFacets?: AppBskyRichtextFacet.Main[]
|
descriptionFacets?: AppBskyRichtextFacet.Main[]
|
||||||
avatar?: string
|
avatar?: string
|
||||||
|
likeCount?: number
|
||||||
viewer?: GeneratorViewerState
|
viewer?: GeneratorViewerState
|
||||||
indexedAt: string
|
indexedAt: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
@ -212,7 +214,7 @@ export function validateGeneratorView(v: unknown): ValidationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface GeneratorViewerState {
|
export interface GeneratorViewerState {
|
||||||
subscribed?: boolean
|
saved?: boolean
|
||||||
like?: string
|
like?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}
|
||||||
|
76
src/lexicon/types/app/bsky/feed/describeFeedGenerator.ts
Normal file
76
src/lexicon/types/app/bsky/feed/describeFeedGenerator.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* GENERATED CODE - DO NOT MODIFY
|
||||||
|
*/
|
||||||
|
import express from 'express'
|
||||||
|
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||||
|
import { lexicons } from '../../../../lexicons'
|
||||||
|
import { isObj, hasProp } from '../../../../util'
|
||||||
|
import { CID } from 'multiformats/cid'
|
||||||
|
import { HandlerAuth } from '@atproto/xrpc-server'
|
||||||
|
|
||||||
|
export interface QueryParams {}
|
||||||
|
|
||||||
|
export type InputSchema = undefined
|
||||||
|
|
||||||
|
export interface OutputSchema {
|
||||||
|
did: string
|
||||||
|
feeds: Feed[]
|
||||||
|
links?: Links
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerInput = undefined
|
||||||
|
|
||||||
|
export interface HandlerSuccess {
|
||||||
|
encoding: 'application/json'
|
||||||
|
body: OutputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandlerError {
|
||||||
|
status: number
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
export type Handler<HA extends HandlerAuth = never> = (ctx: {
|
||||||
|
auth: HA
|
||||||
|
params: QueryParams
|
||||||
|
input: HandlerInput
|
||||||
|
req: express.Request
|
||||||
|
res: express.Response
|
||||||
|
}) => Promise<HandlerOutput> | HandlerOutput
|
||||||
|
|
||||||
|
export interface Feed {
|
||||||
|
uri: string
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isFeed(v: unknown): v is Feed {
|
||||||
|
return (
|
||||||
|
isObj(v) &&
|
||||||
|
hasProp(v, '$type') &&
|
||||||
|
v.$type === 'app.bsky.feed.describeFeedGenerator#feed'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateFeed(v: unknown): ValidationResult {
|
||||||
|
return lexicons.validate('app.bsky.feed.describeFeedGenerator#feed', v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Links {
|
||||||
|
privacyPolicy?: string
|
||||||
|
termsOfService?: string
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLinks(v: unknown): v is Links {
|
||||||
|
return (
|
||||||
|
isObj(v) &&
|
||||||
|
hasProp(v, '$type') &&
|
||||||
|
v.$type === 'app.bsky.feed.describeFeedGenerator#links'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateLinks(v: unknown): ValidationResult {
|
||||||
|
return lexicons.validate('app.bsky.feed.describeFeedGenerator#links', v)
|
||||||
|
}
|
@ -33,6 +33,7 @@ export interface HandlerSuccess {
|
|||||||
export interface HandlerError {
|
export interface HandlerError {
|
||||||
status: number
|
status: number
|
||||||
message?: string
|
message?: string
|
||||||
|
error?: 'UnknownFeed'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HandlerOutput = HandlerError | HandlerSuccess
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
44
src/lexicon/types/app/bsky/feed/getFeedGenerator.ts
Normal file
44
src/lexicon/types/app/bsky/feed/getFeedGenerator.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* GENERATED CODE - DO NOT MODIFY
|
||||||
|
*/
|
||||||
|
import express from 'express'
|
||||||
|
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||||
|
import { lexicons } from '../../../../lexicons'
|
||||||
|
import { isObj, hasProp } from '../../../../util'
|
||||||
|
import { CID } from 'multiformats/cid'
|
||||||
|
import { HandlerAuth } from '@atproto/xrpc-server'
|
||||||
|
import * as AppBskyFeedDefs from './defs'
|
||||||
|
|
||||||
|
export interface QueryParams {
|
||||||
|
feed: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InputSchema = undefined
|
||||||
|
|
||||||
|
export interface OutputSchema {
|
||||||
|
view: AppBskyFeedDefs.GeneratorView
|
||||||
|
isOnline: boolean
|
||||||
|
isValid: boolean
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerInput = undefined
|
||||||
|
|
||||||
|
export interface HandlerSuccess {
|
||||||
|
encoding: 'application/json'
|
||||||
|
body: OutputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandlerError {
|
||||||
|
status: number
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
export type Handler<HA extends HandlerAuth = never> = (ctx: {
|
||||||
|
auth: HA
|
||||||
|
params: QueryParams
|
||||||
|
input: HandlerInput
|
||||||
|
req: express.Request
|
||||||
|
res: express.Response
|
||||||
|
}) => Promise<HandlerOutput> | HandlerOutput
|
@ -33,6 +33,7 @@ export interface HandlerSuccess {
|
|||||||
export interface HandlerError {
|
export interface HandlerError {
|
||||||
status: number
|
status: number
|
||||||
message?: string
|
message?: string
|
||||||
|
error?: 'UnknownFeed'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HandlerOutput = HandlerError | HandlerSuccess
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
@ -12,6 +12,12 @@ import * as ComAtprotoAdminDefs from './defs'
|
|||||||
export interface QueryParams {
|
export interface QueryParams {
|
||||||
subject?: string
|
subject?: string
|
||||||
resolved?: boolean
|
resolved?: boolean
|
||||||
|
actionType?:
|
||||||
|
| 'com.atproto.admin.defs#takedown'
|
||||||
|
| 'com.atproto.admin.defs#flag'
|
||||||
|
| 'com.atproto.admin.defs#acknowledge'
|
||||||
|
| 'com.atproto.admin.defs#escalate'
|
||||||
|
| (string & {})
|
||||||
limit: number
|
limit: number
|
||||||
cursor?: string
|
cursor?: string
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export interface QueryParams {}
|
|||||||
export interface InputSchema {
|
export interface InputSchema {
|
||||||
email: string
|
email: string
|
||||||
handle: string
|
handle: string
|
||||||
|
did?: string
|
||||||
inviteCode?: string
|
inviteCode?: string
|
||||||
password: string
|
password: string
|
||||||
recoveryKey?: string
|
recoveryKey?: string
|
||||||
@ -46,6 +47,8 @@ export interface HandlerError {
|
|||||||
| 'InvalidInviteCode'
|
| 'InvalidInviteCode'
|
||||||
| 'HandleNotAvailable'
|
| 'HandleNotAvailable'
|
||||||
| 'UnsupportedDomain'
|
| 'UnsupportedDomain'
|
||||||
|
| 'UnresolvableDid'
|
||||||
|
| 'IncompatibleDidDoc'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HandlerOutput = HandlerError | HandlerSuccess
|
export type HandlerOutput = HandlerError | HandlerSuccess
|
||||||
|
16
src/methods/describe-generator.ts
Normal file
16
src/methods/describe-generator.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Server } from '../lexicon'
|
||||||
|
import { AppContext } from '../config'
|
||||||
|
import algos from '../algos'
|
||||||
|
|
||||||
|
export default function (server: Server, ctx: AppContext) {
|
||||||
|
server.app.bsky.feed.describeFeedGenerator(async () => {
|
||||||
|
const feeds = Object.keys(algos).map((uri) => ({ uri }))
|
||||||
|
return {
|
||||||
|
encoding: 'application/json',
|
||||||
|
body: {
|
||||||
|
did: ctx.cfg.serviceDid,
|
||||||
|
feeds,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
32
src/methods/feed-generation.ts
Normal file
32
src/methods/feed-generation.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
||||||
|
import { Server } from '../lexicon'
|
||||||
|
import { AppContext } from '../config'
|
||||||
|
import algos from '../algos'
|
||||||
|
import { validateAuth } from '../auth'
|
||||||
|
|
||||||
|
export default function (server: Server, ctx: AppContext) {
|
||||||
|
server.app.bsky.feed.getFeedSkeleton(async ({ params, req }) => {
|
||||||
|
const algo = algos[params.feed]
|
||||||
|
if (!algo) {
|
||||||
|
throw new InvalidRequestError(
|
||||||
|
'Unsupported algorithm',
|
||||||
|
'UnsupportedAlgorithm',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Example of how to check auth if giving user-specific results:
|
||||||
|
*
|
||||||
|
* const requesterDid = await validateAuth(
|
||||||
|
* req,
|
||||||
|
* ctx.cfg.serviceDid,
|
||||||
|
* ctx.didResolver,
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
|
||||||
|
const body = await algo(ctx, params)
|
||||||
|
return {
|
||||||
|
encoding: 'application/json',
|
||||||
|
body: body,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -3,7 +3,8 @@ import events from 'events'
|
|||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { DidResolver, MemoryCache } from '@atproto/did-resolver'
|
import { DidResolver, MemoryCache } from '@atproto/did-resolver'
|
||||||
import { createServer } from './lexicon'
|
import { createServer } from './lexicon'
|
||||||
import feedGeneration from './feed-generation'
|
import feedGeneration from './methods/feed-generation'
|
||||||
|
import describeGenerator from './methods/describe-generator'
|
||||||
import { createDb, Database, migrateToLatest } from './db'
|
import { createDb, Database, migrateToLatest } from './db'
|
||||||
import { FirehoseSubscription } from './subscription'
|
import { FirehoseSubscription } from './subscription'
|
||||||
import { AppContext, Config } from './config'
|
import { AppContext, Config } from './config'
|
||||||
@ -60,6 +61,7 @@ export class FeedGenerator {
|
|||||||
cfg,
|
cfg,
|
||||||
}
|
}
|
||||||
feedGeneration(server, ctx)
|
feedGeneration(server, ctx)
|
||||||
|
describeGenerator(server, ctx)
|
||||||
app.use(server.xrpc.router)
|
app.use(server.xrpc.router)
|
||||||
app.use(wellKnown(cfg.hostname))
|
app.use(wellKnown(cfg.hostname))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user