diff --git a/packages/api/tests/agent.test.ts b/packages/api/tests/agent.test.ts index 2444e7e0c61..c0fb67b9902 100644 --- a/packages/api/tests/agent.test.ts +++ b/packages/api/tests/agent.test.ts @@ -197,7 +197,7 @@ describe('agent', () => { // put the agent through the auth flow AtpAgent.configure({ fetch: tokenExpiredFetchHandler }) - const res1 = await agent.api.app.bsky.feed.getTimeline() + const res1 = await createPost(agent) AtpAgent.configure({ fetch: defaultFetchHandler }) expect(res1.success).toEqual(true) @@ -267,9 +267,9 @@ describe('agent', () => { // put the agent through the auth flow AtpAgent.configure({ fetch: tokenExpiredFetchHandler }) const [res1, res2, res3] = await Promise.all([ - agent.api.app.bsky.feed.getTimeline(), - agent.api.app.bsky.feed.getTimeline(), - agent.api.app.bsky.feed.getTimeline(), + createPost(agent), + createPost(agent), + createPost(agent), ]) AtpAgent.configure({ fetch: defaultFetchHandler }) @@ -462,3 +462,14 @@ describe('agent', () => { }) }) }) + +const createPost = async (agent: AtpAgent) => { + return agent.api.com.atproto.repo.createRecord({ + repo: agent.session?.did ?? '', + collection: 'app.bsky.feed.post', + record: { + text: 'hello there', + createdAt: new Date().toISOString(), + }, + }) +} diff --git a/packages/api/tests/bsky-agent.test.ts b/packages/api/tests/bsky-agent.test.ts index 8ff041d3c14..8066bd61f3a 100644 --- a/packages/api/tests/bsky-agent.test.ts +++ b/packages/api/tests/bsky-agent.test.ts @@ -20,6 +20,20 @@ describe('agent', () => { await close() }) + const getProfileDisplayName = async ( + agent: BskyAgent, + ): Promise => { + try { + const res = await agent.api.app.bsky.actor.profile.get({ + repo: agent.session?.did || '', + rkey: 'self', + }) + return res.value.displayName ?? '' + } catch (err) { + return undefined + } + } + it('upsertProfile correctly creates and updates profiles.', async () => { const agent = new BskyAgent({ service: server.url }) @@ -28,9 +42,8 @@ describe('agent', () => { email: 'user1@test.com', password: 'password', }) - - const profile1 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile1.data.displayName).toBeFalsy() + const displayName1 = await getProfileDisplayName(agent) + expect(displayName1).toBeFalsy() await agent.upsertProfile((existing) => { expect(existing).toBeFalsy() @@ -39,8 +52,8 @@ describe('agent', () => { } }) - const profile2 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile2.data.displayName).toBe('Bob') + const displayName2 = await getProfileDisplayName(agent) + expect(displayName2).toBe('Bob') await agent.upsertProfile((existing) => { expect(existing).toBeTruthy() @@ -49,8 +62,8 @@ describe('agent', () => { } }) - const profile3 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile3.data.displayName).toBe('BOB') + const displayName3 = await getProfileDisplayName(agent) + expect(displayName3).toBe('BOB') }) it('upsertProfile correctly handles CAS failures.', async () => { @@ -62,8 +75,8 @@ describe('agent', () => { password: 'password', }) - const profile1 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile1.data.displayName).toBeFalsy() + const displayName1 = await getProfileDisplayName(agent) + expect(displayName1).toBeFalsy() let hasConflicted = false let ranTwice = false @@ -88,8 +101,8 @@ describe('agent', () => { }) expect(ranTwice).toBe(true) - const profile2 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile2.data.displayName).toBe('Bob') + const displayName2 = await getProfileDisplayName(agent) + expect(displayName2).toBe('Bob') }) it('upsertProfile wont endlessly retry CAS failures.', async () => { @@ -101,8 +114,8 @@ describe('agent', () => { password: 'password', }) - const profile1 = await agent.getProfile({ actor: agent.session?.did || '' }) - expect(profile1.data.displayName).toBeFalsy() + const displayName1 = await getProfileDisplayName(agent) + expect(displayName1).toBeFalsy() const p = agent.upsertProfile(async (_existing) => { await agent.com.atproto.repo.putRecord({ diff --git a/packages/dev-env/src/pds.ts b/packages/dev-env/src/pds.ts index 97b8ceb7452..e94130f41ff 100644 --- a/packages/dev-env/src/pds.ts +++ b/packages/dev-env/src/pds.ts @@ -56,9 +56,6 @@ export class TestPds { appUrlPasswordReset: 'app://forgot-password', emailNoReplyAddress: 'noreply@blueskyweb.xyz', publicUrl: 'https://pds.public.url', - imgUriSalt: '9dd04221f5755bce5f55f47464c27e1e', - imgUriKey: - 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8', dbPostgresUrl: cfg.dbPostgresUrl, maxSubscriptionBuffer: 200, repoBackfillLimitMs: 1000 * 60 * 60, // 1hr @@ -67,7 +64,8 @@ export class TestPds { labelerKeywords: { label_me: 'test-label', label_me_2: 'test-label-2' }, feedGenDid: 'did:example:feedGen', dbTxLockNonce: await randomStr(32, 'base32'), - bskyAppViewProxy: !!cfg.bskyAppViewEndpoint, + bskyAppViewEndpoint: cfg.bskyAppViewEndpoint ?? 'http://fake_address', + bskyAppViewDid: cfg.bskyAppViewDid ?? 'did:example:fake', bskyAppViewCdnUrlPattern: 'http://cdn.appview.com/%s/%s/%s', ...cfg, }) @@ -82,11 +80,7 @@ export class TestPds { : pds.Database.memory() await db.migrateToLatestOrThrow() - if ( - config.bskyAppViewEndpoint && - config.bskyAppViewProxy && - !cfg.enableInProcessAppView - ) { + if (cfg.bskyAppViewEndpoint && !cfg.enableInProcessAppView) { // Disable communication to app view within pds MessageDispatcher.prototype.send = async () => {} } @@ -97,7 +91,6 @@ export class TestPds { repoSigningKey, plcRotationKey, config, - algos: cfg.algos, }) await server.start() diff --git a/packages/dev-env/src/types.ts b/packages/dev-env/src/types.ts index 0aac4f3aa25..d87e78a679a 100644 --- a/packages/dev-env/src/types.ts +++ b/packages/dev-env/src/types.ts @@ -11,7 +11,6 @@ export type PdsConfig = Partial & { plcUrl: string migration?: string enableInProcessAppView?: boolean - algos?: pds.MountedAlgos enableLabelsCache?: boolean } diff --git a/packages/pds/src/api/com/atproto/identity/resolveHandle.ts b/packages/pds/src/api/com/atproto/identity/resolveHandle.ts index 494287dc096..4894103d1c1 100644 --- a/packages/pds/src/api/com/atproto/identity/resolveHandle.ts +++ b/packages/pds/src/api/com/atproto/identity/resolveHandle.ts @@ -33,8 +33,7 @@ export default function (server: Server, ctx: AppContext) { } // this is not someone on our server, but we help with resolving anyway - - if (!did && ctx.canProxyRead()) { + if (!did) { did = await tryResolveFromAppview(ctx.appviewAgent, handle) } diff --git a/packages/pds/src/api/com/atproto/repo/getRecord.ts b/packages/pds/src/api/com/atproto/repo/getRecord.ts index 2d73244b0d9..29194c94843 100644 --- a/packages/pds/src/api/com/atproto/repo/getRecord.ts +++ b/packages/pds/src/api/com/atproto/repo/getRecord.ts @@ -1,7 +1,7 @@ import { AtUri } from '@atproto/syntax' -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../lexicon' import AppContext from '../../../../context' +import { InvalidRequestError } from '@atproto/xrpc-server' export default function (server: Server, ctx: AppContext) { server.com.atproto.repo.getRecord(async ({ params }) => { @@ -14,29 +14,23 @@ export default function (server: Server, ctx: AppContext) { const record = await ctx.services .record(ctx.db) .getRecord(uri, cid || null) - if (record) { - return { - encoding: 'application/json', - body: { - uri: record.uri, - cid: record.cid, - value: record.value, - }, - } + if (!record) { + throw new InvalidRequestError(`Could not locate record: ${uri}`) } - } - - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.com.atproto.repo.getRecord(params) return { encoding: 'application/json', - body: res.data, + body: { + uri: record.uri, + cid: record.cid, + value: record.value, + }, } - } else { - const uri = AtUri.make(did || repo, collection, rkey) - throw new InvalidRequestError( - `Could not locate record: ${uri.toString()}`, - ) + } + + const res = await ctx.appviewAgent.api.com.atproto.repo.getRecord(params) + return { + encoding: 'application/json', + body: res.data, } }) } diff --git a/packages/pds/src/app-view/api/app/bsky/actor/getProfile.ts b/packages/pds/src/app-view/api/app/bsky/actor/getProfile.ts index 540a8cc3779..4d510bda720 100644 --- a/packages/pds/src/app-view/api/app/bsky/actor/getProfile.ts +++ b/packages/pds/src/app-view/api/app/bsky/actor/getProfile.ts @@ -1,6 +1,4 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { softDeleted } from '../../../../../db/util' import AppContext from '../../../../../context' import { authPassthru } from '../../../../../api/com/atproto/admin/util' import { OutputSchema } from '../../../../../lexicon/types/app/bsky/actor/getProfile' @@ -13,57 +11,16 @@ export default function (server: Server, ctx: AppContext) { handler: async ({ req, auth, params }) => { const requester = auth.credentials.type === 'access' ? auth.credentials.did : null - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile( - params, - requester - ? await ctx.serviceAuthHeaders(requester) - : authPassthru(req), - ) - if (res.data.did === requester) { - return await handleReadAfterWrite( - ctx, - requester, - res, - getProfileMunge, - ) - } - return { - encoding: 'application/json', - body: res.data, - } - } - - // As long as user has triage permission, we know that they are a moderator user and can see taken down profiles - const canViewTakendownProfile = - auth.credentials.type === 'role' && auth.credentials.triage - const { actor } = params - const { db, services } = ctx - const actorService = services.appView.actor(db) - - const actorRes = await actorService.getActor(actor, true) - - if (!actorRes) { - throw new InvalidRequestError('Profile not found') - } - if (!canViewTakendownProfile && softDeleted(actorRes)) { - throw new InvalidRequestError( - 'Account has been taken down', - 'AccountTakedown', - ) - } - const profile = await actorService.views.profileDetailed( - actorRes, - requester, - { includeSoftDeleted: canViewTakendownProfile }, + const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile( + params, + requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req), ) - if (!profile) { - throw new InvalidRequestError('Profile not found') + if (res.data.did === requester) { + return await handleReadAfterWrite(ctx, requester, res, getProfileMunge) } - return { encoding: 'application/json', - body: profile, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/actor/getProfiles.ts b/packages/pds/src/app-view/api/app/bsky/actor/getProfiles.ts index 0750a6109d7..08f30dfe690 100644 --- a/packages/pds/src/app-view/api/app/bsky/actor/getProfiles.ts +++ b/packages/pds/src/app-view/api/app/bsky/actor/getProfiles.ts @@ -9,40 +9,17 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles( - params, - await ctx.serviceAuthHeaders(requester), - ) - const hasSelf = res.data.profiles.some((prof) => prof.did === requester) - if (hasSelf) { - return await handleReadAfterWrite( - ctx, - requester, - res, - getProfilesMunge, - ) - } - return { - encoding: 'application/json', - body: res.data, - } + const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles( + params, + await ctx.serviceAuthHeaders(requester), + ) + const hasSelf = res.data.profiles.some((prof) => prof.did === requester) + if (hasSelf) { + return await handleReadAfterWrite(ctx, requester, res, getProfilesMunge) } - - const { actors } = params - const { db, services } = ctx - const actorService = services.appView.actor(db) - - const actorsRes = await actorService.getActors(actors) - return { encoding: 'application/json', - body: { - profiles: await actorService.views.hydrateProfilesDetailed( - actorsRes, - requester, - ), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/actor/getSuggestions.ts b/packages/pds/src/app-view/api/app/bsky/actor/getSuggestions.ts index f80110dacb0..9047634dd30 100644 --- a/packages/pds/src/app-view/api/app/bsky/actor/getSuggestions.ts +++ b/packages/pds/src/app-view/api/app/bsky/actor/getSuggestions.ts @@ -1,5 +1,4 @@ import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' import { Server } from '../../../../../lexicon' export default function (server: Server, ctx: AppContext) { @@ -7,71 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.actor.getSuggestions( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { limit, cursor } = params - - const db = ctx.db.db - const { services } = ctx - const { ref } = db.dynamic - - const graphService = ctx.services.appView.graph(ctx.db) - - let suggestionsQb = db - .selectFrom('suggested_follow') - .innerJoin('did_handle', 'suggested_follow.did', 'did_handle.did') - .innerJoin('repo_root', 'repo_root.did', 'did_handle.did') - .innerJoin('profile_agg', 'profile_agg.did', 'did_handle.did') - .where(notSoftDeletedClause(ref('repo_root'))) - .where('did_handle.did', '!=', requester) - .whereNotExists((qb) => - qb - .selectFrom('follow') - .selectAll() - .where('creator', '=', requester) - .whereRef('subjectDid', '=', ref('did_handle.did')), - ) - .whereNotExists( - graphService.blockQb(requester, [ref('did_handle.did')]), - ) - .selectAll('did_handle') - .select('profile_agg.postsCount as postsCount') - .limit(limit) - .orderBy('suggested_follow.order', 'asc') - - if (cursor) { - const cursorRow = await db - .selectFrom('suggested_follow') - .where('did', '=', cursor) - .selectAll() - .executeTakeFirst() - if (cursorRow) { - suggestionsQb = suggestionsQb.where( - 'suggested_follow.order', - '>', - cursorRow.order, - ) - } - } - - const suggestionsRes = await suggestionsQb.execute() + const res = await ctx.appviewAgent.api.app.bsky.actor.getSuggestions( + params, + await ctx.serviceAuthHeaders(requester), + ) return { encoding: 'application/json', - body: { - cursor: suggestionsRes.at(-1)?.did, - actors: await services.appView - .actor(ctx.db) - .views.hydrateProfiles(suggestionsRes, requester), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/actor/searchActors.ts b/packages/pds/src/app-view/api/app/bsky/actor/searchActors.ts index 0c1e07c014a..ff88cd8d233 100644 --- a/packages/pds/src/app-view/api/app/bsky/actor/searchActors.ts +++ b/packages/pds/src/app-view/api/app/bsky/actor/searchActors.ts @@ -1,90 +1,19 @@ -import { sql } from 'kysely' import AppContext from '../../../../../context' -import Database from '../../../../../db' -import { DidHandle } from '../../../../../db/tables/did-handle' import { Server } from '../../../../../lexicon' -import * as Method from '../../../../../lexicon/types/app/bsky/actor/searchActors' -import { - cleanTerm, - getUserSearchQueryPg, - getUserSearchQuerySqlite, - SearchKeyset, -} from '../../../../../services/util/search' export default function (server: Server, ctx: AppContext) { server.app.bsky.actor.searchActors({ auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.actor.searchActors( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { services, db } = ctx - let { term, limit } = params - const { cursor } = params - - term = cleanTerm(term || '') - limit = Math.min(limit ?? 25, 100) - - if (!term) { - return { - encoding: 'application/json', - body: { - actors: [], - }, - } - } - - const results = - db.dialect === 'pg' - ? await getResultsPg(db, { term, limit, cursor }) - : await getResultsSqlite(db, { term, limit, cursor }) - - const keyset = new SearchKeyset(sql``, sql``) - - const actors = await services.appView - .actor(db) - .views.hydrateProfiles(results, requester) - - const filtered = actors.filter( - (actor) => !actor.viewer?.blocking && !actor.viewer?.blockedBy, + const res = await ctx.appviewAgent.api.app.bsky.actor.searchActors( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - cursor: keyset.packFromResult(results), - actors: filtered, - }, + body: res.data, } }, }) } - -const getResultsPg: GetResultsFn = async (db, { term, limit, cursor }) => { - return await getUserSearchQueryPg(db, { term: term || '', limit, cursor }) - .select('distance') - .selectAll('did_handle') - .execute() -} - -const getResultsSqlite: GetResultsFn = async (db, { term, limit, cursor }) => { - return await getUserSearchQuerySqlite(db, { term: term || '', limit, cursor }) - .leftJoin('profile', 'profile.creator', 'did_handle.did') - .select(sql`0`.as('distance')) - .selectAll('did_handle') - .execute() -} - -type GetResultsFn = ( - db: Database, - opts: Method.QueryParams & { limit: number }, -) => Promise<(DidHandle & { distance: number })[]> diff --git a/packages/pds/src/app-view/api/app/bsky/actor/searchActorsTypeahead.ts b/packages/pds/src/app-view/api/app/bsky/actor/searchActorsTypeahead.ts index bcc80d6acc3..5853cf3104e 100644 --- a/packages/pds/src/app-view/api/app/bsky/actor/searchActorsTypeahead.ts +++ b/packages/pds/src/app-view/api/app/bsky/actor/searchActorsTypeahead.ts @@ -1,83 +1,20 @@ import AppContext from '../../../../../context' -import Database from '../../../../../db' import { Server } from '../../../../../lexicon' -import * as Method from '../../../../../lexicon/types/app/bsky/actor/searchActorsTypeahead' -import { - cleanTerm, - getUserSearchQuerySimplePg, - getUserSearchQuerySqlite, -} from '../../../../../services/util/search' -import { DidHandle } from '../../../../../db/tables/did-handle' export default function (server: Server, ctx: AppContext) { server.app.bsky.actor.searchActorsTypeahead({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = - await ctx.appviewAgent.api.app.bsky.actor.searchActorsTypeahead( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { services, db } = ctx - let { term, limit } = params - - term = cleanTerm(term || '') - limit = Math.min(limit ?? 25, 100) - - if (!term) { - return { - encoding: 'application/json', - body: { - actors: [], - }, - } - } - - const results = - ctx.db.dialect === 'pg' - ? await getResultsPg(ctx.db, { term, limit }) - : await getResultsSqlite(ctx.db, { term, limit }) - - const actors = await services.appView - .actor(db) - .views.hydrateProfilesBasic(results, requester) - - const filtered = actors.filter( - (actor) => !actor.viewer?.blocking && !actor.viewer?.blockedBy, - ) - + const res = + await ctx.appviewAgent.api.app.bsky.actor.searchActorsTypeahead( + params, + await ctx.serviceAuthHeaders(requester), + ) return { encoding: 'application/json', - body: { - actors: filtered, - }, + body: res.data, } }, }) } - -const getResultsPg: GetResultsFn = async (db, { term, limit }) => { - return await getUserSearchQuerySimplePg(db, { term: term || '', limit }) - .selectAll('did_handle') - .execute() -} - -const getResultsSqlite: GetResultsFn = async (db, { term, limit }) => { - return await getUserSearchQuerySqlite(db, { term: term || '', limit }) - .leftJoin('profile', 'profile.creator', 'did_handle.did') - .selectAll('did_handle') - .execute() -} - -type GetResultsFn = ( - db: Database, - opts: Method.QueryParams & { limit: number }, -) => Promise diff --git a/packages/pds/src/app-view/api/app/bsky/feed/describeFeedGenerator.ts b/packages/pds/src/app-view/api/app/bsky/feed/describeFeedGenerator.ts deleted file mode 100644 index 89a8a1f48dd..00000000000 --- a/packages/pds/src/app-view/api/app/bsky/feed/describeFeedGenerator.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Server } from '../../../../../lexicon' -import AppContext from '../../../../../context' -import { MethodNotImplementedError } from '@atproto/xrpc-server' - -export default function (server: Server, ctx: AppContext) { - server.app.bsky.feed.describeFeedGenerator(async () => { - if (!ctx.cfg.feedGenDid) { - throw new MethodNotImplementedError() - } - - const feeds = Object.keys(ctx.algos).map((uri) => ({ uri })) - - return { - encoding: 'application/json', - body: { - did: ctx.cfg.feedGenDid, - feeds, - }, - } - }) -} diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getActorFeeds.ts b/packages/pds/src/app-view/api/app/bsky/feed/getActorFeeds.ts index f6ded6d2c0e..57d7d72b6e4 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getActorFeeds.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getActorFeeds.ts @@ -1,69 +1,18 @@ import { Server } from '../../../../../lexicon' import AppContext from '../../../../../context' -import { TimeCidKeyset, paginate } from '../../../../../db/pagination' -import { InvalidRequestError } from '@atproto/xrpc-server' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getActorFeeds({ auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getActorFeeds( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { actor, limit, cursor } = params - - const actorService = ctx.services.appView.actor(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - - const creatorRes = await actorService.getActor(actor) - if (!creatorRes) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - - const { ref } = ctx.db.db.dynamic - let feedsQb = feedService - .selectFeedGeneratorQb(requester) - .where('feed_generator.creator', '=', creatorRes.did) - - const keyset = new TimeCidKeyset( - ref('feed_generator.createdAt'), - ref('feed_generator.cid'), + const res = await ctx.appviewAgent.api.app.bsky.feed.getActorFeeds( + params, + await ctx.serviceAuthHeaders(requester), ) - feedsQb = paginate(feedsQb, { - limit, - cursor, - keyset, - }) - - const [feedsRes, creatorProfile] = await Promise.all([ - feedsQb.execute(), - actorService.views.profile(creatorRes, requester), - ]) - if (!creatorProfile) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - - const profiles = { [creatorProfile.did]: creatorProfile } - - const feeds = feedsRes.map((row) => - feedService.views.formatFeedGeneratorView(row, profiles), - ) - return { encoding: 'application/json', - body: { - cursor: keyset.packFromResult(feedsRes), - feeds, - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getActorLikes.ts b/packages/pds/src/app-view/api/app/bsky/feed/getActorLikes.ts index 5e67e9c6dcf..6e56bc81214 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getActorLikes.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getActorLikes.ts @@ -1,9 +1,5 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { FeedKeyset } from '../util/feed' -import { paginate } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { FeedRow } from '../../../../services/feed' import { OutputSchema } from '../../../../../lexicon/types/app/bsky/feed/getAuthorFeed' import { handleReadAfterWrite } from '../util/read-after-write' import { authPassthru } from '../../../../../api/com/atproto/admin/util' @@ -16,75 +12,16 @@ export default function (server: Server, ctx: AppContext) { const requester = auth.credentials.type === 'access' ? auth.credentials.did : null - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getActorLikes( - params, - requester - ? await ctx.serviceAuthHeaders(requester) - : authPassthru(req), - ) - if (requester) { - return await handleReadAfterWrite(ctx, requester, res, getAuthorMunge) - } - return { - encoding: 'application/json', - body: res.data, - } - } - - const { actor, limit, cursor } = params - - const { ref } = ctx.db.db.dynamic - const actorService = ctx.services.appView.actor(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - // maybe resolve did first - const actorRes = await actorService.getActor(actor) - if (!actorRes) { - throw new InvalidRequestError('Profile not found') - } - const actorDid = actorRes.did - - if (!requester || requester !== actorDid) { - throw new InvalidRequestError('Profile not found') - } - - // defaults to posts, reposts, and replies - let feedItemsQb = feedService - .selectFeedItemQb() - .innerJoin('like', 'like.subject', 'feed_item.uri') - .where('like.creator', '=', actorDid) - - // for access-based auth, enforce blocks + const res = await ctx.appviewAgent.api.app.bsky.feed.getActorLikes( + params, + requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req), + ) if (requester) { - feedItemsQb = feedItemsQb.whereNotExists( - graphService.blockQb(requester, [ref('post.creator')]), - ) + return await handleReadAfterWrite(ctx, requester, res, getAuthorMunge) } - - const keyset = new FeedKeyset( - ref('feed_item.sortAt'), - ref('feed_item.cid'), - ) - - feedItemsQb = paginate(feedItemsQb, { - limit, - cursor, - keyset, - }) - - const feedItems: FeedRow[] = await feedItemsQb.execute() - const feed = await feedService.hydrateFeed(feedItems, requester, { - includeSoftDeleted: auth.credentials.type === 'role', // show takendown content to mods - }) - return { encoding: 'application/json', - body: { - feed, - cursor: keyset.packFromResult(feedItems), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getAuthorFeed.ts b/packages/pds/src/app-view/api/app/bsky/feed/getAuthorFeed.ts index 7850092dc28..735004f52e3 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getAuthorFeed.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getAuthorFeed.ts @@ -1,9 +1,5 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { FeedKeyset } from '../util/feed' -import { paginate } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { FeedRow } from '../../../../services/feed' import { OutputSchema } from '../../../../../lexicon/types/app/bsky/feed/getAuthorFeed' import { handleReadAfterWrite } from '../util/read-after-write' import { authPassthru } from '../../../../../api/com/atproto/admin/util' @@ -16,130 +12,21 @@ export default function (server: Server, ctx: AppContext) { handler: async ({ req, params, auth }) => { const requester = auth.credentials.type === 'access' ? auth.credentials.did : null - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getAuthorFeed( - params, - requester - ? await ctx.serviceAuthHeaders(requester) - : authPassthru(req), - ) - if (requester) { - return await handleReadAfterWrite(ctx, requester, res, getAuthorMunge) - } - return { - encoding: 'application/json', - body: res.data, - } - } - - const { actor, limit, cursor } = params - - const { ref } = ctx.db.db.dynamic - const accountService = ctx.services.account(ctx.db) - const actorService = ctx.services.appView.actor(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - // maybe resolve did first - const actorRes = await actorService.getActor(actor) - if (!actorRes) { - throw new InvalidRequestError('Profile not found') - } - const actorDid = actorRes.did - - // defaults to posts, reposts, and replies - let feedItemsQb = feedService - .selectFeedItemQb() - .where('originatorDid', '=', actorDid) - - if (params.filter === 'posts_with_media') { - feedItemsQb = feedItemsQb - // and only your own posts/reposts - .where('post.creator', '=', actorDid) - // only posts with media - .whereExists((qb) => - qb - .selectFrom('post_embed_image') - .select('post_embed_image.postUri') - .whereRef('post_embed_image.postUri', '=', 'feed_item.postUri'), - ) - } else if (params.filter === 'posts_no_replies') { - feedItemsQb = feedItemsQb - // only posts, no replies - .where((qb) => - qb - .where('post.replyParent', 'is', null) - .orWhere('type', '=', 'repost'), - ) - } - - // for access-based auth, enforce blocks and mutes + const res = await ctx.appviewAgent.api.app.bsky.feed.getAuthorFeed( + params, + requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req), + ) if (requester) { - await assertNoBlocks(ctx, { requester, actor }) - feedItemsQb = feedItemsQb - .where((qb) => - // hide reposts of muted content - qb - .where('type', '=', 'post') - .orWhere((qb) => - accountService.whereNotMuted(qb, requester, [ - ref('post.creator'), - ]), - ), - ) - .whereNotExists( - graphService.blockQb(requester, [ref('post.creator')]), - ) + return await handleReadAfterWrite(ctx, requester, res, getAuthorMunge) } - - const keyset = new FeedKeyset( - ref('feed_item.sortAt'), - ref('feed_item.cid'), - ) - - feedItemsQb = paginate(feedItemsQb, { - limit, - cursor, - keyset, - }) - - const feedItems: FeedRow[] = await feedItemsQb.execute() - const feed = await feedService.hydrateFeed(feedItems, requester, { - includeSoftDeleted: auth.credentials.type === 'role', // show takendown content to mods - }) - return { encoding: 'application/json', - body: { - feed, - cursor: keyset.packFromResult(feedItems), - }, + body: res.data, } }, }) } -// throws when there's a block between the two users -async function assertNoBlocks( - ctx: AppContext, - opts: { requester: string; actor: string }, -) { - const { requester, actor } = opts - const graphService = ctx.services.appView.graph(ctx.db) - const blocks = await graphService.getBlocks(requester, actor) - if (blocks.blocking) { - throw new InvalidRequestError( - `Requester has blocked actor: ${actor}`, - 'BlockedActor', - ) - } else if (blocks.blockedBy) { - throw new InvalidRequestError( - `Requester is blocked by actor: $${actor}`, - 'BlockedByActor', - ) - } -} - const getAuthorMunge = async ( ctx: AppContext, original: OutputSchema, diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getFeed.ts b/packages/pds/src/app-view/api/app/bsky/feed/getFeed.ts index 5f9eb9d975c..a5cf4176d4e 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getFeed.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getFeed.ts @@ -1,217 +1,25 @@ -import { - InvalidRequestError, - UpstreamFailureError, - createServiceAuthHeaders, - ServerTimer, - serverTimingHeader, -} from '@atproto/xrpc-server' -import { ResponseType, XRPCError } from '@atproto/xrpc' -import { getFeedGen } from '@atproto/identity' -import { AtpAgent, AppBskyFeedGetFeedSkeleton } from '@atproto/api' -import { SkeletonFeedPost } from '../../../../../lexicon/types/app/bsky/feed/defs' -import { QueryParams as GetFeedParams } from '../../../../../lexicon/types/app/bsky/feed/getFeed' -import { OutputSchema as SkeletonOutput } from '../../../../../lexicon/types/app/bsky/feed/getFeedSkeleton' import { Server } from '../../../../../lexicon' import AppContext from '../../../../../context' -import { FeedRow } from '../../../../services/feed' -import { AlgoResponse } from '../../../../../feed-gen/types' -import { getDidDoc } from '../util/resolver' export default function (server: Server, ctx: AppContext) { - const isProxyableFeed = (feed: string): boolean => { - return feed in ctx.algos - } - server.app.bsky.feed.getFeed({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const { data: feed } = - await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator( - { feed: params.feed }, - await ctx.serviceAuthHeaders(requester), - ) - const res = await ctx.appviewAgent.api.app.bsky.feed.getFeed( - params, - await ctx.serviceAuthHeaders(requester, feed.view.did), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - let algoRes: AlgoResponse - const timerSkele = new ServerTimer('skele').start() - - if (ctx.cfg.bskyAppViewEndpoint && isProxyableFeed(params.feed)) { - // this is a temporary solution to smart proxy bsky feeds to the appview - const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedSkeleton( - params, + const { data: feed } = + await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator( + { feed: params.feed }, await ctx.serviceAuthHeaders(requester), ) - algoRes = await filterMutesAndBlocks( - ctx, - res.data, - params.limit, - requester, - ) - } else { - algoRes = await skeletonFromFeedGen(ctx, params, requester) - } - - timerSkele.stop() - - const feedService = ctx.services.appView.feed(ctx.db) - const { feedItems, ...rest } = algoRes - - const timerHydr = new ServerTimer('hydr').start() - const hydrated = await feedService.hydrateFeed(feedItems, requester) - timerHydr.stop() - + const res = await ctx.appviewAgent.api.app.bsky.feed.getFeed( + params, + await ctx.serviceAuthHeaders(requester, feed.view.did), + ) return { encoding: 'application/json', - body: { - ...rest, - feed: hydrated, - }, - headers: { - 'server-timing': serverTimingHeader([timerSkele, timerHydr]), - }, + body: res.data, } }, }) } - -async function skeletonFromFeedGen( - ctx: AppContext, - params: GetFeedParams, - requester: string, -): Promise { - const { feed } = params - // Resolve and fetch feed skeleton - const found = await ctx.db.db - .selectFrom('feed_generator') - .where('uri', '=', feed) - .select('feedDid') - .executeTakeFirst() - if (!found) { - throw new InvalidRequestError('could not find feed') - } - const feedDid = found.feedDid - - const doc = await getDidDoc(ctx, feedDid) - const fgEndpoint = getFeedGen(doc) - if (!fgEndpoint) { - throw new InvalidRequestError( - `invalid feed generator service details in did document: ${feedDid}`, - ) - } - - const agent = new AtpAgent({ service: fgEndpoint }) - const headers = await createServiceAuthHeaders({ - iss: requester, - aud: feedDid, - keypair: ctx.repoSigningKey, - }) - - let skeleton: SkeletonOutput - try { - const result = await agent.api.app.bsky.feed.getFeedSkeleton( - params, - headers, - ) - skeleton = result.data - } catch (err) { - if (err instanceof AppBskyFeedGetFeedSkeleton.UnknownFeedError) { - throw new InvalidRequestError(err.message, 'UnknownFeed') - } - if (err instanceof XRPCError) { - if (err.status === ResponseType.Unknown) { - throw new UpstreamFailureError('feed unavailable') - } - if (err.status === ResponseType.InvalidResponse) { - throw new UpstreamFailureError( - 'feed provided an invalid response', - 'InvalidFeedResponse', - ) - } - } - throw err - } - - return filterMutesAndBlocks(ctx, skeleton, params.limit, requester) -} - -export async function filterMutesAndBlocks( - ctx: AppContext, - skeleton: SkeletonOutput, - limit: number, - requester: string, -) { - const { feed: skeletonFeed, ...rest } = skeleton - - const { ref } = ctx.db.db.dynamic - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - const accountService = ctx.services.account(ctx.db) - const feedItemUris = skeletonFeed.map(getSkeleFeedItemUri) - - const feedItems = feedItemUris.length - ? await feedService - .selectFeedItemQb() - .where('feed_item.uri', 'in', feedItemUris) - .where((qb) => - // Hide posts and reposts of or by muted actors - accountService.whereNotMuted(qb, requester, [ - ref('post.creator'), - ref('originatorDid'), - ]), - ) - .whereNotExists( - graphService.blockQb(requester, [ - ref('post.creator'), - ref('originatorDid'), - ]), - ) - .execute() - : [] - - const orderedItems = getOrderedFeedItems(skeletonFeed, feedItems, limit) - return { - ...rest, - feedItems: orderedItems, - } -} - -function getSkeleFeedItemUri(item: SkeletonFeedPost) { - if (typeof item.reason?.repost === 'string') { - return item.reason.repost - } - return item.post -} - -function getOrderedFeedItems( - skeletonItems: SkeletonFeedPost[], - feedItems: FeedRow[], - limit: number, -) { - const SKIP = [] - const feedItemsByUri = feedItems.reduce((acc, item) => { - return Object.assign(acc, { [item.uri]: item }) - }, {} as Record) - // enforce limit param in the case that the feedgen does not - if (skeletonItems.length > limit) { - skeletonItems = skeletonItems.slice(0, limit) - } - return skeletonItems.flatMap((item) => { - const uri = getSkeleFeedItemUri(item) - const feedItem = feedItemsByUri[uri] - if (!feedItem || item.post !== feedItem.postUri) { - // Couldn't find the record, or skeleton repost referenced the wrong post - return SKIP - } - return feedItem - }) -} diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerator.ts b/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerator.ts index 66e0cc8fdc5..210b1be54ef 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerator.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerator.ts @@ -1,9 +1,3 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' -import { - DidDocument, - PoorlyFormattedDidDocumentError, - getFeedGen, -} from '@atproto/identity' import { Server } from '../../../../../lexicon' import AppContext from '../../../../../context' @@ -12,67 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { feed } = params - - const feedService = ctx.services.appView.feed(ctx.db) - - const got = await feedService.getFeedGeneratorInfos([feed], requester) - const feedInfo = got[feed] - if (!feedInfo) { - throw new InvalidRequestError('could not find feed') - } - - const feedDid = feedInfo.feedDid - let resolved: DidDocument | null - try { - resolved = await ctx.idResolver.did.resolve(feedDid) - } catch (err) { - if (err instanceof PoorlyFormattedDidDocumentError) { - throw new InvalidRequestError(`invalid did document: ${feedDid}`) - } - throw err - } - if (!resolved) { - throw new InvalidRequestError( - `could not resolve did document: ${feedDid}`, - ) - } - - const fgEndpoint = getFeedGen(resolved) - if (!fgEndpoint) { - throw new InvalidRequestError( - `invalid feed generator service details in did document: ${feedDid}`, - ) - } - - const profiles = await feedService.getActorInfos( - [feedInfo.creator], - requester, - ) - const feedView = feedService.views.formatFeedGeneratorView( - feedInfo, - profiles, + const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - view: feedView, - // @TODO temporarily hard-coding to true while external feedgens catch-up on describeFeedGenerator - isOnline: true, - isValid: true, - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerators.ts b/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerators.ts index 3cf7f8eef11..36353f015b7 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerators.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getFeedGenerators.ts @@ -6,36 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerators( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { feeds } = params - - const feedService = ctx.services.appView.feed(ctx.db) - - const genInfos = await feedService.getFeedGeneratorInfos(feeds, requester) - const genList = Object.values(genInfos) - - const creators = genList.map((gen) => gen.creator) - const profiles = await feedService.getActorInfos(creators, requester) - - const feedViews = genList.map((gen) => - feedService.views.formatFeedGeneratorView(gen, profiles), + const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerators( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - feeds: feedViews, - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getLikes.ts b/packages/pds/src/app-view/api/app/bsky/feed/getLikes.ts index e6658863bed..a78469355d5 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getLikes.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getLikes.ts @@ -1,83 +1,18 @@ -import { mapDefined } from '@atproto/common' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getLikes({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getLikes( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { uri, limit, cursor, cid } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const graphService = ctx.services.appView.graph(ctx.db) - - let builder = db.db - .selectFrom('like') - .where('like.subject', '=', uri) - .innerJoin('did_handle as creator', 'creator.did', 'like.creator') - .innerJoin( - 'repo_root as creator_repo', - 'creator_repo.did', - 'like.creator', - ) - .where(notSoftDeletedClause(ref('creator_repo'))) - .whereNotExists(graphService.blockQb(requester, [ref('like.creator')])) - .selectAll('creator') - .select([ - 'like.cid as cid', - 'like.createdAt as createdAt', - 'like.indexedAt as indexedAt', - ]) - - if (cid) { - builder = builder.where('like.subjectCid', '=', cid) - } - - const keyset = new TimeCidKeyset(ref('like.createdAt'), ref('like.cid')) - builder = paginate(builder, { - limit, - cursor, - keyset, - }) - - const likesRes = await builder.execute() - const actors = await services.appView - .actor(db) - .views.profiles(likesRes, requester) - - const likes = mapDefined(likesRes, (row) => - actors[row.did] - ? { - createdAt: row.createdAt, - indexedAt: row.indexedAt, - actor: actors[row.did], - } - : undefined, + const res = await ctx.appviewAgent.api.app.bsky.feed.getLikes( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - uri, - cid, - cursor: keyset.packFromResult(likesRes), - likes, - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getPostThread.ts b/packages/pds/src/app-view/api/app/bsky/feed/getPostThread.ts index fb5276f2452..be1e8004bac 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getPostThread.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getPostThread.ts @@ -1,27 +1,10 @@ import { AtUri } from '@atproto/syntax' import { AppBskyFeedGetPostThread } from '@atproto/api' import { Headers } from '@atproto/xrpc' -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' import AppContext from '../../../../../context' import { - ActorInfoMap, - PostEmbedViews, - FeedRow, - FeedService, - PostInfoMap, - PostBlocksMap, -} from '../../../../services/feed' -import { - getAncestorsAndSelfQb, - getDescendentsQb, -} from '../../../../services/feed/util' -import { Labels } from '../../../../services/label' -import { - BlockedPost, - NotFoundPost, ThreadViewPost, - isNotFoundPost, isThreadViewPost, } from '../../../../../lexicon/types/app/bsky/feed/defs' import { Record as PostRecord } from '../../../../../lexicon/types/app/bsky/feed/post' @@ -40,294 +23,51 @@ import { handleReadAfterWrite, } from '../util/read-after-write' -export type PostThread = { - post: FeedRow - parent?: PostThread | ParentNotFoundError - replies?: PostThread[] -} - export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getPostThread({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - try { - const res = await ctx.appviewAgent.api.app.bsky.feed.getPostThread( - params, - await ctx.serviceAuthHeaders(requester), - ) - return await handleReadAfterWrite( + try { + const res = await ctx.appviewAgent.api.app.bsky.feed.getPostThread( + params, + await ctx.serviceAuthHeaders(requester), + ) + return await handleReadAfterWrite( + ctx, + requester, + res, + getPostThreadMunge, + ) + } catch (err) { + if (err instanceof AppBskyFeedGetPostThread.NotFoundError) { + const local = await readAfterWriteNotFound( ctx, + params, requester, - res, - getPostThreadMunge, + err.headers, ) - } catch (err) { - if (err instanceof AppBskyFeedGetPostThread.NotFoundError) { - const local = await readAfterWriteNotFound( - ctx, - params, - requester, - err.headers, - ) - if (local === null) { - throw err - } else { - return { - encoding: 'application/json', - body: local.data, - headers: local.lag - ? { - 'Atproto-Upstream-Lag': local.lag.toString(10), - } - : undefined, - } - } - } else { + if (local === null) { throw err + } else { + return { + encoding: 'application/json', + body: local.data, + headers: local.lag + ? { + 'Atproto-Upstream-Lag': local.lag.toString(10), + } + : undefined, + } } + } else { + throw err } } - - const { uri, depth, parentHeight } = params - - const feedService = ctx.services.appView.feed(ctx.db) - const labelService = ctx.services.appView.label(ctx.db) - - const threadData = await getThreadData(ctx, uri, depth, parentHeight) - if (!threadData) { - throw new InvalidRequestError(`Post not found: ${uri}`, 'NotFound') - } - const relevant = getRelevantIds(threadData) - const [actors, posts, labels] = await Promise.all([ - feedService.getActorInfos(Array.from(relevant.dids), requester, { - skipLabels: true, - }), - feedService.getPostInfos(Array.from(relevant.uris), requester), - labelService.getLabelsForSubjects([...relevant.uris, ...relevant.dids]), - ]) - const blocks = await feedService.blocksForPosts(posts) - const embeds = await feedService.embedsForPosts(posts, blocks, requester) - - const thread = composeThread( - threadData, - feedService, - posts, - actors, - embeds, - blocks, - labels, - ) - - if (isNotFoundPost(thread)) { - // @TODO technically this could be returned as a NotFoundPost based on lexicon - throw new InvalidRequestError(`Post not found: ${uri}`, 'NotFound') - } - - return { - encoding: 'application/json', - body: { thread }, - } }, }) } -const composeThread = ( - threadData: PostThread, - feedService: FeedService, - posts: PostInfoMap, - actors: ActorInfoMap, - embeds: PostEmbedViews, - blocks: PostBlocksMap, - labels: Labels, -): ThreadViewPost | NotFoundPost | BlockedPost => { - const post = feedService.views.formatPostView( - threadData.post.postUri, - actors, - posts, - embeds, - labels, - ) - - if (!post || blocks[post.uri]?.reply) { - return { - $type: 'app.bsky.feed.defs#notFoundPost', - uri: threadData.post.postUri, - notFound: true, - } - } - - if (post.author.viewer?.blocking || post.author.viewer?.blockedBy) { - return { - $type: 'app.bsky.feed.defs#blockedPost', - uri: threadData.post.postUri, - blocked: true, - author: { - did: post.author.did, - viewer: post.author.viewer - ? { - blockedBy: post.author.viewer?.blockedBy, - blocking: post.author.viewer?.blocking, - } - : undefined, - }, - } - } - - let parent: ThreadViewPost | NotFoundPost | BlockedPost | undefined - if (threadData.parent) { - if (threadData.parent instanceof ParentNotFoundError) { - parent = { - $type: 'app.bsky.feed.defs#notFoundPost', - uri: threadData.parent.uri, - notFound: true, - } - } else { - parent = composeThread( - threadData.parent, - feedService, - posts, - actors, - embeds, - blocks, - labels, - ) - } - } - - let replies: (ThreadViewPost | NotFoundPost | BlockedPost)[] | undefined - if (threadData.replies) { - replies = threadData.replies.flatMap((reply) => { - const thread = composeThread( - reply, - feedService, - posts, - actors, - embeds, - blocks, - labels, - ) - // e.g. don't bother including #postNotFound reply placeholders for takedowns. either way matches api contract. - const skip = [] - return isNotFoundPost(thread) ? skip : thread - }) - } - - return { - $type: 'app.bsky.feed.defs#threadViewPost', - post, - parent, - replies, - } -} - -const getRelevantIds = ( - thread: PostThread, -): { dids: Set; uris: Set } => { - const dids = new Set() - const uris = new Set() - if (thread.parent && !(thread.parent instanceof ParentNotFoundError)) { - const fromParent = getRelevantIds(thread.parent) - fromParent.dids.forEach((did) => dids.add(did)) - fromParent.uris.forEach((uri) => uris.add(uri)) - } - if (thread.replies) { - for (const reply of thread.replies) { - const fromChild = getRelevantIds(reply) - fromChild.dids.forEach((did) => dids.add(did)) - fromChild.uris.forEach((uri) => uris.add(uri)) - } - } - dids.add(thread.post.postAuthorDid) - uris.add(thread.post.postUri) - return { dids, uris } -} - -const getThreadData = async ( - ctx: AppContext, - uri: string, - depth: number, - parentHeight: number, -): Promise => { - const feedService = ctx.services.appView.feed(ctx.db) - const [parents, children] = await Promise.all([ - getAncestorsAndSelfQb(ctx.db.db, { uri, parentHeight }) - .selectFrom('ancestor') - .innerJoin( - feedService.selectPostQb().as('post'), - 'post.uri', - 'ancestor.uri', - ) - .selectAll('post') - .execute(), - getDescendentsQb(ctx.db.db, { uri, depth }) - .selectFrom('descendent') - .innerJoin( - feedService.selectPostQb().as('post'), - 'post.uri', - 'descendent.uri', - ) - .selectAll('post') - .orderBy('sortAt', 'desc') - .execute(), - ]) - const parentsByUri = parents.reduce((acc, parent) => { - return Object.assign(acc, { [parent.postUri]: parent }) - }, {} as Record) - const childrenByParentUri = children.reduce((acc, child) => { - if (!child.replyParent) return acc - acc[child.replyParent] ??= [] - acc[child.replyParent].push(child) - return acc - }, {} as Record) - const post = parentsByUri[uri] - if (!post) return null - return { - post, - parent: post.replyParent - ? getParentData(parentsByUri, post.replyParent, parentHeight) - : undefined, - replies: getChildrenData(childrenByParentUri, uri, depth), - } -} - -const getParentData = ( - postsByUri: Record, - uri: string, - depth: number, -): PostThread | ParentNotFoundError | undefined => { - if (depth === 0) return undefined - const post = postsByUri[uri] - if (!post) return new ParentNotFoundError(uri) - return { - post, - parent: post.replyParent - ? getParentData(postsByUri, post.replyParent, depth - 1) - : undefined, - replies: [], - } -} - -const getChildrenData = ( - childrenByParentUri: Record, - uri: string, - depth: number, -): PostThread[] | undefined => { - if (depth === 0) return undefined - const children = childrenByParentUri[uri] ?? [] - return children.map((row) => ({ - post: row, - replies: getChildrenData(childrenByParentUri, row.postUri, depth - 1), - })) -} - -class ParentNotFoundError extends Error { - constructor(public uri: string) { - super(`Parent not found: ${uri}`) - } -} - // READ AFTER WRITE // ---------------- diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getPosts.ts b/packages/pds/src/app-view/api/app/bsky/feed/getPosts.ts index 25bc3d652e4..f394ae57a08 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getPosts.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getPosts.ts @@ -1,45 +1,18 @@ -import * as common from '@atproto/common' import { Server } from '../../../../../lexicon' import AppContext from '../../../../../context' -import { PostView } from '../../../../../lexicon/types/app/bsky/feed/defs' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getPosts({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getPosts( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const uris = common.dedupeStrs(params.uris) - - const postViews = await ctx.services.appView - .feed(ctx.db) - .getPostViews(uris, requester) - - const posts: PostView[] = [] - for (const uri of uris) { - const post = postViews[uri] - const isBlocked = - post?.author.viewer?.blockedBy === true || - typeof post?.author.viewer?.blocking === 'string' - - if (post && !isBlocked) { - posts.push(post) - } - } - + const res = await ctx.appviewAgent.api.app.bsky.feed.getPosts( + params, + await ctx.serviceAuthHeaders(requester), + ) return { encoding: 'application/json', - body: { posts }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getRepostedBy.ts b/packages/pds/src/app-view/api/app/bsky/feed/getRepostedBy.ts index f00f9a1a2b5..9704597ad27 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getRepostedBy.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getRepostedBy.ts @@ -1,73 +1,18 @@ import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' export default function (server: Server, ctx: AppContext) { server.app.bsky.feed.getRepostedBy({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getRepostedBy( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { uri, limit, cursor, cid } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const graphService = ctx.services.appView.graph(ctx.db) - - let builder = db.db - .selectFrom('repost') - .where('repost.subject', '=', uri) - .innerJoin('did_handle as creator', 'creator.did', 'repost.creator') - .innerJoin( - 'repo_root as creator_repo', - 'creator_repo.did', - 'repost.creator', - ) - .where(notSoftDeletedClause(ref('creator_repo'))) - .whereNotExists( - graphService.blockQb(requester, [ref('repost.creator')]), - ) - .selectAll('creator') - .select(['repost.cid as cid', 'repost.createdAt as createdAt']) - - if (cid) { - builder = builder.where('repost.subjectCid', '=', cid) - } - - const keyset = new TimeCidKeyset( - ref('repost.createdAt'), - ref('repost.cid'), + const res = await ctx.appviewAgent.api.app.bsky.feed.getRepostedBy( + params, + await ctx.serviceAuthHeaders(requester), ) - builder = paginate(builder, { - limit, - cursor, - keyset, - }) - - const repostedByRes = await builder.execute() - const repostedBy = await services.appView - .actor(db) - .views.hydrateProfiles(repostedByRes, requester) - return { encoding: 'application/json', - body: { - uri, - cid, - repostedBy, - cursor: keyset.packFromResult(repostedByRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/feed/getTimeline.ts b/packages/pds/src/app-view/api/app/bsky/feed/getTimeline.ts index 5b1e29168a1..08676b3a943 100644 --- a/packages/pds/src/app-view/api/app/bsky/feed/getTimeline.ts +++ b/packages/pds/src/app-view/api/app/bsky/feed/getTimeline.ts @@ -1,10 +1,5 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { FeedAlgorithm, FeedKeyset, getFeedDateThreshold } from '../util/feed' -import { paginate } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { FeedRow } from '../../../../services/feed' -import { filterMutesAndBlocks } from './getFeed' import { OutputSchema } from '../../../../../lexicon/types/app/bsky/feed/getTimeline' import { handleReadAfterWrite } from '../util/read-after-write' import { LocalRecords } from '../../../../../services/local' @@ -14,100 +9,11 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - const { algorithm, limit, cursor } = params - if (algorithm && algorithm !== FeedAlgorithm.ReverseChronological) { - throw new InvalidRequestError(`Unsupported algorithm: ${algorithm}`) - } - - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.feed.getTimeline( - params, - await ctx.serviceAuthHeaders(requester), - ) - return await handleReadAfterWrite(ctx, requester, res, getTimelineMunge) - } - - if (ctx.cfg.bskyAppViewEndpoint) { - const res = - await ctx.appviewAgent.api.app.bsky.unspecced.getTimelineSkeleton( - { limit, cursor }, - await ctx.serviceAuthHeaders(requester), - ) - const filtered = await filterMutesAndBlocks( - ctx, - res.data, - limit, - requester, - ) - const hydrated = await ctx.services.appView - .feed(ctx.db) - .hydrateFeed(filtered.feedItems, requester) - return { - encoding: 'application/json', - body: { - cursor: filtered.cursor, - feed: hydrated, - }, - } - } - - const db = ctx.db.db - const { ref } = db.dynamic - - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const followingIdsSubquery = db - .selectFrom('follow') - .select('follow.subjectDid') - .where('follow.creator', '=', requester) - - const keyset = new FeedKeyset( - ref('feed_item.sortAt'), - ref('feed_item.cid'), + const res = await ctx.appviewAgent.api.app.bsky.feed.getTimeline( + params, + await ctx.serviceAuthHeaders(requester), ) - const sortFrom = keyset.unpack(cursor)?.primary - - let feedItemsQb = feedService - .selectFeedItemQb() - .where((qb) => - qb - .where('originatorDid', '=', requester) - .orWhere('originatorDid', 'in', followingIdsSubquery), - ) - .where((qb) => - // Hide posts and reposts of or by muted actors - accountService.whereNotMuted(qb, requester, [ - ref('post.creator'), - ref('originatorDid'), - ]), - ) - .whereNotExists( - graphService.blockQb(requester, [ - ref('post.creator'), - ref('originatorDid'), - ]), - ) - .where('feed_item.sortAt', '>', getFeedDateThreshold(sortFrom)) - - feedItemsQb = paginate(feedItemsQb, { - limit, - cursor, - keyset, - tryIndex: true, - }) - - const feedItems: FeedRow[] = await feedItemsQb.execute() - const feed = await feedService.hydrateFeed(feedItems, requester) - - return { - encoding: 'application/json', - body: { - feed, - cursor: keyset.packFromResult(feedItems), - }, - } + return await handleReadAfterWrite(ctx, requester, res, getTimelineMunge) }, }) } diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getBlocks.ts b/packages/pds/src/app-view/api/app/bsky/graph/getBlocks.ts index 11acf6352a5..52f7b4d6f7f 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getBlocks.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getBlocks.ts @@ -1,72 +1,18 @@ import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' export default function (server: Server, ctx: AppContext) { server.app.bsky.graph.getBlocks({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getBlocks( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { limit, cursor } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - let blocksReq = ctx.db.db - .selectFrom('actor_block') - .where('actor_block.creator', '=', requester) - .innerJoin( - 'did_handle as subject', - 'subject.did', - 'actor_block.subjectDid', - ) - .innerJoin( - 'repo_root as subject_repo', - 'subject_repo.did', - 'actor_block.subjectDid', - ) - .where(notSoftDeletedClause(ref('subject_repo'))) - .selectAll('subject') - .select([ - 'actor_block.cid as cid', - 'actor_block.createdAt as createdAt', - ]) - - const keyset = new TimeCidKeyset( - ref('actor_block.createdAt'), - ref('actor_block.cid'), + const res = await ctx.appviewAgent.api.app.bsky.graph.getBlocks( + params, + await ctx.serviceAuthHeaders(requester), ) - blocksReq = paginate(blocksReq, { - limit, - cursor, - keyset, - }) - - const blocksRes = await blocksReq.execute() - - const actorService = services.appView.actor(db) - const blocks = await actorService.views.hydrateProfiles( - blocksRes, - requester, - ) - return { encoding: 'application/json', - body: { - blocks, - cursor: keyset.packFromResult(blocksRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getFollowers.ts b/packages/pds/src/app-view/api/app/bsky/graph/getFollowers.ts index 73a38e83df2..0c7f23869eb 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getFollowers.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getFollowers.ts @@ -1,8 +1,5 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' import { authPassthru } from '../../../../../api/com/atproto/admin/util' export default function (server: Server, ctx: AppContext) { @@ -11,90 +8,13 @@ export default function (server: Server, ctx: AppContext) { handler: async ({ req, params, auth }) => { const requester = auth.credentials.type === 'access' ? auth.credentials.did : null - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getFollowers( - params, - requester - ? await ctx.serviceAuthHeaders(requester) - : authPassthru(req), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const canViewTakendownProfile = - auth.credentials.type === 'role' && auth.credentials.triage - const { actor, limit, cursor } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const actorService = services.appView.actor(db) - const graphService = services.appView.graph(db) - - const subjectRes = await actorService.getActor( - actor, - canViewTakendownProfile, + const res = await ctx.appviewAgent.api.app.bsky.graph.getFollowers( + params, + requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req), ) - if (!subjectRes) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - - let followersReq = ctx.db.db - .selectFrom('follow') - .where('follow.subjectDid', '=', subjectRes.did) - .innerJoin('did_handle as creator', 'creator.did', 'follow.creator') - .innerJoin( - 'repo_root as creator_repo', - 'creator_repo.did', - 'follow.creator', - ) - .if(!canViewTakendownProfile, (qb) => - qb.where(notSoftDeletedClause(ref('creator_repo'))), - ) - .whereNotExists( - graphService.blockQb(requester, [ref('follow.creator')]), - ) - .whereNotExists( - graphService.blockRefQb( - ref('follow.subjectDid'), - ref('follow.creator'), - ), - ) - .selectAll('creator') - .select(['follow.cid as cid', 'follow.createdAt as createdAt']) - - const keyset = new TimeCidKeyset( - ref('follow.createdAt'), - ref('follow.cid'), - ) - followersReq = paginate(followersReq, { - limit, - cursor, - keyset, - }) - - const followersRes = await followersReq.execute() - const [followers, subject] = await Promise.all([ - actorService.views.hydrateProfiles(followersRes, requester, { - includeSoftDeleted: canViewTakendownProfile, - }), - actorService.views.profile(subjectRes, requester, { - includeSoftDeleted: canViewTakendownProfile, - }), - ]) - if (!subject) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - return { encoding: 'application/json', - body: { - subject, - followers, - cursor: keyset.packFromResult(followersRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getFollows.ts b/packages/pds/src/app-view/api/app/bsky/graph/getFollows.ts index 3ebd47f6210..5871a213302 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getFollows.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getFollows.ts @@ -1,8 +1,5 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' import { authPassthru } from '../../../../../api/com/atproto/admin/util' export default function (server: Server, ctx: AppContext) { @@ -11,90 +8,13 @@ export default function (server: Server, ctx: AppContext) { handler: async ({ req, params, auth }) => { const requester = auth.credentials.type === 'access' ? auth.credentials.did : null - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getFollows( - params, - requester - ? await ctx.serviceAuthHeaders(requester) - : authPassthru(req), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const canViewTakendownProfile = - auth.credentials.type === 'role' && auth.credentials.triage - const { actor, limit, cursor } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const actorService = services.appView.actor(db) - const graphService = services.appView.graph(db) - - const creatorRes = await actorService.getActor( - actor, - canViewTakendownProfile, + const res = await ctx.appviewAgent.api.app.bsky.graph.getFollows( + params, + requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req), ) - if (!creatorRes) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - - let followsReq = ctx.db.db - .selectFrom('follow') - .where('follow.creator', '=', creatorRes.did) - .innerJoin('did_handle as subject', 'subject.did', 'follow.subjectDid') - .innerJoin( - 'repo_root as subject_repo', - 'subject_repo.did', - 'follow.subjectDid', - ) - .if(!canViewTakendownProfile, (qb) => - qb.where(notSoftDeletedClause(ref('subject_repo'))), - ) - .whereNotExists( - graphService.blockQb(requester, [ref('follow.subjectDid')]), - ) - .whereNotExists( - graphService.blockRefQb( - ref('follow.subjectDid'), - ref('follow.creator'), - ), - ) - .selectAll('subject') - .select(['follow.cid as cid', 'follow.createdAt as createdAt']) - - const keyset = new TimeCidKeyset( - ref('follow.createdAt'), - ref('follow.cid'), - ) - followsReq = paginate(followsReq, { - limit, - cursor, - keyset, - }) - - const followsRes = await followsReq.execute() - const [follows, subject] = await Promise.all([ - actorService.views.hydrateProfiles(followsRes, requester, { - includeSoftDeleted: canViewTakendownProfile, - }), - actorService.views.profile(creatorRes, requester, { - includeSoftDeleted: canViewTakendownProfile, - }), - ]) - if (!subject) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - return { encoding: 'application/json', - body: { - subject, - follows, - cursor: keyset.packFromResult(followsRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getList.ts b/packages/pds/src/app-view/api/app/bsky/graph/getList.ts index a7a1556ec18..ba9b9f9346f 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getList.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getList.ts @@ -1,6 +1,4 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' export default function (server: Server, ctx: AppContext) { @@ -8,86 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getList( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { list, limit, cursor } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const graphService = ctx.services.appView.graph(ctx.db) - - const listRes = await graphService - .getListsQb(requester) - .where('list.uri', '=', list) - .executeTakeFirst() - if (!listRes) { - throw new InvalidRequestError(`List not found: ${list}`) - } - - let itemsReq = graphService - .getListItemsQb() - .where('list_item.listUri', '=', list) - .where('list_item.creator', '=', listRes.creator) - - const keyset = new TimeCidKeyset( - ref('list_item.createdAt'), - ref('list_item.cid'), + const res = await ctx.appviewAgent.api.app.bsky.graph.getList( + params, + await ctx.serviceAuthHeaders(requester), ) - itemsReq = paginate(itemsReq, { - limit, - cursor, - keyset, - }) - const itemsRes = await itemsReq.execute() - - const actorService = services.appView.actor(db) - const profiles = await actorService.views.hydrateProfiles( - itemsRes, - requester, - ) - - const items = profiles.map((subject) => ({ subject })) - - const creator = await actorService.views.profile(listRes, requester) - if (!creator) { - throw new InvalidRequestError(`Actor not found: ${listRes.handle}`) - } - - const subject = { - uri: listRes.uri, - cid: listRes.cid, - creator, - name: listRes.name, - purpose: listRes.purpose, - description: listRes.description ?? undefined, - descriptionFacets: listRes.descriptionFacets - ? JSON.parse(listRes.descriptionFacets) - : undefined, - avatar: listRes.avatarCid - ? ctx.imgUriBuilder.getCommonSignedUri('avatar', listRes.avatarCid) - : undefined, - indexedAt: listRes.indexedAt, - viewer: { - muted: !!listRes.viewerMuted, - }, - } - return { encoding: 'application/json', - body: { - items, - list: subject, - cursor: keyset.packFromResult(itemsRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getListMutes.ts b/packages/pds/src/app-view/api/app/bsky/graph/getListMutes.ts index 673b2c61b38..adae96d58b0 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getListMutes.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getListMutes.ts @@ -1,5 +1,4 @@ import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' export default function (server: Server, ctx: AppContext) { @@ -7,54 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getListMutes( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { limit, cursor } = params - const { db } = ctx - const { ref } = db.db.dynamic - - const graphService = ctx.services.appView.graph(ctx.db) - - let listsReq = graphService - .getListsQb(requester) - .whereExists( - ctx.db.db - .selectFrom('list_mute') - .where('list_mute.mutedByDid', '=', requester) - .whereRef('list_mute.listUri', '=', ref('list.uri')) - .selectAll(), - ) - - const keyset = new TimeCidKeyset(ref('list.createdAt'), ref('list.cid')) - listsReq = paginate(listsReq, { - limit, - cursor, - keyset, - }) - const listsRes = await listsReq.execute() - - const actorService = ctx.services.appView.actor(ctx.db) - const profiles = await actorService.views.profiles(listsRes, requester) - - const lists = listsRes.map((row) => - graphService.formatListView(row, profiles), + const res = await ctx.appviewAgent.api.app.bsky.graph.getListMutes( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - lists, - cursor: keyset.packFromResult(listsRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getLists.ts b/packages/pds/src/app-view/api/app/bsky/graph/getLists.ts index c6653726459..893b6d5a9ad 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getLists.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getLists.ts @@ -1,6 +1,4 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' export default function (server: Server, ctx: AppContext) { @@ -8,61 +6,13 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getLists( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { actor, limit, cursor } = params - const { services, db } = ctx - const { ref } = db.db.dynamic - - const actorService = services.appView.actor(db) - const graphService = services.appView.graph(db) - - const creatorRes = await actorService.getActor(actor) - if (!creatorRes) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - - let listsReq = graphService - .getListsQb(requester) - .where('list.creator', '=', creatorRes.did) - - const keyset = new TimeCidKeyset(ref('list.createdAt'), ref('list.cid')) - listsReq = paginate(listsReq, { - limit, - cursor, - keyset, - }) - - const [listsRes, creator] = await Promise.all([ - listsReq.execute(), - actorService.views.profile(creatorRes, requester), - ]) - if (!creator) { - throw new InvalidRequestError(`Actor not found: ${actor}`) - } - const profileMap = { - [creator.did]: creator, - } - - const lists = listsRes.map((row) => - graphService.formatListView(row, profileMap), + const res = await ctx.appviewAgent.api.app.bsky.graph.getLists( + params, + await ctx.serviceAuthHeaders(requester), ) - return { encoding: 'application/json', - body: { - lists, - cursor: keyset.packFromResult(listsRes), - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/graph/getMutes.ts b/packages/pds/src/app-view/api/app/bsky/graph/getMutes.ts index a082666a968..596fef9dd15 100644 --- a/packages/pds/src/app-view/api/app/bsky/graph/getMutes.ts +++ b/packages/pds/src/app-view/api/app/bsky/graph/getMutes.ts @@ -1,68 +1,19 @@ import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause } from '../../../../../db/util' export default function (server: Server, ctx: AppContext) { server.app.bsky.graph.getMutes({ auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = await ctx.appviewAgent.api.app.bsky.graph.getMutes( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { limit, cursor } = params - const { services, db } = ctx - const { ref } = ctx.db.db.dynamic - - let mutesReq = ctx.db.db - .selectFrom('mute') - .innerJoin('did_handle as actor', 'actor.did', 'mute.did') - .innerJoin('repo_root', 'repo_root.did', 'mute.did') - .where(notSoftDeletedClause(ref('repo_root'))) - .where('mute.mutedByDid', '=', requester) - .selectAll('actor') - .select('mute.createdAt as createdAt') - - const keyset = new CreatedAtDidKeyset( - ref('mute.createdAt'), - ref('mute.did'), + const res = await ctx.appviewAgent.api.app.bsky.graph.getMutes( + params, + await ctx.serviceAuthHeaders(requester), ) - mutesReq = paginate(mutesReq, { - limit, - cursor, - keyset, - }) - - const mutesRes = await mutesReq.execute() - - // @NOTE calling into app-view, will eventually be replaced - const actorService = services.appView.actor(db) - return { encoding: 'application/json', - body: { - cursor: keyset.packFromResult(mutesRes), - mutes: await actorService.views.hydrateProfiles(mutesRes, requester), - }, + body: res.data, } }, }) } - -export class CreatedAtDidKeyset extends TimeCidKeyset<{ - createdAt: string - did: string // dids are treated identically to cids in TimeCidKeyset -}> { - labelResult(result: { createdAt: string; did: string }) { - return { primary: result.createdAt, secondary: result.did } - } -} diff --git a/packages/pds/src/app-view/api/app/bsky/index.ts b/packages/pds/src/app-view/api/app/bsky/index.ts index 96b0b5de06c..69cf8432224 100644 --- a/packages/pds/src/app-view/api/app/bsky/index.ts +++ b/packages/pds/src/app-view/api/app/bsky/index.ts @@ -6,7 +6,6 @@ import getSuggestedFeeds from './feed/getSuggestedFeeds' import getAuthorFeed from './feed/getAuthorFeed' import getFeedGenerator from './feed/getFeedGenerator' import getFeedGenerators from './feed/getFeedGenerators' -import describeFeedGenerator from './feed/describeFeedGenerator' import getFeed from './feed/getFeed' import getLikes from './feed/getLikes' import getListFeed from './feed/getListFeed' @@ -45,7 +44,6 @@ export default function (server: Server, ctx: AppContext) { getAuthorFeed(server, ctx) getFeedGenerator(server, ctx) getFeedGenerators(server, ctx) - describeFeedGenerator(server, ctx) getFeed(server, ctx) getLikes(server, ctx) getListFeed(server, ctx) diff --git a/packages/pds/src/app-view/api/app/bsky/notification/getUnreadCount.ts b/packages/pds/src/app-view/api/app/bsky/notification/getUnreadCount.ts index 262cfa06fe0..61c2b48f1e3 100644 --- a/packages/pds/src/app-view/api/app/bsky/notification/getUnreadCount.ts +++ b/packages/pds/src/app-view/api/app/bsky/notification/getUnreadCount.ts @@ -1,6 +1,4 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../../lexicon' -import { countAll, notSoftDeletedClause } from '../../../../../db/util' import AppContext from '../../../../../context' export default function (server: Server, ctx: AppContext) { @@ -8,51 +6,14 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = - await ctx.appviewAgent.api.app.bsky.notification.getUnreadCount( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { seenAt } = params - const { ref } = ctx.db.db.dynamic - if (seenAt) { - throw new InvalidRequestError('The seenAt parameter is unsupported') - } - - const accountService = ctx.services.account(ctx.db) - - const result = await ctx.db.db - .selectFrom('user_notification as notif') - .select(countAll.as('count')) - .innerJoin('user_account', 'user_account.did', 'notif.userDid') - .innerJoin('user_state', 'user_state.did', 'user_account.did') - .innerJoin( - 'repo_root as author_repo', - 'author_repo.did', - 'notif.author', - ) - .innerJoin('record', 'record.uri', 'notif.recordUri') - .where(notSoftDeletedClause(ref('author_repo'))) - .where(notSoftDeletedClause(ref('record'))) - .where('notif.userDid', '=', requester) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('notif.author')]), + const res = + await ctx.appviewAgent.api.app.bsky.notification.getUnreadCount( + params, + await ctx.serviceAuthHeaders(requester), ) - .whereRef('notif.indexedAt', '>', 'user_state.lastSeenNotifs') - .executeTakeFirst() - - const count = result?.count ?? 0 - return { encoding: 'application/json', - body: { count }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/notification/listNotifications.ts b/packages/pds/src/app-view/api/app/bsky/notification/listNotifications.ts index d3e44a90aa2..eefb3d29a48 100644 --- a/packages/pds/src/app-view/api/app/bsky/notification/listNotifications.ts +++ b/packages/pds/src/app-view/api/app/bsky/notification/listNotifications.ts @@ -1,171 +1,20 @@ -import { sql } from 'kysely' -import { InvalidRequestError } from '@atproto/xrpc-server' -import * as common from '@atproto/common' import { Server } from '../../../../../lexicon' -import { paginate, TimeCidKeyset } from '../../../../../db/pagination' import AppContext from '../../../../../context' -import { notSoftDeletedClause, valuesList } from '../../../../../db/util' -import { getSelfLabels } from '../../../../services/label' export default function (server: Server, ctx: AppContext) { server.app.bsky.notification.listNotifications({ auth: ctx.accessVerifier, handler: async ({ params, auth }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const res = - await ctx.appviewAgent.api.app.bsky.notification.listNotifications( - params, - await ctx.serviceAuthHeaders(requester), - ) - return { - encoding: 'application/json', - body: res.data, - } - } - - const { limit, cursor, seenAt } = params - const { ref } = ctx.db.db.dynamic - if (seenAt) { - throw new InvalidRequestError('The seenAt parameter is unsupported') - } - - const accountService = ctx.services.account(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - let notifBuilder = ctx.db.db - .selectFrom('user_notification as notif') - .innerJoin('did_handle as author', 'author.did', 'notif.author') - .innerJoin( - 'repo_root as author_repo', - 'author_repo.did', - 'notif.author', - ) - .innerJoin('record', 'record.uri', 'notif.recordUri') - .where(notSoftDeletedClause(ref('author_repo'))) - .where(notSoftDeletedClause(ref('record'))) - .where('notif.userDid', '=', requester) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('notif.author')]), + const res = + await ctx.appviewAgent.api.app.bsky.notification.listNotifications( + params, + await ctx.serviceAuthHeaders(requester), ) - .whereNotExists(graphService.blockQb(requester, [ref('notif.author')])) - .where((clause) => - clause - .where('reasonSubject', 'is', null) - .orWhereExists( - ctx.db.db - .selectFrom('record as subject') - .selectAll() - .whereRef('subject.uri', '=', ref('notif.reasonSubject')), - ), - ) - .select([ - 'notif.recordUri as uri', - 'notif.recordCid as cid', - 'author.did as authorDid', - 'author.handle as authorHandle', - 'notif.reason as reason', - 'notif.reasonSubject as reasonSubject', - 'notif.indexedAt as indexedAt', - ]) - - const keyset = new NotifsKeyset( - ref('notif.indexedAt'), - ref('notif.recordCid'), - ) - notifBuilder = paginate(notifBuilder, { - cursor, - limit, - keyset, - }) - - const userStateQuery = ctx.db.db - .selectFrom('user_state') - .selectAll() - .where('did', '=', requester) - .executeTakeFirst() - - const [userState, notifs] = await Promise.all([ - userStateQuery, - notifBuilder.execute(), - ]) - - if (!userState) { - throw new InvalidRequestError(`Could not find user: ${requester}`) - } - - const recordTuples = notifs.map((notif) => { - return sql`${notif.authorDid}, ${notif.cid}` - }) - - const emptyBlocksResult: { cid: string; bytes: Uint8Array }[] = [] - const blocksQb = recordTuples.length - ? ctx.db.db - .selectFrom('ipld_block') - .whereRef(sql`(creator, cid)`, 'in', valuesList(recordTuples)) - .select(['cid', 'content as bytes']) - : null - - const actorService = ctx.services.appView.actor(ctx.db) - - // @NOTE calling into app-view, will eventually be replaced - const labelService = ctx.services.appView.label(ctx.db) - const recordUris = notifs.map((notif) => notif.uri) - const [blocks, authors, labels] = await Promise.all([ - blocksQb ? blocksQb.execute() : emptyBlocksResult, - actorService.views.profiles( - notifs.map((notif) => ({ - did: notif.authorDid, - handle: notif.authorHandle, - })), - requester, - ), - labelService.getLabelsForUris(recordUris), - ]) - - const bytesByCid = blocks.reduce((acc, block) => { - acc[block.cid] = block.bytes - return acc - }, {} as Record) - - const notifications = common.mapDefined(notifs, (notif) => { - const bytes = bytesByCid[notif.cid] - const author = authors[notif.authorDid] - if (!bytes || !author) return undefined - const record = common.cborBytesToRecord(bytes) - const recordLabels = labels[notif.uri] ?? [] - const recordSelfLabels = getSelfLabels({ - uri: notif.uri, - cid: notif.cid, - record, - }) - return { - uri: notif.uri, - cid: notif.cid, - author: authors[notif.authorDid], - reason: notif.reason, - reasonSubject: notif.reasonSubject || undefined, - record, - isRead: notif.indexedAt <= userState.lastSeenNotifs, - indexedAt: notif.indexedAt, - labels: [...recordLabels, ...recordSelfLabels], - } - }) - return { encoding: 'application/json', - body: { - notifications, - cursor: keyset.packFromResult(notifs), - }, + body: res.data, } }, }) } - -type NotifRow = { indexedAt: string; cid: string } -class NotifsKeyset extends TimeCidKeyset { - labelResult(result: NotifRow) { - return { primary: result.indexedAt, secondary: result.cid } - } -} diff --git a/packages/pds/src/app-view/api/app/bsky/unspecced.ts b/packages/pds/src/app-view/api/app/bsky/unspecced.ts index 9dc3f77aba4..482adb3dbd8 100644 --- a/packages/pds/src/app-view/api/app/bsky/unspecced.ts +++ b/packages/pds/src/app-view/api/app/bsky/unspecced.ts @@ -1,129 +1,29 @@ -import { NotEmptyArray } from '@atproto/common' import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server' import { Server } from '../../../../lexicon' -import { GenericKeyset, paginate } from '../../../../db/pagination' +import { GenericKeyset } from '../../../../db/pagination' import AppContext from '../../../../context' -import { FeedRow } from '../../../services/feed' -import { - isPostView, - GeneratorView, -} from '../../../../lexicon/types/app/bsky/feed/defs' -import { isViewRecord } from '../../../../lexicon/types/app/bsky/embed/record' -import { countAll, valuesList } from '../../../../db/util' -import { FeedKeyset } from './util/feed' -const NO_WHATS_HOT_LABELS: NotEmptyArray = [ - '!no-promote', - 'corpse', - 'self-harm', -] - -const NSFW_LABELS = ['porn', 'sexual', 'nudity', 'underwear'] - -// @NOTE currently relies on the hot-classic feed being configured on the pds // THIS IS A TEMPORARY UNSPECCED ROUTE export default function (server: Server, ctx: AppContext) { server.app.bsky.unspecced.getPopular({ auth: ctx.accessVerifier, - handler: async ({ params, auth }) => { + handler: async ({ auth, params }) => { const requester = auth.credentials.did - if (ctx.canProxyRead()) { - const hotClassicUri = Object.keys(ctx.algos).find((uri) => - uri.endsWith('/hot-classic'), - ) - if (!hotClassicUri) { - return { - encoding: 'application/json', - body: { feed: [] }, - } - } - const { data: feed } = - await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator( - { feed: hotClassicUri }, - await ctx.serviceAuthHeaders(requester), - ) - const res = await ctx.appviewAgent.api.app.bsky.feed.getFeed( - { feed: hotClassicUri, limit: params.limit, cursor: params.cursor }, - await ctx.serviceAuthHeaders(requester, feed.view.did), - ) - return { - encoding: 'application/json', - body: res.data, - } + const HOT_CLASSIC_URI = + 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/hot-classic' + const HOT_CLASSIC_DID = 'did:plc:5fllqkujj6kqp5izd5jg7gox' + const res = await ctx.appviewAgent.api.app.bsky.feed.getFeed( + { feed: HOT_CLASSIC_URI, limit: params.limit, cursor: params.cursor }, + await ctx.serviceAuthHeaders(requester, HOT_CLASSIC_DID), + ) + return { + encoding: 'application/json', + body: res.data, } - const { limit, cursor, includeNsfw } = params - const db = ctx.db.db - const { ref } = db.dynamic - - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const labelsToFilter = includeNsfw - ? NO_WHATS_HOT_LABELS - : [...NO_WHATS_HOT_LABELS, ...NSFW_LABELS] - - const postsQb = feedService - .selectPostQb() - .leftJoin('post_agg', 'post_agg.uri', 'post.uri') - .where('post_agg.likeCount', '>=', 12) - .where('post.replyParent', 'is', null) - .whereNotExists((qb) => - qb - .selectFrom('label') - .selectAll() - .whereRef('val', 'in', valuesList(labelsToFilter)) - .where('neg', '=', 0) - .where((clause) => - clause - .whereRef('label.uri', '=', ref('post.creator')) - .orWhereRef('label.uri', '=', ref('post.uri')), - ), - ) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - - const keyset = new FeedKeyset(ref('sortAt'), ref('cid')) - - let feedQb = ctx.db.db.selectFrom(postsQb.as('feed_items')).selectAll() - feedQb = paginate(feedQb, { limit, cursor, keyset }) - - const feedItems: FeedRow[] = await feedQb.execute() - const feed = await feedService.hydrateFeed(feedItems, requester) - - // filter out any quote post where the internal post has a filtered label - const noLabeledQuotePosts = feed.filter((post) => { - const quoteView = post.post.embed?.record - if (!quoteView || !isViewRecord(quoteView)) return true - for (const label of quoteView.labels || []) { - if (labelsToFilter.includes(label.val)) return false - } - return true - }) - - // remove record embeds in our response - const noRecordEmbeds = noLabeledQuotePosts.map((post) => { - delete post.post.record['embed'] - if (post.reply) { - if (isPostView(post.reply.parent)) { - delete post.reply.parent.record['embed'] - } - if (isPostView(post.reply.root)) { - delete post.reply.root.record['embed'] - } - } - return post - }) - return { encoding: 'application/json', - body: { - feed: noRecordEmbeds, - cursor: keyset.packFromResult(feedItems), - }, + body: { feed: [] }, } }, }) @@ -132,62 +32,14 @@ export default function (server: Server, ctx: AppContext) { auth: ctx.accessVerifier, handler: async ({ auth, params }) => { const requester = auth.credentials.did - const db = ctx.db.db - const { limit, cursor, query } = params - const { ref } = db.dynamic - const feedService = ctx.services.appView.feed(ctx.db) - - let inner = ctx.db.db - .selectFrom('feed_generator') - .select([ - 'uri', - 'cid', - ctx.db.db - .selectFrom('like') - .whereRef('like.subject', '=', ref('feed_generator.uri')) - .select(countAll.as('count')) - .as('likeCount'), - ]) - - if (query) { - // like is case-insensitive is sqlite, and ilike is not supported - const operator = ctx.db.dialect === 'pg' ? 'ilike' : 'like' - inner = inner.where((qb) => - qb - .where('feed_generator.displayName', operator, `%${query}%`) - .orWhere('feed_generator.description', operator, `%${query}%`), + const res = + await ctx.appviewAgent.api.app.bsky.unspecced.getPopularFeedGenerators( + params, + await ctx.serviceAuthHeaders(requester), ) - } - - let builder = ctx.db.db.selectFrom(inner.as('feed_gens')).selectAll() - - const keyset = new LikeCountKeyset(ref('likeCount'), ref('cid')) - builder = paginate(builder, { limit, cursor, keyset, direction: 'desc' }) - - const res = await builder.execute() - - const genInfos = await feedService.getFeedGeneratorInfos( - res.map((feed) => feed.uri), - requester, - ) - - const creators = Object.values(genInfos).map((gen) => gen.creator) - const profiles = await feedService.getActorInfos(creators, requester) - - const genViews: GeneratorView[] = [] - for (const row of res) { - const gen = genInfos[row.uri] - if (!gen) continue - const view = feedService.views.formatFeedGeneratorView(gen, profiles) - genViews.push(view) - } - return { encoding: 'application/json', - body: { - cursor: keyset.packFromResult(res), - feeds: genViews, - }, + body: res.data, } }, }) diff --git a/packages/pds/src/app-view/api/app/bsky/util/feed.ts b/packages/pds/src/app-view/api/app/bsky/util/feed.ts deleted file mode 100644 index 9d9d0323b95..00000000000 --- a/packages/pds/src/app-view/api/app/bsky/util/feed.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { TimeCidKeyset } from '../../../../../db/pagination' -import { FeedRow } from '../../../../services/feed' - -export enum FeedAlgorithm { - ReverseChronological = 'reverse-chronological', -} - -export class FeedKeyset extends TimeCidKeyset { - labelResult(result: FeedRow) { - return { primary: result.sortAt, secondary: result.cid } - } -} - -// For users with sparse feeds, avoid scanning more than one week for a single page -export const getFeedDateThreshold = (from: string | undefined, days = 1) => { - const timelineDateThreshold = from ? new Date(from) : new Date() - timelineDateThreshold.setDate(timelineDateThreshold.getDate() - days) - return timelineDateThreshold.toISOString() -} diff --git a/packages/pds/src/app-view/services/actor/index.ts b/packages/pds/src/app-view/services/actor/index.ts deleted file mode 100644 index e6c6fd6e756..00000000000 --- a/packages/pds/src/app-view/services/actor/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -import Database from '../../../db' -import { DidHandle } from '../../../db/tables/did-handle' -import { notSoftDeletedClause } from '../../../db/util' -import { ActorViews } from './views' -import { ImageUriBuilder } from '../../../image/uri' -import { LabelCache } from '../../../label-cache' - -export class ActorService { - constructor( - public db: Database, - public imgUriBuilder: ImageUriBuilder, - public labelCache: LabelCache, - ) {} - - static creator(imgUriBuilder: ImageUriBuilder, labelCache: LabelCache) { - return (db: Database) => new ActorService(db, imgUriBuilder, labelCache) - } - - views = new ActorViews(this.db, this.imgUriBuilder, this.labelCache) - - async getActor( - handleOrDid: string, - includeSoftDeleted = false, - ): Promise { - const actors = await this.getActors([handleOrDid], includeSoftDeleted) - return actors[0] || null - } - - async getActors( - handleOrDids: string[], - includeSoftDeleted = false, - ): Promise { - const { ref } = this.db.db.dynamic - const dids: string[] = [] - const handles: string[] = [] - const order: Record = {} - handleOrDids.forEach((item, i) => { - if (item.startsWith('did:')) { - order[item] = i - dids.push(item) - } else { - order[item.toLowerCase()] = i - handles.push(item.toLowerCase()) - } - }) - const results = await this.db.db - .selectFrom('did_handle') - .innerJoin('repo_root', 'repo_root.did', 'did_handle.did') - .if(!includeSoftDeleted, (qb) => - qb.where(notSoftDeletedClause(ref('repo_root'))), - ) - .where((qb) => { - if (dids.length) { - qb = qb.orWhere('did_handle.did', 'in', dids) - } - if (handles.length) { - qb = qb.orWhere('did_handle.handle', 'in', handles) - } - return qb - }) - .selectAll('did_handle') - .select('takedownId') - .execute() - - return results.sort((a, b) => { - const orderA = order[a.did] ?? order[a.handle.toLowerCase()] - const orderB = order[b.did] ?? order[b.handle.toLowerCase()] - return orderA - orderB - }) - } -} - -type ActorResult = DidHandle & { takedownId: number | null } diff --git a/packages/pds/src/app-view/services/actor/views.ts b/packages/pds/src/app-view/services/actor/views.ts deleted file mode 100644 index 3e4a1a91f7f..00000000000 --- a/packages/pds/src/app-view/services/actor/views.ts +++ /dev/null @@ -1,374 +0,0 @@ -import { mapDefined } from '@atproto/common' -import { cborToLexRecord } from '@atproto/repo' -import { - ProfileViewDetailed, - ProfileView, - ProfileViewBasic, -} from '../../../lexicon/types/app/bsky/actor/defs' -import { DidHandle } from '../../../db/tables/did-handle' -import Database from '../../../db' -import { ImageUriBuilder } from '../../../image/uri' -import { LabelService, getSelfLabels } from '../label' -import { GraphService } from '../graph' -import { LabelCache } from '../../../label-cache' -import { notSoftDeletedClause } from '../../../db/util' - -export class ActorViews { - constructor( - private db: Database, - private imgUriBuilder: ImageUriBuilder, - private labelCache: LabelCache, - ) {} - - services = { - label: LabelService.creator(this.labelCache)(this.db), - graph: GraphService.creator(this.imgUriBuilder)(this.db), - } - - async profilesDetailed( - results: ActorResult[], - viewer: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise> { - if (results.length === 0) return {} - - const { ref } = this.db.db.dynamic - const { skipLabels = false, includeSoftDeleted = false } = opts ?? {} - - const dids = results.map((r) => r.did) - - const profileInfosQb = this.db.db - .selectFrom('did_handle') - .where('did_handle.did', 'in', dids) - .innerJoin('repo_root', 'repo_root.did', 'did_handle.did') - .leftJoin('profile', 'profile.creator', 'did_handle.did') - .leftJoin('profile_agg', 'profile_agg.did', 'did_handle.did') - .leftJoin('ipld_block', (join) => - join - .onRef('ipld_block.cid', '=', 'profile.cid') - .onRef('ipld_block.creator', '=', 'profile.creator'), - ) - .if(!includeSoftDeleted, (qb) => - qb.where(notSoftDeletedClause(ref('repo_root'))), - ) - .select([ - 'did_handle.did as did', - 'did_handle.handle as handle', - 'profile.uri as profileUri', - 'profile.cid as profileCid', - 'profile.displayName as displayName', - 'profile.description as description', - 'profile.avatarCid as avatarCid', - 'profile.bannerCid as bannerCid', - 'profile.indexedAt as indexedAt', - 'profile_agg.followsCount as followsCount', - 'profile_agg.followersCount as followersCount', - 'profile_agg.postsCount as postsCount', - 'ipld_block.content as profileBytes', - this.db.db - .selectFrom('follow') - .where('creator', '=', viewer ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterFollowing'), - this.db.db - .selectFrom('follow') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', viewer ?? '') - .select('uri') - .as('requesterFollowedBy'), - this.db.db - .selectFrom('actor_block') - .where('creator', '=', viewer ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterBlocking'), - this.db.db - .selectFrom('actor_block') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', viewer ?? '') - .select('uri') - .as('requesterBlockedBy'), - this.db.db - .selectFrom('mute') - .whereRef('did', '=', ref('did_handle.did')) - .where('mutedByDid', '=', viewer ?? '') - .select('did') - .as('requesterMuted'), - this.db.db - .selectFrom('list_item') - .innerJoin('list_mute', 'list_mute.listUri', 'list_item.listUri') - .where('list_mute.mutedByDid', '=', viewer ?? '') - .whereRef('list_item.subjectDid', '=', ref('did_handle.did')) - .select('list_item.listUri') - .limit(1) - .as('requesterMutedByList'), - ]) - - const [profileInfos, labels] = await Promise.all([ - profileInfosQb.execute(), - this.services.label.getLabelsForSubjects(skipLabels ? [] : dids), - ]) - - const listUris: string[] = profileInfos - .map((a) => a.requesterMutedByList) - .filter((list) => !!list) - const listViews = await this.services.graph.getListViews(listUris, viewer) - - return profileInfos.reduce((acc, cur) => { - const avatar = cur?.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', cur.avatarCid) - : undefined - const banner = cur?.bannerCid - ? this.imgUriBuilder.getCommonSignedUri('banner', cur.bannerCid) - : undefined - const mutedByList = - cur.requesterMutedByList && listViews[cur.requesterMutedByList] - ? this.services.graph.formatListViewBasic( - listViews[cur.requesterMutedByList], - ) - : undefined - const actorLabels = labels[cur.did] ?? [] - const selfLabels = getSelfLabels({ - uri: cur.profileUri, - cid: cur.profileCid, - record: cur.profileBytes && cborToLexRecord(cur.profileBytes), - }) - const profile = { - did: cur.did, - handle: cur.handle, - displayName: truncateUtf8(cur?.displayName, 64) || undefined, - description: truncateUtf8(cur?.description, 256) || undefined, - avatar, - banner, - followsCount: cur?.followsCount || 0, - followersCount: cur?.followersCount || 0, - postsCount: cur?.postsCount || 0, - indexedAt: cur?.indexedAt || undefined, - viewer: { - muted: !!cur?.requesterMuted || !!cur?.requesterMutedByList, - mutedByList, - blockedBy: !!cur.requesterBlockedBy, - blocking: cur.requesterBlocking || undefined, - following: cur?.requesterFollowing || undefined, - followedBy: cur?.requesterFollowedBy || undefined, - }, - labels: skipLabels ? undefined : [...actorLabels, ...selfLabels], - } - acc[cur.did] = profile - return acc - }, {} as Record) - } - - async hydrateProfilesDetailed( - results: ActorResult[], - viewer: string, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profilesDetailed(results, viewer, opts) - return mapDefined(results, (result) => profiles[result.did]) - } - - async profileDetailed( - result: ActorResult, - viewer: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profilesDetailed([result], viewer, opts) - return profiles[result.did] ?? null - } - - async profiles( - results: ActorResult[], - viewer: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise> { - if (results.length === 0) return {} - - const { ref } = this.db.db.dynamic - const { skipLabels = false, includeSoftDeleted = false } = opts ?? {} - const dids = results.map((r) => r.did) - - const profileInfosQb = this.db.db - .selectFrom('did_handle') - .where('did_handle.did', 'in', dids) - .innerJoin('repo_root', 'repo_root.did', 'did_handle.did') - .leftJoin('profile', 'profile.creator', 'did_handle.did') - .leftJoin('ipld_block', (join) => - join - .onRef('ipld_block.cid', '=', 'profile.cid') - .onRef('ipld_block.creator', '=', 'profile.creator'), - ) - .if(!includeSoftDeleted, (qb) => - qb.where(notSoftDeletedClause(ref('repo_root'))), - ) - .select([ - 'did_handle.did as did', - 'did_handle.handle as handle', - 'profile.uri as profileUri', - 'profile.cid as profileCid', - 'profile.displayName as displayName', - 'profile.description as description', - 'profile.avatarCid as avatarCid', - 'profile.indexedAt as indexedAt', - 'ipld_block.content as profileBytes', - this.db.db - .selectFrom('follow') - .where('creator', '=', viewer ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterFollowing'), - this.db.db - .selectFrom('follow') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', viewer ?? '') - .select('uri') - .as('requesterFollowedBy'), - this.db.db - .selectFrom('actor_block') - .where('creator', '=', viewer ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterBlocking'), - this.db.db - .selectFrom('actor_block') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', viewer ?? '') - .select('uri') - .as('requesterBlockedBy'), - this.db.db - .selectFrom('mute') - .whereRef('did', '=', ref('did_handle.did')) - .where('mutedByDid', '=', viewer ?? '') - .select('did') - .as('requesterMuted'), - this.db.db - .selectFrom('list_item') - .innerJoin('list_mute', 'list_mute.listUri', 'list_item.listUri') - .where('list_mute.mutedByDid', '=', viewer ?? '') - .whereRef('list_item.subjectDid', '=', ref('did_handle.did')) - .select('list_item.listUri') - .limit(1) - .as('requesterMutedByList'), - ]) - - const [profileInfos, labels] = await Promise.all([ - profileInfosQb.execute(), - this.services.label.getLabelsForSubjects(skipLabels ? [] : dids), - ]) - - const listUris: string[] = profileInfos - .map((a) => a.requesterMutedByList) - .filter((list) => !!list) - const listViews = await this.services.graph.getListViews(listUris, viewer) - - return profileInfos.reduce((acc, cur) => { - const avatar = cur.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', cur.avatarCid) - : undefined - const mutedByList = - cur.requesterMutedByList && listViews[cur.requesterMutedByList] - ? this.services.graph.formatListViewBasic( - listViews[cur.requesterMutedByList], - ) - : undefined - const actorLabels = labels[cur.did] ?? [] - const selfLabels = getSelfLabels({ - uri: cur.profileUri, - cid: cur.profileCid, - record: cur.profileBytes && cborToLexRecord(cur.profileBytes), - }) - const profile = { - did: cur.did, - handle: cur.handle, - displayName: truncateUtf8(cur?.displayName, 64) || undefined, - description: truncateUtf8(cur?.description, 256) || undefined, - avatar, - indexedAt: cur?.indexedAt || undefined, - viewer: { - muted: !!cur?.requesterMuted || !!cur?.requesterMutedByList, - mutedByList, - blockedBy: !!cur.requesterBlockedBy, - blocking: cur.requesterBlocking || undefined, - following: cur?.requesterFollowing || undefined, - followedBy: cur?.requesterFollowedBy || undefined, - }, - labels: skipLabels ? undefined : [...actorLabels, ...selfLabels], - } - acc[cur.did] = profile - return acc - }, {} as Record) - } - - async hydrateProfiles( - results: ActorResult[], - viewer: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profiles(results, viewer, opts) - return mapDefined(results, (result) => profiles[result.did]) - } - - async profile( - result: ActorResult, - viewer: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profiles([result], viewer, opts) - return profiles[result.did] ?? null - } - - // @NOTE keep in sync with feedService.getActorViews() - async profilesBasic( - results: ActorResult[], - viewer: string, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise> { - if (results.length === 0) return {} - const profiles = await this.profiles(results, viewer, opts) - return Object.values(profiles).reduce((acc, cur) => { - const profile = { - did: cur.did, - handle: cur.handle, - displayName: truncateUtf8(cur.displayName, 64) || undefined, - avatar: cur.avatar, - viewer: cur.viewer, - labels: cur.labels, - } - acc[cur.did] = profile - return acc - }, {} as Record) - } - - async hydrateProfilesBasic( - results: ActorResult[], - viewer: string, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profilesBasic(results, viewer, opts) - return mapDefined(results, (result) => profiles[result.did]) - } - - async profileBasic( - result: ActorResult, - viewer: string, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, - ): Promise { - const profiles = await this.profilesBasic([result], viewer, opts) - return profiles[result.did] ?? null - } -} - -type ActorResult = DidHandle - -function truncateUtf8(str: string | null | undefined, length: number) { - if (!str) return str - const encoder = new TextEncoder() - const utf8 = encoder.encode(str) - if (utf8.length > length) { - const decoder = new TextDecoder('utf-8', { fatal: false }) - const truncated = utf8.slice(0, length) - return decoder.decode(truncated).replace(/\uFFFD$/, '') - } - return str -} diff --git a/packages/pds/src/app-view/services/feed/index.ts b/packages/pds/src/app-view/services/feed/index.ts deleted file mode 100644 index a7f153b7a76..00000000000 --- a/packages/pds/src/app-view/services/feed/index.ts +++ /dev/null @@ -1,685 +0,0 @@ -import { sql } from 'kysely' -import { AtUri } from '@atproto/syntax' -import { dedupeStrs } from '@atproto/common' -import { cborToLexRecord } from '@atproto/repo' -import Database from '../../../db' -import { countAll, notSoftDeletedClause, valuesList } from '../../../db/util' -import { ImageUriBuilder } from '../../../image/uri' -import { ids } from '../../../lexicon/lexicons' -import { - Record as PostRecord, - isRecord as isPostRecord, -} from '../../../lexicon/types/app/bsky/feed/post' -import { isMain as isEmbedImages } from '../../../lexicon/types/app/bsky/embed/images' -import { isMain as isEmbedExternal } from '../../../lexicon/types/app/bsky/embed/external' -import { - isMain as isEmbedRecord, - isViewRecord, -} from '../../../lexicon/types/app/bsky/embed/record' -import { isMain as isEmbedRecordWithMedia } from '../../../lexicon/types/app/bsky/embed/recordWithMedia' -import { FeedViewPost } from '../../../lexicon/types/app/bsky/feed/defs' -import { - ActorInfoMap, - PostInfoMap, - FeedItemType, - FeedRow, - FeedGenInfoMap, - PostViews, - PostEmbedViews, - RecordEmbedViewRecordMap, - PostBlocksMap, - RecordEmbedViewRecord, - FeedHydrationOptions, - kSelfLabels, -} from './types' -import { LabelService, Labels, getSelfLabels } from '../label' -import { ActorService } from '../actor' -import { GraphService } from '../graph' -import { FeedViews } from './views' -import { LabelCache } from '../../../label-cache' - -export * from './types' - -export class FeedService { - constructor( - public db: Database, - public imgUriBuilder: ImageUriBuilder, - public labelCache: LabelCache, - ) {} - - static creator(imgUriBuilder: ImageUriBuilder, labelCache: LabelCache) { - return (db: Database) => new FeedService(db, imgUriBuilder, labelCache) - } - - views = new FeedViews(this.db, this.imgUriBuilder) - services = { - label: LabelService.creator(this.labelCache)(this.db), - actor: ActorService.creator(this.imgUriBuilder, this.labelCache)(this.db), - graph: GraphService.creator(this.imgUriBuilder)(this.db), - } - - selectPostQb() { - return this.db.db - .selectFrom('post') - .select([ - sql`${'post'}`.as('type'), - 'post.uri as uri', - 'post.cid as cid', - 'post.uri as postUri', - 'post.creator as originatorDid', - 'post.creator as postAuthorDid', - 'post.replyParent as replyParent', - 'post.replyRoot as replyRoot', - 'post.indexedAt as sortAt', - ]) - } - - selectFeedItemQb() { - return this.db.db - .selectFrom('feed_item') - .innerJoin('post', 'post.uri', 'feed_item.postUri') - .selectAll('feed_item') - .select([ - 'post.replyRoot', - 'post.replyParent', - 'post.creator as postAuthorDid', - ]) - } - - selectFeedGeneratorQb(requester: string | null) { - const { ref } = this.db.db.dynamic - return this.db.db - .selectFrom('feed_generator') - .innerJoin('did_handle', 'did_handle.did', 'feed_generator.creator') - .innerJoin( - 'repo_root as creator_repo', - 'creator_repo.did', - 'feed_generator.creator', - ) - .innerJoin('record', 'record.uri', 'feed_generator.uri') - .selectAll() - .where(notSoftDeletedClause(ref('creator_repo'))) - .where(notSoftDeletedClause(ref('record'))) - .select((qb) => - qb - .selectFrom('like') - .whereRef('like.subject', '=', 'feed_generator.uri') - .select(countAll.as('count')) - .as('likeCount'), - ) - .select((qb) => - qb - .selectFrom('like') - .where('like.creator', '=', requester ?? '') - .whereRef('like.subject', '=', 'feed_generator.uri') - .select('uri') - .as('viewerLike'), - ) - } - - // @NOTE keep in sync with actorService.views.profile() - async getActorInfos( - dids: string[], - requester: string | null, - opts?: { skipLabels?: boolean; includeSoftDeleted?: boolean }, // @NOTE used by hydrateFeed() to batch label hydration - ): Promise { - if (dids.length < 1) return {} - const { ref } = this.db.db.dynamic - const { skipLabels = false, includeSoftDeleted = false } = opts ?? {} - const [actors, labels] = await Promise.all([ - this.db.db - .selectFrom('did_handle') - .where('did_handle.did', 'in', dids) - .innerJoin('repo_root', 'repo_root.did', 'did_handle.did') - .leftJoin('profile', 'profile.creator', 'did_handle.did') - .leftJoin('ipld_block', (join) => - join - .onRef('ipld_block.cid', '=', 'profile.cid') - .onRef('ipld_block.creator', '=', 'profile.creator'), - ) - .selectAll('did_handle') - .if(!includeSoftDeleted, (qb) => - qb.where(notSoftDeletedClause(ref('repo_root'))), - ) - .select([ - 'profile.uri as profileUri', - 'profile.cid as profileCid', - 'profile.displayName as displayName', - 'profile.description as description', - 'profile.avatarCid as avatarCid', - 'profile.indexedAt as indexedAt', - 'ipld_block.content as profileBytes', - this.db.db - .selectFrom('follow') - .where('creator', '=', requester ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterFollowing'), - this.db.db - .selectFrom('follow') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', requester ?? '') - .select('uri') - .as('requesterFollowedBy'), - this.db.db - .selectFrom('actor_block') - .where('creator', '=', requester ?? '') - .whereRef('subjectDid', '=', ref('did_handle.did')) - .select('uri') - .as('requesterBlocking'), - this.db.db - .selectFrom('actor_block') - .whereRef('creator', '=', ref('did_handle.did')) - .where('subjectDid', '=', requester ?? '') - .select('uri') - .as('requesterBlockedBy'), - this.db.db - .selectFrom('mute') - .whereRef('did', '=', ref('did_handle.did')) - .where('mutedByDid', '=', requester ?? '') - .select('did') - .as('requesterMuted'), - this.db.db - .selectFrom('list_item') - .innerJoin('list_mute', 'list_mute.listUri', 'list_item.listUri') - .where('list_mute.mutedByDid', '=', requester ?? '') - .whereRef('list_item.subjectDid', '=', ref('did_handle.did')) - .select('list_item.listUri') - .limit(1) - .as('requesterMutedByList'), - ]) - .execute(), - this.services.label.getLabelsForSubjects(skipLabels ? [] : dids), - ]) - const listUris: string[] = actors - .map((a) => a.requesterMutedByList) - .filter((list) => !!list) - const listViews = await this.services.graph.getListViews( - listUris, - requester, - ) - return actors.reduce((acc, cur) => { - const avatar = cur.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', cur.avatarCid) - : undefined - const mutedByList = - cur.requesterMutedByList && listViews[cur.requesterMutedByList] - ? this.services.graph.formatListViewBasic( - listViews[cur.requesterMutedByList], - ) - : undefined - const actorLabels = labels[cur.did] ?? [] - const selfLabels = getSelfLabels({ - uri: cur.profileUri, - cid: cur.profileCid, - record: cur.profileBytes && cborToLexRecord(cur.profileBytes), - }) - return { - ...acc, - [cur.did]: { - did: cur.did, - handle: cur.handle, - displayName: truncateUtf8(cur.displayName, 64) || undefined, - avatar, - viewer: { - muted: !!cur?.requesterMuted || !!cur?.requesterMutedByList, - mutedByList, - blockedBy: !!cur?.requesterBlockedBy, - blocking: cur?.requesterBlocking || undefined, - following: cur?.requesterFollowing || undefined, - followedBy: cur?.requesterFollowedBy || undefined, - }, - labels: skipLabels ? undefined : [...actorLabels, ...selfLabels], - [kSelfLabels]: selfLabels, - }, - } - }, {} as ActorInfoMap) - } - - async getPostInfos( - postUris: string[], - requester: string | null, - options?: Pick, - ): Promise { - if (postUris.length < 1) return {} - const db = this.db.db - const { ref } = db.dynamic - let postsQb = db - .selectFrom('post') - .where('post.uri', 'in', postUris) - .leftJoin('post_agg', 'post_agg.uri', 'post.uri') - .innerJoin('ipld_block', (join) => - join - .onRef('ipld_block.cid', '=', 'post.cid') - .onRef('ipld_block.creator', '=', 'post.creator'), - ) - .innerJoin('repo_root', 'repo_root.did', 'post.creator') - .innerJoin('record', 'record.uri', 'post.uri') - - if (!options?.includeSoftDeleted) { - postsQb = postsQb - .where(notSoftDeletedClause(ref('repo_root'))) // Ensures post reply parent/roots get omitted from views when taken down - .where(notSoftDeletedClause(ref('record'))) - } - - const posts = await postsQb - .select([ - 'post.uri as uri', - 'post.cid as cid', - 'post.creator as creator', - 'post.indexedAt as indexedAt', - 'ipld_block.content as recordBytes', - 'post_agg.likeCount as likeCount', - 'post_agg.repostCount as repostCount', - 'post_agg.replyCount as replyCount', - 'record.takedownId as takedownId', - db - .selectFrom('repost') - .where('creator', '=', requester ?? '') - .whereRef('subject', '=', ref('post.uri')) - .select('uri') - .as('requesterRepost'), - db - .selectFrom('like') - .where('creator', '=', requester ?? '') - .whereRef('subject', '=', ref('post.uri')) - .select('uri') - .as('requesterLike'), - ]) - .execute() - return posts.reduce((acc, cur) => { - const { recordBytes, ...post } = cur - return Object.assign(acc, { - [post.uri]: { - ...post, - record: cborToLexRecord(recordBytes), - }, - }) - }, {} as PostInfoMap) - } - - async getFeedGeneratorInfos( - generatorUris: string[], - requester: string | null, - ) { - if (generatorUris.length < 1) return {} - const feedGens = await this.selectFeedGeneratorQb(requester) - .where('feed_generator.uri', 'in', generatorUris) - .execute() - return feedGens.reduce( - (acc, cur) => ({ - ...acc, - [cur.uri]: cur, - }), - {} as FeedGenInfoMap, - ) - } - - async getPostViews( - postUris: string[], - requester: string, - precomputed?: { - actors?: ActorInfoMap - posts?: PostInfoMap - embeds?: PostEmbedViews - blocks?: PostBlocksMap - labels?: Labels - }, - ): Promise { - const uris = dedupeStrs(postUris) - const dids = dedupeStrs(postUris.map((uri) => new AtUri(uri).hostname)) - - const [actors, posts, labels] = await Promise.all([ - precomputed?.actors ?? - this.getActorInfos(dids, requester, { skipLabels: true }), - precomputed?.posts ?? this.getPostInfos(uris, requester), - precomputed?.labels ?? - this.services.label.getLabelsForSubjects([...uris, ...dids]), - ]) - const blocks = precomputed?.blocks ?? (await this.blocksForPosts(posts)) - const embeds = - precomputed?.embeds ?? - (await this.embedsForPosts(posts, blocks, requester)) - - return uris.reduce((acc, cur) => { - const view = this.views.formatPostView(cur, actors, posts, embeds, labels) - if (view) { - acc[cur] = view - } - return acc - }, {} as PostViews) - } - - async hydrateFeed( - items: FeedRow[], - requester: string | null, - options?: FeedHydrationOptions, - ): Promise { - const actorDids = new Set() - const postUris = new Set() - for (const item of items) { - actorDids.add(item.postAuthorDid) - postUris.add(item.postUri) - if (item.postAuthorDid !== item.originatorDid) { - actorDids.add(item.originatorDid) - } - if (item.replyParent) { - postUris.add(item.replyParent) - actorDids.add(new AtUri(item.replyParent).hostname) - } - if (item.replyRoot) { - postUris.add(item.replyRoot) - actorDids.add(new AtUri(item.replyRoot).hostname) - } - } - - const [actors, posts, labels] = await Promise.all([ - this.getActorInfos(Array.from(actorDids), requester, { - skipLabels: true, - includeSoftDeleted: options?.includeSoftDeleted, - }), - this.getPostInfos(Array.from(postUris), requester, options), - this.services.label.getLabelsForSubjects([...postUris, ...actorDids]), - ]) - const blocks = await this.blocksForPosts(posts) - const embeds = await this.embedsForPosts(posts, blocks, requester) - - return this.views.formatFeed( - items, - actors, - posts, - embeds, - labels, - blocks, - options, - ) - } - - // applies blocks for visibility to third-parties (i.e. based on post content) - async blocksForPosts(posts: PostInfoMap): Promise { - const relationships: RelationshipPair[] = [] - const byPost: Record = {} - const didFromUri = (uri) => new AtUri(uri).host - for (const post of Object.values(posts)) { - // skip posts that we can't process or appear to already have been processed - if (!isPostRecord(post.record)) continue - if (byPost[post.uri]) continue - byPost[post.uri] = {} - // 3p block for replies - const parentUri = post.record.reply?.parent.uri - const parentDid = parentUri ? didFromUri(parentUri) : null - // 3p block for record embeds - const embedUris = nestedRecordUris([post.record]) - // gather actor relationships among posts - if (parentDid) { - const pair: RelationshipPair = [post.creator, parentDid] - relationships.push(pair) - byPost[post.uri].reply = pair - } - for (const embedUri of embedUris) { - const pair: RelationshipPair = [post.creator, didFromUri(embedUri)] - relationships.push(pair) - byPost[post.uri].embed = pair - } - } - // compute block state from all actor relationships among posts - const blockSet = await this.getBlockSet(relationships) - if (blockSet.empty()) return {} - const result: PostBlocksMap = {} - Object.entries(byPost).forEach(([uri, block]) => { - if (block.embed && blockSet.has(block.embed)) { - result[uri] ??= {} - result[uri].embed = true - } - if (block.reply && blockSet.has(block.reply)) { - result[uri] ??= {} - result[uri].reply = true - } - }) - return result - } - - private async getBlockSet(relationships: RelationshipPair[]) { - const { ref } = this.db.db.dynamic - const blockSet = new RelationshipSet() - if (!relationships.length) return blockSet - const relationshipSet = new RelationshipSet() - relationships.forEach((pair) => relationshipSet.add(pair)) - // compute actual block set from all actor relationships - const blockRows = await this.db.db - .selectFrom('actor_block') - .select(['creator', 'subjectDid']) // index-only columns - .where( - sql`(${ref('creator')}, ${ref('subjectDid')})`, - 'in', - valuesList( - relationshipSet.listAllPairs().map(([a, b]) => sql`${a}, ${b}`), - ), - ) - .execute() - blockRows.forEach((r) => blockSet.add([r.creator, r.subjectDid])) - return blockSet - } - - async embedsForPosts( - postInfos: PostInfoMap, - blocks: PostBlocksMap, - requester: string | null, - depth = 0, - ) { - const postMap = postRecordsFromInfos(postInfos) - const posts = Object.values(postMap) - if (posts.length < 1) { - return {} - } - const recordEmbedViews = - depth > 1 ? {} : await this.nestedRecordViews(posts, requester, depth) - - const postEmbedViews: PostEmbedViews = {} - for (const [uri, post] of Object.entries(postMap)) { - if (!post.embed) continue - if (isEmbedImages(post.embed)) { - postEmbedViews[uri] = this.views.imagesEmbedView(post.embed) - } else if (isEmbedExternal(post.embed)) { - postEmbedViews[uri] = this.views.externalEmbedView(post.embed) - } else if (isEmbedRecord(post.embed)) { - if (!recordEmbedViews[post.embed.record.uri]) continue - postEmbedViews[uri] = { - $type: 'app.bsky.embed.record#view', - record: applyEmbedBlock( - uri, - blocks, - recordEmbedViews[post.embed.record.uri], - ), - } - } else if (isEmbedRecordWithMedia(post.embed)) { - const embedRecordView = recordEmbedViews[post.embed.record.record.uri] - if (!embedRecordView) continue - const formatted = this.views.getRecordWithMediaEmbedView( - post.embed, - applyEmbedBlock(uri, blocks, embedRecordView), - ) - if (formatted) { - postEmbedViews[uri] = formatted - } - } - } - return postEmbedViews - } - - async nestedRecordViews( - posts: PostRecord[], - requester: string | null, - depth: number, - ): Promise { - const nestedUris = nestedRecordUris(posts) - if (nestedUris.length < 1) return {} - const nestedPostUris: string[] = [] - const nestedFeedGenUris: string[] = [] - const nestedListUris: string[] = [] - const nestedDidsSet = new Set() - for (const uri of nestedUris) { - const parsed = new AtUri(uri) - nestedDidsSet.add(parsed.hostname) - if (parsed.collection === ids.AppBskyFeedPost) { - nestedPostUris.push(uri) - } else if (parsed.collection === ids.AppBskyFeedGenerator) { - nestedFeedGenUris.push(uri) - } else if (parsed.collection === ids.AppBskyGraphList) { - nestedListUris.push(uri) - } - } - const nestedDids = [...nestedDidsSet] - const [postInfos, actorInfos, labelViews, feedGenInfos, listViews] = - await Promise.all([ - this.getPostInfos(nestedPostUris, requester), - this.getActorInfos(nestedDids, requester, { skipLabels: true }), - this.services.label.getLabelsForSubjects([ - ...nestedPostUris, - ...nestedDids, - ]), - this.getFeedGeneratorInfos(nestedFeedGenUris, requester), - this.services.graph.getListViews(nestedListUris, requester), - ]) - const deepBlocks = await this.blocksForPosts(postInfos) - const deepEmbedViews = await this.embedsForPosts( - postInfos, - deepBlocks, - requester, - depth + 1, - ) - const recordEmbedViews: RecordEmbedViewRecordMap = {} - for (const uri of nestedUris) { - const collection = new AtUri(uri).collection - if (collection === ids.AppBskyFeedGenerator && feedGenInfos[uri]) { - recordEmbedViews[uri] = { - $type: 'app.bsky.feed.defs#generatorView', - ...this.views.formatFeedGeneratorView( - feedGenInfos[uri], - actorInfos, - labelViews, - ), - } - } else if (collection === ids.AppBskyGraphList && listViews[uri]) { - recordEmbedViews[uri] = { - $type: 'app.bsky.graph.defs#listView', - ...this.services.graph.formatListView(listViews[uri], actorInfos), - } - } else if (collection === ids.AppBskyFeedPost && postInfos[uri]) { - const formatted = this.views.formatPostView( - uri, - actorInfos, - postInfos, - deepEmbedViews, - labelViews, - ) - recordEmbedViews[uri] = this.views.getRecordEmbedView( - uri, - formatted, - depth > 0, - ) - } else { - recordEmbedViews[uri] = { - $type: 'app.bsky.embed.record#viewNotFound', - uri, - notFound: true, - } - } - } - return recordEmbedViews - } -} - -function truncateUtf8(str: string | null | undefined, length: number) { - if (!str) return str - const encoder = new TextEncoder() - const utf8 = encoder.encode(str) - if (utf8.length > length) { - const decoder = new TextDecoder('utf-8', { fatal: false }) - const truncated = utf8.slice(0, length) - return decoder.decode(truncated).replace(/\uFFFD$/, '') - } - return str -} - -const postRecordsFromInfos = ( - infos: PostInfoMap, -): { [uri: string]: PostRecord } => { - const records: { [uri: string]: PostRecord } = {} - for (const [uri, info] of Object.entries(infos)) { - if (isPostRecord(info.record)) { - records[uri] = info.record - } - } - return records -} - -const nestedRecordUris = (posts: PostRecord[]): string[] => { - const uris: string[] = [] - for (const post of posts) { - if (!post.embed) continue - if (isEmbedRecord(post.embed)) { - uris.push(post.embed.record.uri) - } else if (isEmbedRecordWithMedia(post.embed)) { - uris.push(post.embed.record.record.uri) - } else { - continue - } - } - return uris -} - -type PostRelationships = { reply?: RelationshipPair; embed?: RelationshipPair } - -type RelationshipPair = [didA: string, didB: string] - -class RelationshipSet { - index = new Map>() - add([didA, didB]: RelationshipPair) { - const didAIdx = this.index.get(didA) ?? new Set() - const didBIdx = this.index.get(didB) ?? new Set() - if (!this.index.has(didA)) this.index.set(didA, didAIdx) - if (!this.index.has(didB)) this.index.set(didB, didBIdx) - didAIdx.add(didB) - didBIdx.add(didA) - } - has([didA, didB]: RelationshipPair) { - return !!this.index.get(didA)?.has(didB) - } - listAllPairs() { - const pairs: RelationshipPair[] = [] - for (const [didA, didBIdx] of this.index.entries()) { - for (const didB of didBIdx) { - pairs.push([didA, didB]) - } - } - return pairs - } - empty() { - return this.index.size === 0 - } -} - -function applyEmbedBlock( - uri: string, - blocks: PostBlocksMap, - view: RecordEmbedViewRecord, -): RecordEmbedViewRecord { - if (isViewRecord(view) && blocks[uri]?.embed) { - return { - $type: 'app.bsky.embed.record#viewBlocked', - uri: view.uri, - blocked: true, - author: { - did: view.author.did, - viewer: view.author.viewer - ? { - blockedBy: view.author.viewer?.blockedBy, - blocking: view.author.viewer?.blocking, - } - : undefined, - }, - } - } - return view -} diff --git a/packages/pds/src/app-view/services/feed/types.ts b/packages/pds/src/app-view/services/feed/types.ts deleted file mode 100644 index 998caa6e32c..00000000000 --- a/packages/pds/src/app-view/services/feed/types.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { RepoRecord } from '@atproto/lexicon' -import { View as ImagesEmbedView } from '../../../lexicon/types/app/bsky/embed/images' -import { View as ExternalEmbedView } from '../../../lexicon/types/app/bsky/embed/external' -import { - ViewBlocked, - ViewNotFound, - ViewRecord, - View as RecordEmbedView, -} from '../../../lexicon/types/app/bsky/embed/record' -import { View as RecordWithMediaEmbedView } from '../../../lexicon/types/app/bsky/embed/recordWithMedia' -import { - BlockedPost, - GeneratorView, - NotFoundPost, - PostView, -} from '../../../lexicon/types/app/bsky/feed/defs' -import { Label } from '../../../lexicon/types/com/atproto/label/defs' -import { FeedGenerator } from '../../db/tables/feed-generator' -import { ListView } from '../../../lexicon/types/app/bsky/graph/defs' - -export type PostEmbedViews = { - [uri: string]: PostEmbedView -} - -export type PostEmbedView = - | ImagesEmbedView - | ExternalEmbedView - | RecordEmbedView - | RecordWithMediaEmbedView - -export type PostViews = { [uri: string]: PostView } - -export type PostInfo = { - uri: string - cid: string - creator: string - record: RepoRecord - indexedAt: string - likeCount: number | null - repostCount: number | null - replyCount: number | null - requesterRepost: string | null - requesterLike: string | null - takedownId: number | null -} - -export type PostInfoMap = { [uri: string]: PostInfo } - -export type PostBlocksMap = { - [uri: string]: { reply?: boolean; embed?: boolean } -} - -export const kSelfLabels = Symbol('selfLabels') - -export type ActorInfo = { - did: string - handle: string - displayName?: string - avatar?: string - viewer?: { - muted?: boolean - blockedBy?: boolean - blocking?: string - following?: string - followedBy?: string - } - labels?: Label[] - // allows threading self-labels through if they are going to be applied later, i.e. when using skipLabels option. - [kSelfLabels]?: Label[] -} -export type ActorInfoMap = { [did: string]: ActorInfo } - -export type FeedGenInfo = FeedGenerator & { - likeCount: number - viewerLike: string | null -} - -export type FeedGenInfoMap = { [uri: string]: FeedGenInfo } - -export type FeedItemType = 'post' | 'repost' - -export type FeedRow = { - type: FeedItemType - uri: string - cid: string - postUri: string - postAuthorDid: string - originatorDid: string - replyParent: string | null - replyRoot: string | null - sortAt: string -} -export type FeedHydrationOptions = { - includeSoftDeleted?: boolean - usePostViewUnion?: boolean -} - -export type MaybePostView = PostView | NotFoundPost | BlockedPost - -export type RecordEmbedViewRecord = - | ViewRecord - | ViewNotFound - | ViewBlocked - | GeneratorView - | ListView - -export type RecordEmbedViewRecordMap = { [uri: string]: RecordEmbedViewRecord } diff --git a/packages/pds/src/app-view/services/feed/util.ts b/packages/pds/src/app-view/services/feed/util.ts deleted file mode 100644 index cedc82df0e9..00000000000 --- a/packages/pds/src/app-view/services/feed/util.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { sql } from 'kysely' -import DatabaseSchema from '../../../db/database-schema' - -export const getDescendentsQb = ( - db: DatabaseSchema, - opts: { - uri: string - depth: number // required, protects against cycles - }, -) => { - const { uri, depth } = opts - const query = db.withRecursive('descendent(uri, depth)', (cte) => { - return cte - .selectFrom('post') - .select(['post.uri as uri', sql`1`.as('depth')]) - .where(sql`1`, '<=', depth) - .where('replyParent', '=', uri) - .unionAll( - cte - .selectFrom('post') - .innerJoin('descendent', 'descendent.uri', 'post.replyParent') - .where('descendent.depth', '<', depth) - .select([ - 'post.uri as uri', - sql`descendent.depth + 1`.as('depth'), - ]), - ) - }) - return query -} - -export const getAncestorsAndSelfQb = ( - db: DatabaseSchema, - opts: { - uri: string - parentHeight: number // required, protects against cycles - }, -) => { - const { uri, parentHeight } = opts - const query = db.withRecursive( - 'ancestor(uri, ancestorUri, height)', - (cte) => { - return cte - .selectFrom('post') - .select([ - 'post.uri as uri', - 'post.replyParent as ancestorUri', - sql`0`.as('height'), - ]) - .where('uri', '=', uri) - .unionAll( - cte - .selectFrom('post') - .innerJoin('ancestor', 'ancestor.ancestorUri', 'post.uri') - .where('ancestor.height', '<', parentHeight) - .select([ - 'post.uri as uri', - 'post.replyParent as ancestorUri', - sql`ancestor.height + 1`.as('height'), - ]), - ) - }, - ) - return query -} diff --git a/packages/pds/src/app-view/services/feed/views.ts b/packages/pds/src/app-view/services/feed/views.ts deleted file mode 100644 index cfb4d158e2b..00000000000 --- a/packages/pds/src/app-view/services/feed/views.ts +++ /dev/null @@ -1,344 +0,0 @@ -import Database from '../../../db' -import { - FeedViewPost, - GeneratorView, - PostView, -} from '../../../lexicon/types/app/bsky/feed/defs' -import { - Main as EmbedImages, - isMain as isEmbedImages, - View as EmbedImagesView, -} from '../../../lexicon/types/app/bsky/embed/images' -import { - Main as EmbedExternal, - isMain as isEmbedExternal, - View as EmbedExternalView, -} from '../../../lexicon/types/app/bsky/embed/external' -import { Main as EmbedRecordWithMedia } from '../../../lexicon/types/app/bsky/embed/recordWithMedia' -import { - ViewBlocked, - ViewNotFound, - ViewRecord, -} from '../../../lexicon/types/app/bsky/embed/record' -import { - ActorInfoMap, - PostEmbedViews, - FeedGenInfo, - FeedRow, - MaybePostView, - PostInfoMap, - RecordEmbedViewRecord, - PostBlocksMap, - FeedHydrationOptions, - kSelfLabels, -} from './types' -import { Labels, getSelfLabels } from '../label' -import { ImageUriBuilder } from '../../../image/uri' - -export * from './types' - -export class FeedViews { - constructor(public db: Database, public imgUriBuilder: ImageUriBuilder) {} - - static creator(imgUriBuilder: ImageUriBuilder) { - return (db: Database) => new FeedViews(db, imgUriBuilder) - } - - formatFeedGeneratorView( - info: FeedGenInfo, - profiles: ActorInfoMap, - labels?: Labels, - ): GeneratorView { - const profile = profiles[info.creator] - if (profile && !profile.labels) { - // If the creator labels are not hydrated yet, attempt to pull them - // from labels: e.g. compatible with embedsForPosts() batching label hydration. - const profileLabels = labels?.[info.creator] ?? [] - const profileSelfLabels = profile[kSelfLabels] ?? [] - profile.labels = [...profileLabels, ...profileSelfLabels] - } - return { - uri: info.uri, - cid: info.cid, - did: info.feedDid, - creator: profile, - displayName: info.displayName ?? undefined, - description: info.description ?? undefined, - descriptionFacets: info.descriptionFacets - ? JSON.parse(info.descriptionFacets) - : undefined, - avatar: info.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', info.avatarCid) - : undefined, - likeCount: info.likeCount, - viewer: { - like: info.viewerLike ?? undefined, - }, - indexedAt: info.indexedAt, - } - } - - formatFeed( - items: FeedRow[], - actors: ActorInfoMap, - posts: PostInfoMap, - embeds: PostEmbedViews, - labels: Labels, - blocks: PostBlocksMap, - opts?: FeedHydrationOptions, - ): FeedViewPost[] { - const feed: FeedViewPost[] = [] - for (const item of items) { - const post = this.formatPostView( - item.postUri, - actors, - posts, - embeds, - labels, - opts, - ) - // skip over not found & blocked posts - if (!post || blocks[post.uri]?.reply) { - continue - } - const feedPost = { post } - if (item.type === 'repost') { - const originator = actors[item.originatorDid] - // skip over reposts where we don't have reposter profile - if (!originator) { - continue - } else { - const originatorLabels = labels[item.originatorDid] ?? [] - const originatorSelfLabels = originator[kSelfLabels] ?? [] - feedPost['reason'] = { - $type: 'app.bsky.feed.defs#reasonRepost', - by: { - ...originator, - labels: [...originatorLabels, ...originatorSelfLabels], - }, - indexedAt: item.sortAt, - } - } - } - if (item.replyParent && item.replyRoot) { - const replyParent = this.formatMaybePostView( - item.replyParent, - actors, - posts, - embeds, - labels, - blocks, - opts, - ) - const replyRoot = this.formatMaybePostView( - item.replyRoot, - actors, - posts, - embeds, - labels, - blocks, - opts, - ) - if (replyRoot && replyParent) { - feedPost['reply'] = { - root: replyRoot, - parent: replyParent, - } - } - } - feed.push(feedPost) - } - return feed - } - - formatPostView( - uri: string, - actors: ActorInfoMap, - posts: PostInfoMap, - embeds: PostEmbedViews, - labels: Labels, - opts?: Pick, - ): PostView | undefined { - const post = posts[uri] - const author = actors[post?.creator] - if (!post || !author) return undefined - // If the author labels are not hydrated yet, attempt to pull them - // from labels: e.g. compatible with hydrateFeed() batching label hydration. - const authorLabels = labels[author.did] ?? [] - const authorSelfLabels = author[kSelfLabels] ?? [] - author.labels ??= [...authorLabels, ...authorSelfLabels] - const postLabels = labels[uri] ?? [] - const postSelfLabels = getSelfLabels({ - uri: post.uri, - cid: post.cid, - record: post.record, - }) - return { - uri: post.uri, - cid: post.cid, - author: author, - takedownId: opts?.includeSoftDeleted - ? post.takedownId ?? null - : undefined, - record: post.record, - embed: embeds[uri], - replyCount: post.replyCount ?? 0, - repostCount: post.repostCount ?? 0, - likeCount: post.likeCount ?? 0, - indexedAt: post.indexedAt, - viewer: { - repost: post.requesterRepost ?? undefined, - like: post.requesterLike ?? undefined, - }, - labels: [...postLabels, ...postSelfLabels], - } - } - - formatMaybePostView( - uri: string, - actors: ActorInfoMap, - posts: PostInfoMap, - embeds: PostEmbedViews, - labels: Labels, - blocks: PostBlocksMap, - opts?: FeedHydrationOptions, - ): MaybePostView | undefined { - const post = this.formatPostView(uri, actors, posts, embeds, labels, opts) - if (!post) { - if (!opts?.usePostViewUnion) return - return this.notFoundPost(uri) - } - if ( - post.author.viewer?.blockedBy || - post.author.viewer?.blocking || - blocks[uri]?.reply - ) { - if (!opts?.usePostViewUnion) return - return this.blockedPost(post) - } - return { - $type: 'app.bsky.feed.defs#postView', - ...post, - } - } - - blockedPost(post: PostView) { - return { - $type: 'app.bsky.feed.defs#blockedPost', - uri: post.uri, - blocked: true as const, - author: { - did: post.author.did, - viewer: post.author.viewer - ? { - blockedBy: post.author.viewer?.blockedBy, - blocking: post.author.viewer?.blocking, - } - : undefined, - }, - } - } - - notFoundPost(uri: string) { - return { - $type: 'app.bsky.feed.defs#notFoundPost', - uri: uri, - notFound: true as const, - } - } - - imagesEmbedView(embed: EmbedImages) { - const imgViews = embed.images.map((img) => ({ - thumb: this.imgUriBuilder.getCommonSignedUri( - 'feed_thumbnail', - img.image.ref, - ), - fullsize: this.imgUriBuilder.getCommonSignedUri( - 'feed_fullsize', - img.image.ref, - ), - alt: img.alt, - aspectRatio: img.aspectRatio, - })) - return { - $type: 'app.bsky.embed.images#view', - images: imgViews, - } - } - - externalEmbedView(embed: EmbedExternal) { - const { uri, title, description, thumb } = embed.external - return { - $type: 'app.bsky.embed.external#view', - external: { - uri, - title, - description, - thumb: thumb - ? this.imgUriBuilder.getCommonSignedUri('feed_thumbnail', thumb.ref) - : undefined, - }, - } - } - - getRecordEmbedView( - uri: string, - post?: PostView, - omitEmbeds = false, - ): (ViewRecord | ViewNotFound | ViewBlocked) & { $type: string } { - if (!post) { - return { - $type: 'app.bsky.embed.record#viewNotFound', - uri, - notFound: true, - } - } - if (post.author.viewer?.blocking || post.author.viewer?.blockedBy) { - return { - $type: 'app.bsky.embed.record#viewBlocked', - uri, - blocked: true, - author: { - did: post.author.did, - viewer: post.author.viewer - ? { - blockedBy: post.author.viewer?.blockedBy, - blocking: post.author.viewer?.blocking, - } - : undefined, - }, - } - } - return { - $type: 'app.bsky.embed.record#viewRecord', - uri: post.uri, - cid: post.cid, - author: post.author, - value: post.record, - labels: post.labels, - indexedAt: post.indexedAt, - embeds: omitEmbeds ? undefined : post.embed ? [post.embed] : [], - } - } - - getRecordWithMediaEmbedView( - embed: EmbedRecordWithMedia, - embedRecordView: RecordEmbedViewRecord, - ) { - let mediaEmbed: EmbedImagesView | EmbedExternalView - if (isEmbedImages(embed.media)) { - mediaEmbed = this.imagesEmbedView(embed.media) - } else if (isEmbedExternal(embed.media)) { - mediaEmbed = this.externalEmbedView(embed.media) - } else { - return - } - return { - $type: 'app.bsky.embed.recordWithMedia#view', - record: { - record: embedRecordView, - }, - media: mediaEmbed, - } - } -} diff --git a/packages/pds/src/app-view/services/graph/index.ts b/packages/pds/src/app-view/services/graph/index.ts deleted file mode 100644 index 6df2d0f10d4..00000000000 --- a/packages/pds/src/app-view/services/graph/index.ts +++ /dev/null @@ -1,174 +0,0 @@ -import Database from '../../../db' -import { DbRef } from '../../../db/util' -import { NotEmptyArray } from '@atproto/common' -import { sql } from 'kysely' -import { ImageUriBuilder } from '../../../image/uri' -import { ProfileView } from '../../../lexicon/types/app/bsky/actor/defs' -import { List } from '../../db/tables/list' - -export class GraphService { - constructor(public db: Database, public imgUriBuilder: ImageUriBuilder) {} - - static creator(imgUriBuilder: ImageUriBuilder) { - return (db: Database) => new GraphService(db, imgUriBuilder) - } - - getListsQb(requester: string | null) { - const { ref } = this.db.db.dynamic - return this.db.db - .selectFrom('list') - .innerJoin('did_handle', 'did_handle.did', 'list.creator') - .selectAll('list') - .selectAll('did_handle') - .select( - this.db.db - .selectFrom('list_mute') - .where('list_mute.mutedByDid', '=', requester ?? '') - .whereRef('list_mute.listUri', '=', ref('list.uri')) - .select('list_mute.listUri') - .as('viewerMuted'), - ) - } - - getListItemsQb() { - return this.db.db - .selectFrom('list_item') - .innerJoin('did_handle as subject', 'subject.did', 'list_item.subjectDid') - .selectAll('subject') - .select(['list_item.cid as cid', 'list_item.createdAt as createdAt']) - } - - blockQb(requester: string | null, refs: NotEmptyArray) { - const subjectRefs = sql.join(refs) - return this.db.db - .selectFrom('actor_block') - .where((outer) => - outer - .where((qb) => - qb - .where('actor_block.creator', '=', requester ?? '') - .whereRef('actor_block.subjectDid', 'in', sql`(${subjectRefs})`), - ) - .orWhere((qb) => - qb - .where('actor_block.subjectDid', '=', requester ?? '') - .whereRef('actor_block.creator', 'in', sql`(${subjectRefs})`), - ), - ) - .select(['creator', 'subjectDid']) - } - - blockRefQb(first: DbRef, second: DbRef) { - return this.db.db - .selectFrom('actor_block') - .where((outer) => - outer - .where((qb) => - qb - .whereRef('actor_block.creator', '=', first) - .whereRef('actor_block.subjectDid', '=', second), - ) - .orWhere((qb) => - qb - .whereRef('actor_block.subjectDid', '=', first) - .whereRef('actor_block.creator', '=', second), - ), - ) - .select(['creator', 'subjectDid']) - } - - async getBlocks( - requester: string, - subjectHandleOrDid: string, - ): Promise<{ blocking: boolean; blockedBy: boolean }> { - let subjectDid - if (subjectHandleOrDid.startsWith('did:')) { - subjectDid = subjectHandleOrDid - } else { - const res = await this.db.db - .selectFrom('did_handle') - .where('handle', '=', subjectHandleOrDid) - .select('did') - .executeTakeFirst() - if (!res) { - return { blocking: false, blockedBy: false } - } - subjectDid = res.did - } - - const accnts = [requester, subjectDid] - const blockRes = await this.db.db - .selectFrom('actor_block') - .where('creator', 'in', accnts) - .where('subjectDid', 'in', accnts) - .selectAll() - .execute() - - const blocking = blockRes.some( - (row) => row.creator === requester && row.subjectDid === subjectDid, - ) - const blockedBy = blockRes.some( - (row) => row.creator === subjectDid && row.subjectDid === requester, - ) - - return { - blocking, - blockedBy, - } - } - - async getListViews(listUris: string[], requester: string | null) { - if (listUris.length < 1) return {} - const lists = await this.getListsQb(requester) - .where('list.uri', 'in', listUris) - .execute() - return lists.reduce( - (acc, cur) => ({ - ...acc, - [cur.uri]: cur, - }), - {}, - ) - } - - formatListView(list: ListInfo, profiles: Record) { - return { - uri: list.uri, - cid: list.cid, - creator: profiles[list.creator], - name: list.name, - purpose: list.purpose, - description: list.description ?? undefined, - descriptionFacets: list.descriptionFacets - ? JSON.parse(list.descriptionFacets) - : undefined, - avatar: list.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', list.avatarCid) - : undefined, - indexedAt: list.indexedAt, - viewer: { - muted: !!list.viewerMuted, - }, - } - } - - formatListViewBasic(list: ListInfo) { - return { - uri: list.uri, - cid: list.cid, - name: list.name, - purpose: list.purpose, - avatar: list.avatarCid - ? this.imgUriBuilder.getCommonSignedUri('avatar', list.avatarCid) - : undefined, - indexedAt: list.indexedAt, - viewer: { - muted: !!list.viewerMuted, - }, - } - } -} - -type ListInfo = List & { - viewerMuted: string | null -} diff --git a/packages/pds/src/app-view/services/indexing/plugins/post.ts b/packages/pds/src/app-view/services/indexing/plugins/post.ts index 3583f087cf1..efc1f2532c7 100644 --- a/packages/pds/src/app-view/services/indexing/plugins/post.ts +++ b/packages/pds/src/app-view/services/indexing/plugins/post.ts @@ -20,7 +20,6 @@ import RecordProcessor from '../processor' import { UserNotification } from '../../../../db/tables/user-notification' import { countAll, excluded } from '../../../../db/util' import { toSimplifiedISOSafe } from '../util' -import { getAncestorsAndSelfQb } from '../../feed/util' type Post = DatabaseSchemaType['post'] type PostEmbedImage = DatabaseSchemaType['post_embed_image'] @@ -138,14 +137,7 @@ const insertFn = async ( await db.insertInto('post_embed_record').values(recordEmbed).execute() } } - const ancestors = await getAncestorsAndSelfQb(db, { - uri: post.uri, - parentHeight: REPLY_NOTIF_DEPTH, - }) - .selectFrom('ancestor') - .selectAll() - .execute() - return { post: insertedPost, facets, embeds, ancestors } + return { post: insertedPost, facets, embeds } } const findDuplicate = async (): Promise => { diff --git a/packages/pds/src/config.ts b/packages/pds/src/config.ts index acca18b580a..816aa511873 100644 --- a/packages/pds/src/config.ts +++ b/packages/pds/src/config.ts @@ -38,11 +38,6 @@ export interface ServerConfigValues { availableUserDomains: string[] handleResolveNameservers?: string[] - imgUriSalt: string - imgUriKey: string - imgUriEndpoint?: string - blobCacheLocation?: string - rateLimitsEnabled: boolean rateLimitBypassKey?: string rateLimitBypassIps?: string[] @@ -69,10 +64,9 @@ export interface ServerConfigValues { // this is really only used in test environments dbTxLockNonce?: string - bskyAppViewEndpoint?: string + bskyAppViewEndpoint: string + bskyAppViewDid: string bskyAppViewModeration?: boolean - bskyAppViewDid?: string - bskyAppViewProxy: boolean bskyAppViewCdnUrlPattern?: string crawlersToNotify?: string[] @@ -154,14 +148,6 @@ export class ServerConfig { ? process.env.HANDLE_RESOLVE_NAMESERVERS.split(',') : [] - const imgUriSalt = - process.env.IMG_URI_SALT || '9dd04221f5755bce5f55f47464c27e1e' - const imgUriKey = - process.env.IMG_URI_KEY || - 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8' - const imgUriEndpoint = process.env.IMG_URI_ENDPOINT - const blobCacheLocation = process.env.BLOB_CACHE_LOC - const rateLimitsEnabled = process.env.RATE_LIMITS_ENABLED === 'true' const rateLimitBypassKey = nonemptyString(process.env.RATE_LIMIT_BYPASS_KEY) const rateLimitBypassIpsStr = nonemptyString( @@ -228,12 +214,17 @@ export class ServerConfig { const bskyAppViewEndpoint = nonemptyString( process.env.BSKY_APP_VIEW_ENDPOINT, ) + if (typeof bskyAppViewEndpoint !== 'string') { + throw new Error( + 'No value provided for process.env.BSKY_APP_VIEW_ENDPOINT', + ) + } + const bskyAppViewDid = nonemptyString(process.env.BSKY_APP_VIEW_DID) + if (typeof bskyAppViewDid !== 'string') { + throw new Error('No value provided for process.env.BSKY_APP_VIEW_DID') + } const bskyAppViewModeration = process.env.BSKY_APP_VIEW_MODERATION === 'true' ? true : false - const bskyAppViewDid = nonemptyString(process.env.BSKY_APP_VIEW_DID) - const bskyAppViewProxy = - process.env.BSKY_APP_VIEW_PROXY === 'true' ? true : false - const bskyAppViewCdnUrlPattern = nonemptyString( process.env.BSKY_APP_VIEW_CDN_URL_PATTERN, ) @@ -270,10 +261,6 @@ export class ServerConfig { databaseLocation, availableUserDomains, handleResolveNameservers, - imgUriSalt, - imgUriKey, - imgUriEndpoint, - blobCacheLocation, rateLimitsEnabled, rateLimitBypassKey, rateLimitBypassIps, @@ -294,9 +281,8 @@ export class ServerConfig { sequencerLeaderEnabled, dbTxLockNonce, bskyAppViewEndpoint, - bskyAppViewModeration, bskyAppViewDid, - bskyAppViewProxy, + bskyAppViewModeration, bskyAppViewCdnUrlPattern, crawlersToNotify, ...overrides, @@ -441,22 +427,6 @@ export class ServerConfig { return this.cfg.handleResolveNameservers } - get imgUriSalt() { - return this.cfg.imgUriSalt - } - - get imgUriKey() { - return this.cfg.imgUriKey - } - - get imgUriEndpoint() { - return this.cfg.imgUriEndpoint - } - - get blobCacheLocation() { - return this.cfg.blobCacheLocation - } - get rateLimitsEnabled() { return this.cfg.rateLimitsEnabled } @@ -537,16 +507,12 @@ export class ServerConfig { return this.cfg.bskyAppViewEndpoint } - get bskyAppViewModeration() { - return this.cfg.bskyAppViewModeration - } - get bskyAppViewDid() { return this.cfg.bskyAppViewDid } - get bskyAppViewProxy() { - return this.cfg.bskyAppViewProxy + get bskyAppViewModeration() { + return this.cfg.bskyAppViewModeration } get bskyAppViewCdnUrlPattern() { diff --git a/packages/pds/src/context.ts b/packages/pds/src/context.ts index 1f414845ea1..ea0990955e2 100644 --- a/packages/pds/src/context.ts +++ b/packages/pds/src/context.ts @@ -1,4 +1,3 @@ -import express from 'express' import { Redis } from 'ioredis' import * as plc from '@did-plc/lib' import * as crypto from '@atproto/crypto' @@ -11,14 +10,12 @@ import * as auth from './auth' import { ServerMailer } from './mailer' import { ModerationMailer } from './mailer/moderation' import { BlobStore } from '@atproto/repo' -import { ImageUriBuilder } from './image/uri' import { Services } from './services' import { MessageDispatcher } from './event-stream/message-queue' import { Sequencer, SequencerLeader } from './sequencer' import { Labeler } from './labeler' import { BackgroundQueue } from './event-stream/background-queue' import DidSqlCache from './did-cache' -import { MountedAlgos } from './feed-gen/types' import { Crawlers } from './crawlers' import { LabelCache } from './label-cache' import { RuntimeFlags } from './runtime-flags' @@ -34,7 +31,6 @@ export class AppContext { idResolver: IdResolver didCache: DidSqlCache auth: auth.ServerAuth - imgUriBuilder: ImageUriBuilder cfg: ServerConfig mailer: ServerMailer moderationMailer: ModerationMailer @@ -46,9 +42,8 @@ export class AppContext { labelCache: LabelCache runtimeFlags: RuntimeFlags backgroundQueue: BackgroundQueue - appviewAgent?: AtpAgent + appviewAgent: AtpAgent crawlers: Crawlers - algos: MountedAlgos }, ) {} @@ -104,10 +99,6 @@ export class AppContext { return auth.optionalAccessOrRoleVerifier(this.auth) } - get imgUriBuilder(): ImageUriBuilder { - return this.opts.imgUriBuilder - } - get cfg(): ServerConfig { return this.opts.cfg } @@ -168,8 +159,8 @@ export class AppContext { return this.opts.didCache } - get algos(): MountedAlgos { - return this.opts.algos + get appviewAgent(): AtpAgent { + return this.opts.appviewAgent } async serviceAuthHeaders(did: string, audience?: string) { @@ -184,27 +175,6 @@ export class AppContext { }) } - get appviewAgent(): AtpAgent { - if (!this.opts.appviewAgent) { - throw new Error('Could not find bsky appview endpoint') - } - return this.opts.appviewAgent - } - - canProxyRead(): boolean { - if (!this.cfg.bskyAppViewProxy || !this.cfg.bskyAppViewEndpoint) { - return false - } - return true - } - - canProxyFeedConstruction(req: express.Request): boolean { - return ( - this.cfg.bskyAppViewEndpoint !== undefined && - req.get('x-appview-proxy') !== undefined - ) - } - shouldProxyModeration(): boolean { return ( this.cfg.bskyAppViewEndpoint !== undefined && diff --git a/packages/pds/src/feed-gen/best-of-follows.ts b/packages/pds/src/feed-gen/best-of-follows.ts deleted file mode 100644 index a88e24fdb8f..00000000000 --- a/packages/pds/src/feed-gen/best-of-follows.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { InvalidRequestError } from '@atproto/xrpc-server' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import { AlgoHandler, AlgoResponse } from './types' -import { GenericKeyset, paginate } from '../db/pagination' -import AppContext from '../context' - -const handler: AlgoHandler = async ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -): Promise => { - if (ctx.db.dialect === 'sqlite') { - throw new Error('best-of-follows algo not available in sqlite') - } - - const { limit, cursor } = params - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const { ref } = ctx.db.db.dynamic - - // candidates are ranked within a materialized view by like count, depreciated over time. - - let builder = feedService - .selectPostQb() - .innerJoin('algo_whats_hot_view as candidate', 'candidate.uri', 'post.uri') - .where((qb) => - qb - .where('post.creator', '=', requester) - .orWhereExists((inner) => - inner - .selectFrom('follow') - .where('follow.creator', '=', requester) - .whereRef('follow.subjectDid', '=', 'post.creator'), - ), - ) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - .select('candidate.score') - .select('candidate.cid') - - const keyset = new ScoreKeyset(ref('candidate.score'), ref('candidate.cid')) - builder = paginate(builder, { limit, cursor, keyset }) - - const feedItems = await builder.execute() - - return { - feedItems, - cursor: keyset.packFromResult(feedItems), - } -} - -export default handler - -type Result = { score: number; cid: string } -type LabeledResult = { primary: number; secondary: string } -export class ScoreKeyset extends GenericKeyset { - labelResult(result: Result) { - return { - primary: result.score, - secondary: result.cid, - } - } - labeledResultToCursor(labeled: LabeledResult) { - return { - primary: Math.round(labeled.primary).toString(), - secondary: labeled.secondary, - } - } - cursorToLabeledResult(cursor: { primary: string; secondary: string }) { - const score = parseInt(cursor.primary, 10) - if (isNaN(score)) { - throw new InvalidRequestError('Malformed cursor') - } - return { - primary: score, - secondary: cursor.secondary, - } - } -} diff --git a/packages/pds/src/feed-gen/bsky-team.ts b/packages/pds/src/feed-gen/bsky-team.ts deleted file mode 100644 index ba4196e79d9..00000000000 --- a/packages/pds/src/feed-gen/bsky-team.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NotEmptyArray } from '@atproto/common' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import AppContext from '../context' -import { paginate } from '../db/pagination' -import { AlgoHandler, AlgoResponse } from './types' -import { FeedKeyset } from '../app-view/api/app/bsky/util/feed' - -const BSKY_TEAM: NotEmptyArray = [ - 'did:plc:z72i7hdynmk6r22z27h6tvur', // @bsky.app - 'did:plc:ewvi7nxzyoun6zhxrhs64oiz', // @atproto.com - 'did:plc:eon2iu7v3x2ukgxkqaf7e5np', // @safety.bsky.app -] - -const handler: AlgoHandler = async ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -): Promise => { - const { limit = 50, cursor } = params - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const { ref } = ctx.db.db.dynamic - - const postsQb = feedService - .selectPostQb() - .where('post.creator', 'in', BSKY_TEAM) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - - const keyset = new FeedKeyset(ref('sortAt'), ref('cid')) - - let feedQb = ctx.db.db.selectFrom(postsQb.as('feed_items')).selectAll() - feedQb = paginate(feedQb, { limit, cursor, keyset }) - - const feedItems = await feedQb.execute() - return { - feedItems, - cursor: keyset.packFromResult(feedItems), - } -} - -export default handler diff --git a/packages/pds/src/feed-gen/hot-classic.ts b/packages/pds/src/feed-gen/hot-classic.ts deleted file mode 100644 index 5284632a7e9..00000000000 --- a/packages/pds/src/feed-gen/hot-classic.ts +++ /dev/null @@ -1,59 +0,0 @@ -import AppContext from '../context' -import { NotEmptyArray } from '@atproto/common' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import { paginate } from '../db/pagination' -import { AlgoHandler, AlgoResponse } from './types' -import { FeedKeyset } from '../app-view/api/app/bsky/util/feed' -import { valuesList } from '../db/util' - -const NO_WHATS_HOT_LABELS: NotEmptyArray = ['!no-promote'] - -const handler: AlgoHandler = async ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -): Promise => { - const { limit = 50, cursor } = params - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const { ref } = ctx.db.db.dynamic - - const postsQb = feedService - .selectPostQb() - .leftJoin('post_agg', 'post_agg.uri', 'post.uri') - .leftJoin('post_embed_record', 'post_embed_record.postUri', 'post.uri') - .where('post_agg.likeCount', '>=', 12) - .where('post.replyParent', 'is', null) - .whereNotExists((qb) => - qb - .selectFrom('label') - .selectAll() - .whereRef('val', 'in', valuesList(NO_WHATS_HOT_LABELS)) - .where('neg', '=', 0) - .where((clause) => - clause - .whereRef('label.uri', '=', ref('post.creator')) - .orWhereRef('label.uri', '=', ref('post.uri')) - .orWhereRef('label.uri', '=', ref('post_embed_record.embedUri')), - ), - ) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - - const keyset = new FeedKeyset(ref('sortAt'), ref('cid')) - - let feedQb = ctx.db.db.selectFrom(postsQb.as('feed_items')).selectAll() - feedQb = paginate(feedQb, { limit, cursor, keyset }) - - const feedItems = await feedQb.execute() - return { - feedItems, - cursor: keyset.packFromResult(feedItems), - } -} - -export default handler diff --git a/packages/pds/src/feed-gen/index.ts b/packages/pds/src/feed-gen/index.ts deleted file mode 100644 index 46657e87fae..00000000000 --- a/packages/pds/src/feed-gen/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { AtUri } from '@atproto/syntax' -import withFriends from './with-friends' -import bskyTeam from './bsky-team' -import hotClassic from './hot-classic' -import bestOfFollows from './best-of-follows' -import mutuals from './mutuals' -import { ids } from '../lexicon/lexicons' -import { MountedAlgos } from './types' - -const coll = ids.AppBskyFeedGenerator - -// These are custom algorithms that will be mounted directly onto an AppView -// Feel free to remove, update to your own, or serve the following logic at a record that you control -export const makeAlgos = (did: string): MountedAlgos => ({ - [AtUri.make(did, coll, 'with-friends').toString()]: withFriends, - [AtUri.make(did, coll, 'bsky-team').toString()]: bskyTeam, - [AtUri.make(did, coll, 'hot-classic').toString()]: hotClassic, - [AtUri.make(did, coll, 'best-of-follows').toString()]: bestOfFollows, - [AtUri.make(did, coll, 'mutuals').toString()]: mutuals, -}) diff --git a/packages/pds/src/feed-gen/mutuals.ts b/packages/pds/src/feed-gen/mutuals.ts deleted file mode 100644 index 94aba5bb104..00000000000 --- a/packages/pds/src/feed-gen/mutuals.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import AppContext from '../context' -import { paginate } from '../db/pagination' -import { AlgoHandler, AlgoResponse } from './types' -import { - FeedKeyset, - getFeedDateThreshold, -} from '../app-view/api/app/bsky/util/feed' - -const handler: AlgoHandler = async ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -): Promise => { - const { limit = 50, cursor } = params - const accountService = ctx.services.account(ctx.db) - const feedService = ctx.services.appView.feed(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const { ref } = ctx.db.db.dynamic - - const mutualsSubquery = ctx.db.db - .selectFrom('follow') - .where('follow.creator', '=', requester) - .whereExists((qb) => - qb - .selectFrom('follow as follow_inner') - .whereRef('follow_inner.creator', '=', 'follow.subjectDid') - .where('follow_inner.subjectDid', '=', requester) - .selectAll(), - ) - .select('follow.subjectDid') - - const keyset = new FeedKeyset(ref('feed_item.sortAt'), ref('feed_item.cid')) - const sortFrom = keyset.unpack(cursor)?.primary - - let feedQb = feedService - .selectFeedItemQb() - .where('feed_item.type', '=', 'post') // ensures originatorDid is post.creator - .where((qb) => - qb - .where('originatorDid', '=', requester) - .orWhere('originatorDid', 'in', mutualsSubquery), - ) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('originatorDid')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('originatorDid')])) - .where('feed_item.sortAt', '>', getFeedDateThreshold(sortFrom)) - - feedQb = paginate(feedQb, { limit, cursor, keyset }) - - const feedItems = await feedQb.execute() - return { - feedItems, - cursor: keyset.packFromResult(feedItems), - } -} - -export default handler diff --git a/packages/pds/src/feed-gen/types.ts b/packages/pds/src/feed-gen/types.ts deleted file mode 100644 index 7682a0e23bc..00000000000 --- a/packages/pds/src/feed-gen/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -import AppContext from '../context' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import { FeedRow } from '../app-view/services/feed' - -export type AlgoResponse = { - feedItems: FeedRow[] - cursor?: string -} - -export type AlgoHandler = ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -) => Promise - -export type MountedAlgos = Record diff --git a/packages/pds/src/feed-gen/whats-hot.ts b/packages/pds/src/feed-gen/whats-hot.ts deleted file mode 100644 index d48c049e95c..00000000000 --- a/packages/pds/src/feed-gen/whats-hot.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { NotEmptyArray } from '@atproto/common' -import { InvalidRequestError } from '@atproto/xrpc-server' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import { AlgoHandler, AlgoResponse } from './types' -import { GenericKeyset, paginate } from '../db/pagination' -import AppContext from '../context' -import { valuesList } from '../db/util' -import { sql } from 'kysely' -import { FeedItemType } from '../app-view/services/feed' - -const NO_WHATS_HOT_LABELS: NotEmptyArray = [ - '!no-promote', - 'corpse', - 'self-harm', - 'porn', - 'sexual', - 'nudity', - 'underwear', -] - -const handler: AlgoHandler = async ( - ctx: AppContext, - params: SkeletonParams, - requester: string, -): Promise => { - if (ctx.db.dialect === 'sqlite') { - throw new Error('what-hot algo not available in sqlite') - } - - const { limit, cursor } = params - const accountService = ctx.services.account(ctx.db) - const graphService = ctx.services.appView.graph(ctx.db) - - const { ref } = ctx.db.db.dynamic - - // candidates are ranked within a materialized view by like count, depreciated over time. - - let builder = ctx.db.db - .selectFrom('algo_whats_hot_view as candidate') - .innerJoin('post', 'post.uri', 'candidate.uri') - .leftJoin('post_embed_record', 'post_embed_record.postUri', 'candidate.uri') - .whereNotExists((qb) => - qb - .selectFrom('label') - .selectAll() - .whereRef('val', 'in', valuesList(NO_WHATS_HOT_LABELS)) - .where('neg', '=', 0) - .where((clause) => - clause - .whereRef('label.uri', '=', ref('post.creator')) - .orWhereRef('label.uri', '=', ref('post.uri')) - .orWhereRef('label.uri', '=', ref('post_embed_record.embedUri')), - ), - ) - .where((qb) => - accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - ) - .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - .select([ - sql`${'post'}`.as('type'), - 'post.uri as uri', - 'post.cid as cid', - 'post.uri as postUri', - 'post.creator as originatorDid', - 'post.creator as postAuthorDid', - 'post.replyParent as replyParent', - 'post.replyRoot as replyRoot', - 'post.indexedAt as sortAt', - 'candidate.score', - 'candidate.cid', - ]) - - const keyset = new ScoreKeyset(ref('candidate.score'), ref('candidate.cid')) - builder = paginate(builder, { limit, cursor, keyset }) - - const feedItems = await builder.execute() - - return { - feedItems, - cursor: keyset.packFromResult(feedItems), - } -} - -export default handler - -type Result = { score: number; cid: string } -type LabeledResult = { primary: number; secondary: string } -export class ScoreKeyset extends GenericKeyset { - labelResult(result: Result) { - return { - primary: result.score, - secondary: result.cid, - } - } - labeledResultToCursor(labeled: LabeledResult) { - return { - primary: Math.round(labeled.primary).toString(), - secondary: labeled.secondary, - } - } - cursorToLabeledResult(cursor: { primary: string; secondary: string }) { - const score = parseInt(cursor.primary, 10) - if (isNaN(score)) { - throw new InvalidRequestError('Malformed cursor') - } - return { - primary: score, - secondary: cursor.secondary, - } - } -} diff --git a/packages/pds/src/feed-gen/with-friends.ts b/packages/pds/src/feed-gen/with-friends.ts deleted file mode 100644 index a36f435286c..00000000000 --- a/packages/pds/src/feed-gen/with-friends.ts +++ /dev/null @@ -1,62 +0,0 @@ -import AppContext from '../context' -import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' -import { AlgoHandler, AlgoResponse } from './types' - -const handler: AlgoHandler = async ( - _ctx: AppContext, - _params: SkeletonParams, - _requester: string, -): Promise => { - // Temporary change to only return a post notifying users that the feed is down - return { - feedItems: [ - { - type: 'post', - uri: 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3jzinucnmbi2c', - cid: 'bafyreifmtn55tubbv7tefrq277nzfy4zu7ioithky276aho5ehb6w3nu6q', - postUri: - 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3jzinucnmbi2c', - postAuthorDid: 'did:plc:z72i7hdynmk6r22z27h6tvur', - originatorDid: 'did:plc:z72i7hdynmk6r22z27h6tvur', - replyParent: null, - replyRoot: null, - sortAt: '2023-07-01T23:04:27.853Z', - }, - ], - } - // const { cursor, limit = 50 } = params - // const accountService = ctx.services.account(ctx.db) - // const feedService = ctx.services.appView.feed(ctx.db) - // const graphService = ctx.services.appView.graph(ctx.db) - - // const { ref } = ctx.db.db.dynamic - - // const keyset = new FeedKeyset(ref('post.indexedAt'), ref('post.cid')) - // const sortFrom = keyset.unpack(cursor)?.primary - - // let postsQb = feedService - // .selectPostQb() - // // .innerJoin('post_agg', 'post_agg.uri', 'post.uri') - // // .where('post_agg.likeCount', '>=', 6) - // .whereExists((qb) => - // qb - // .selectFrom('follow') - // .where('follow.creator', '=', requester) - // .whereRef('follow.subjectDid', '=', 'post.creator'), - // ) - // .where((qb) => - // accountService.whereNotMuted(qb, requester, [ref('post.creator')]), - // ) - // .whereNotExists(graphService.blockQb(requester, [ref('post.creator')])) - // .where('post.indexedAt', '>', getFeedDateThreshold(sortFrom)) - - // postsQb = paginate(postsQb, { limit, cursor, keyset, tryIndex: true }) - - // const feedItems = await postsQb.execute() - // return { - // feedItems, - // cursor: keyset.packFromResult(feedItems), - // } -} - -export default handler diff --git a/packages/pds/src/image/index.ts b/packages/pds/src/image/index.ts index 3197b5aeb5c..ebf47088f6b 100644 --- a/packages/pds/src/image/index.ts +++ b/packages/pds/src/image/index.ts @@ -1,2 +1,80 @@ -export * from './sharp' -export type { Options, ImageInfo } from './util' +import { Readable } from 'stream' +import { pipeline } from 'stream/promises' +import sharp from 'sharp' +import { errHasMsg } from '@atproto/common' + +export async function maybeGetInfo( + stream: Readable, +): Promise { + let metadata: sharp.Metadata + try { + const processor = sharp() + const [result] = await Promise.all([ + processor.metadata(), + pipeline(stream, processor), // Handles error propagation + ]) + metadata = result + } catch (err) { + if (errHasMsg(err, 'Input buffer contains unsupported image format')) { + return null + } + throw err + } + const { size, height, width, format } = metadata + if ( + size === undefined || + height === undefined || + width === undefined || + format === undefined + ) { + return null + } + + return { + height, + width, + size, + mime: formatsToMimes[format] ?? ('unknown' as const), + } +} + +export async function getInfo(stream: Readable): Promise { + const maybeInfo = await maybeGetInfo(stream) + if (!maybeInfo) { + throw new Error('could not obtain all image metadata') + } + return maybeInfo +} + +export type Options = Dimensions & { + format: 'jpeg' | 'png' + // When 'cover' (default), scale to fill given dimensions, cropping if necessary. + // When 'inside', scale to fit within given dimensions. + fit?: 'cover' | 'inside' + // When false (default), do not scale up. + // When true, scale up to hit dimensions given in options. + // Otherwise, scale up to hit specified min dimensions. + min?: Dimensions | boolean + // A number 1-100 + quality?: number +} + +export type ImageInfo = Dimensions & { + size: number + mime: `image/${string}` | 'unknown' +} + +export type Dimensions = { height: number; width: number } + +export const formatsToMimes: { + [s in keyof sharp.FormatEnum]?: `image/${string}` +} = { + jpg: 'image/jpeg', + jpeg: 'image/jpeg', + png: 'image/png', + gif: 'image/gif', + svg: 'image/svg+xml', + tif: 'image/tiff', + tiff: 'image/tiff', + webp: 'image/webp', +} diff --git a/packages/pds/src/image/invalidator.ts b/packages/pds/src/image/invalidator.ts deleted file mode 100644 index d1319951500..00000000000 --- a/packages/pds/src/image/invalidator.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { BlobCache } from './server' - -// Invalidation is a general interface for propagating an image blob -// takedown through any caches where a representation of it may be stored. -// @NOTE this does not remove the blob from storage: just invalidates it from caches. -// @NOTE keep in sync with same interface in aws/src/cloudfront.ts -export interface ImageInvalidator { - invalidate(subject: string, paths: string[]): Promise -} - -export class ImageProcessingServerInvalidator implements ImageInvalidator { - constructor(private cache: BlobCache) {} - async invalidate(_subject: string, paths: string[]) { - const results = await Promise.allSettled( - paths.map(async (path) => { - const [, signature] = path.split('/') - if (!signature) throw new Error('Missing signature') - await this.cache.clear(signature) - }), - ) - const rejection = results.find( - (result): result is PromiseRejectedResult => result.status === 'rejected', - ) - if (rejection) throw rejection.reason - } -} diff --git a/packages/pds/src/image/logger.ts b/packages/pds/src/image/logger.ts deleted file mode 100644 index f4bcb5c9a66..00000000000 --- a/packages/pds/src/image/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { subsystemLogger } from '@atproto/common' - -export const logger = subsystemLogger('pds:image') - -export default logger diff --git a/packages/pds/src/image/server.ts b/packages/pds/src/image/server.ts deleted file mode 100644 index 8e52d5d1fdf..00000000000 --- a/packages/pds/src/image/server.ts +++ /dev/null @@ -1,170 +0,0 @@ -import fs from 'fs/promises' -import fsSync from 'fs' -import os from 'os' -import path from 'path' -import { Readable } from 'stream' -import express, { ErrorRequestHandler, NextFunction } from 'express' -import createError, { isHttpError } from 'http-errors' -import { BlobNotFoundError, BlobStore } from '@atproto/repo' -import { - cloneStream, - forwardStreamErrors, - isErrnoException, -} from '@atproto/common' -import { BadPathError, ImageUriBuilder } from './uri' -import log from './logger' -import { resize } from './sharp' -import { formatsToMimes, Options } from './util' - -export class ImageProcessingServer { - app = express() - uriBuilder: ImageUriBuilder - - constructor( - protected salt: string | Uint8Array, - protected key: string | Uint8Array, - protected storage: BlobStore, - public cache: BlobCache, - ) { - this.uriBuilder = new ImageUriBuilder('', salt, key) - this.app.get('*', this.handler.bind(this)) - this.app.use(errorMiddleware) - } - - async handler( - req: express.Request, - res: express.Response, - next: NextFunction, - ) { - try { - const path = req.path - const options = this.uriBuilder.getVerifiedOptions(path) - - // Cached flow - - try { - const cachedImage = await this.cache.get(options.signature) - res.statusCode = 200 - res.setHeader('x-cache', 'hit') - res.setHeader('content-type', getMime(options.format)) - res.setHeader('cache-control', `public, max-age=31536000`) // 1 year - res.setHeader('content-length', cachedImage.size) - forwardStreamErrors(cachedImage, res) - return cachedImage.pipe(res) - } catch (err) { - // Ignore BlobNotFoundError and move on to non-cached flow - if (!(err instanceof BlobNotFoundError)) throw err - } - - // Non-cached flow - - const imageStream = await this.storage.getStream(options.cid) - const processedImage = await resize(imageStream, options) - - // Cache in the background - this.cache - .put(options.signature, cloneStream(processedImage)) - .catch((err) => log.error(err, 'failed to cache image')) - // Respond - res.statusCode = 200 - res.setHeader('x-cache', 'miss') - res.setHeader('content-type', getMime(options.format)) - res.setHeader('cache-control', `public, max-age=31536000`) // 1 year - forwardStreamErrors(processedImage, res) - return ( - processedImage - // @NOTE sharp does emit this in time to be set as a header - .once('info', (info) => res.setHeader('content-length', info.size)) - .pipe(res) - ) - } catch (err: unknown) { - if (err instanceof BadPathError) { - return next(createError(400, err)) - } - if (err instanceof BlobNotFoundError) { - return next(createError(404, 'Image not found')) - } - return next(err) - } - } -} - -const errorMiddleware: ErrorRequestHandler = function (err, _req, res, next) { - if (isHttpError(err)) { - log.error(err, `error: ${err.message}`) - } else { - log.error(err, 'unhandled exception') - } - if (res.headersSent) { - return next(err) - } - const httpError = createError(err) - return res.status(httpError.status).json({ - message: httpError.expose ? httpError.message : 'Internal Server Error', - }) -} - -function getMime(format: Options['format']) { - const mime = formatsToMimes[format] - if (!mime) throw new Error('Unknown format') - return mime -} - -export interface BlobCache { - get(fileId: string): Promise - put(fileId: string, stream: Readable): Promise - clear(fileId: string): Promise - clearAll(): Promise -} - -export class BlobDiskCache implements BlobCache { - tempDir: string - constructor(basePath?: string) { - this.tempDir = basePath || path.join(os.tmpdir(), 'pds--processed-images') - if (!path.isAbsolute(this.tempDir)) { - throw new Error('Must provide an absolute path') - } - try { - fsSync.mkdirSync(this.tempDir, { recursive: true }) - } catch (err) { - // All good if cache dir already exists - if (isErrnoException(err) && err.code === 'EEXIST') return - } - } - - async get(fileId: string) { - const filePath = path.join(this.tempDir, fileId) - try { - const { size } = await fs.stat(filePath) - if (size === 0) { - throw new BlobNotFoundError() - } - return Object.assign(fsSync.createReadStream(filePath), { size }) - } catch (err) { - if (isErrnoException(err) && err.code === 'ENOENT') { - throw new BlobNotFoundError() - } - throw err - } - } - - async put(fileId: string, stream: Readable) { - const filename = path.join(this.tempDir, fileId) - try { - await fs.writeFile(filename, stream, { flag: 'wx' }) - } catch (err) { - // Do not overwrite existing file, just ignore the error - if (isErrnoException(err) && err.code === 'EEXIST') return - throw err - } - } - - async clear(fileId: string) { - const filename = path.join(this.tempDir, fileId) - await fs.rm(filename, { force: true }) - } - - async clearAll() { - await fs.rm(this.tempDir, { recursive: true, force: true }) - } -} diff --git a/packages/pds/src/image/sharp.ts b/packages/pds/src/image/sharp.ts deleted file mode 100644 index 1edc7a58835..00000000000 --- a/packages/pds/src/image/sharp.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Readable } from 'stream' -import { pipeline } from 'stream/promises' -import sharp from 'sharp' -import { errHasMsg, forwardStreamErrors } from '@atproto/common' -import { formatsToMimes, ImageInfo, Options } from './util' - -export type { Options } - -export async function resize( - stream: Readable, - options: Options, -): Promise { - const { height, width, min = false, fit = 'cover', format, quality } = options - - let processor = sharp() - - // Scale up to hit any specified minimum size - if (typeof min !== 'boolean') { - const upsizeProcessor = sharp().resize({ - fit: 'outside', - width: min.width, - height: min.height, - withoutReduction: true, - withoutEnlargement: false, - }) - forwardStreamErrors(stream, upsizeProcessor) - stream = stream.pipe(upsizeProcessor) - } - - // Scale down (or possibly up if min is true) to desired size - processor = processor.resize({ - fit, - width, - height, - withoutEnlargement: min !== true, - }) - - // Output to specified format - if (format === 'jpeg') { - processor = processor.jpeg({ quality: quality ?? 100 }) - } else if (format === 'png') { - processor = processor.png({ quality: quality ?? 100 }) - } else { - const exhaustiveCheck: never = format - throw new Error(`Unhandled case: ${exhaustiveCheck}`) - } - - forwardStreamErrors(stream, processor) - return stream.pipe(processor) -} - -export async function maybeGetInfo( - stream: Readable, -): Promise { - let metadata: sharp.Metadata - try { - const processor = sharp() - const [result] = await Promise.all([ - processor.metadata(), - pipeline(stream, processor), // Handles error propagation - ]) - metadata = result - } catch (err) { - if (errHasMsg(err, 'Input buffer contains unsupported image format')) { - return null - } - throw err - } - const { size, height, width, format } = metadata - if ( - size === undefined || - height === undefined || - width === undefined || - format === undefined - ) { - return null - } - - return { - height, - width, - size, - mime: formatsToMimes[format] ?? ('unknown' as const), - } -} - -export async function getInfo(stream: Readable): Promise { - const maybeInfo = await maybeGetInfo(stream) - if (!maybeInfo) { - throw new Error('could not obtain all image metadata') - } - return maybeInfo -} diff --git a/packages/pds/src/image/uri.ts b/packages/pds/src/image/uri.ts deleted file mode 100644 index 227a4ebb94b..00000000000 --- a/packages/pds/src/image/uri.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { createHmac } from 'crypto' -import * as uint8arrays from 'uint8arrays' -import { CID } from 'multiformats/cid' -import { Options } from './util' - -// @NOTE if there are any additions here, ensure to include them on ImageUriBuilder.commonSignedUris -type CommonSignedUris = 'avatar' | 'banner' | 'feed_thumbnail' | 'feed_fullsize' - -export class ImageUriBuilder { - public endpoint: string - private salt: Uint8Array - private key: Uint8Array - - constructor( - endpoint: string, - salt: Uint8Array | string, - key: Uint8Array | string, - ) { - this.endpoint = endpoint - this.salt = - typeof salt === 'string' ? uint8arrays.fromString(salt, 'hex') : salt - this.key = - typeof key === 'string' ? uint8arrays.fromString(key, 'hex') : key - } - - getSignedPath(opts: Options & { cid: CID }): string { - const path = ImageUriBuilder.getPath(opts) - const saltedPath = uint8arrays.concat([ - this.salt, - uint8arrays.fromString(path), - ]) - const sig = hmac(this.key, saltedPath).toString('base64url') - return `/${sig}${path}` - } - - getSignedUri(opts: Options & { cid: CID }): string { - const path = this.getSignedPath(opts) - return this.endpoint + path - } - - static commonSignedUris: CommonSignedUris[] = [ - 'avatar', - 'banner', - 'feed_thumbnail', - 'feed_fullsize', - ] - - getCommonSignedUri(id: CommonSignedUris, cid: string | CID): string { - if (id === 'avatar') { - return this.getSignedUri({ - cid: typeof cid === 'string' ? CID.parse(cid) : cid, - format: 'jpeg', - fit: 'cover', - height: 1000, - width: 1000, - min: true, - }) - } else if (id === 'banner') { - return this.getSignedUri({ - cid: typeof cid === 'string' ? CID.parse(cid) : cid, - format: 'jpeg', - fit: 'cover', - height: 1000, - width: 3000, - min: true, - }) - } else if (id === 'feed_fullsize') { - return this.getSignedUri({ - cid: typeof cid === 'string' ? CID.parse(cid) : cid, - format: 'jpeg', - fit: 'inside', - height: 2000, - width: 2000, - min: true, - }) - } else if (id === 'feed_thumbnail') { - return this.getSignedUri({ - cid: typeof cid === 'string' ? CID.parse(cid) : cid, - format: 'jpeg', - fit: 'inside', - height: 1000, - width: 1000, - min: true, - }) - } else { - const exhaustiveCheck: never = id - throw new Error( - `Unrecognized requested common uri type: ${exhaustiveCheck}`, - ) - } - } - - getVerifiedOptions(path: string): Options & { cid: CID; signature: string } { - if (path.at(0) !== '/') { - throw new BadPathError('Invalid path: does not start with a slash') - } - const pathParts = path.split('/') // ['', sig, 'rs:fill:...', ...] - const [sig] = pathParts.splice(1, 1) // ['', 'rs:fill:...', ...] - const unsignedPath = pathParts.join('/') - if (!sig || sig.includes(':')) { - throw new BadPathError('Invalid path: missing signature') - } - const saltedPath = uint8arrays.concat([ - this.salt, - uint8arrays.fromString(unsignedPath), - ]) - const validSig = hmac(this.key, saltedPath).toString('base64url') - if (sig !== validSig) { - throw new BadPathError('Invalid path: bad signature') - } - const options = ImageUriBuilder.getOptions(unsignedPath) - return { - signature: validSig, - ...options, - } - } - - static getPath(opts: Options & { cid: CID }) { - const fit = opts.fit === 'inside' ? 'fit' : 'fill' // fit default is 'cover' - const enlarge = opts.min === true ? 1 : 0 // min default is false - const resize = `rs:${fit}:${opts.width}:${opts.height}:${enlarge}:0` // final ':0' is for interop with imgproxy - const minWidth = - opts.min && typeof opts.min === 'object' ? `mw:${opts.min.width}` : null - const minHeight = - opts.min && typeof opts.min === 'object' ? `mh:${opts.min.height}` : null - const quality = opts.quality ? `q:${opts.quality}` : null - return ( - `/` + - [resize, minWidth, minHeight, quality].filter(Boolean).join('/') + - `/plain/${opts.cid.toString()}@${opts.format}` - ) - } - - static getOptions(path: string): Options & { cid: CID } { - if (path.at(0) !== '/') { - throw new BadPathError('Invalid path: does not start with a slash') - } - const parts = path.split('/') - if (parts.at(-2) !== 'plain') { - throw new BadPathError('Invalid path') - } - const cidAndFormat = parts.at(-1) - const [cid, format, ...others] = cidAndFormat?.split('@') ?? [] - if (!cid || (format !== 'png' && format !== 'jpeg') || others.length) { - throw new BadPathError('Invalid path: bad cid/format part') - } - const resizePart = parts.find((part) => part.startsWith('rs:')) - const qualityPart = parts.find((part) => part.startsWith('q:')) - const minWidthPart = parts.find((part) => part.startsWith('mw:')) - const minHeightPart = parts.find((part) => part.startsWith('mh:')) - const [, fit, width, height, enlarge] = resizePart?.split(':') ?? [] - const [, quality] = qualityPart?.split(':') ?? [] - const [, minWidth] = minWidthPart?.split(':') ?? [] - const [, minHeight] = minHeightPart?.split(':') ?? [] - if (fit !== 'fill' && fit !== 'fit') { - throw new BadPathError('Invalid path: bad resize fit param') - } - if (isNaN(toInt(width)) || isNaN(toInt(height))) { - throw new BadPathError('Invalid path: bad resize height/width param') - } - if (enlarge !== '0' && enlarge !== '1') { - throw new BadPathError('Invalid path: bad resize enlarge param') - } - if (quality && isNaN(toInt(quality))) { - throw new BadPathError('Invalid path: bad quality param') - } - if ( - (!minWidth && minHeight) || - (minWidth && !minHeight) || - (minWidth && isNaN(toInt(minWidth))) || - (minHeight && isNaN(toInt(minHeight))) || - (enlarge === '1' && (minHeight || minHeight)) - ) { - throw new BadPathError('Invalid path: bad min width/height param') - } - return { - cid: CID.parse(cid), - format, - height: toInt(height), - width: toInt(width), - fit: fit === 'fill' ? 'cover' : 'inside', - quality: quality ? toInt(quality) : undefined, - min: - minWidth && minHeight - ? { width: toInt(minWidth), height: toInt(minHeight) } - : enlarge === '1', - } - } -} - -export class BadPathError extends Error {} - -function toInt(str: string) { - if (!/^\d+$/.test(str)) { - return NaN // String must be all numeric - } - return parseInt(str, 10) -} - -function hmac(key: Uint8Array, message: Uint8Array) { - return createHmac('sha256', key).update(message).digest() -} diff --git a/packages/pds/src/image/util.ts b/packages/pds/src/image/util.ts deleted file mode 100644 index ce18ba343d5..00000000000 --- a/packages/pds/src/image/util.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FormatEnum } from 'sharp' - -export type Options = Dimensions & { - format: 'jpeg' | 'png' - // When 'cover' (default), scale to fill given dimensions, cropping if necessary. - // When 'inside', scale to fit within given dimensions. - fit?: 'cover' | 'inside' - // When false (default), do not scale up. - // When true, scale up to hit dimensions given in options. - // Otherwise, scale up to hit specified min dimensions. - min?: Dimensions | boolean - // A number 1-100 - quality?: number -} - -export type ImageInfo = Dimensions & { - size: number - mime: `image/${string}` | 'unknown' -} - -export type Dimensions = { height: number; width: number } - -export const formatsToMimes: { [s in keyof FormatEnum]?: `image/${string}` } = { - jpg: 'image/jpeg', - jpeg: 'image/jpeg', - png: 'image/png', - gif: 'image/gif', - svg: 'image/svg+xml', - tif: 'image/tiff', - tiff: 'image/tiff', - webp: 'image/webp', -} diff --git a/packages/pds/src/index.ts b/packages/pds/src/index.ts index a156d8f7b8e..36f15adae8e 100644 --- a/packages/pds/src/index.ts +++ b/packages/pds/src/index.ts @@ -36,26 +36,18 @@ import { ServerMailer } from './mailer' import { ModerationMailer } from './mailer/moderation' import { createServer } from './lexicon' import { MessageDispatcher } from './event-stream/message-queue' -import { ImageUriBuilder } from './image/uri' -import { BlobDiskCache, ImageProcessingServer } from './image/server' import { createServices } from './services' import { createHttpTerminator, HttpTerminator } from 'http-terminator' import AppContext from './context' import { Sequencer, SequencerLeader } from './sequencer' -import { - ImageInvalidator, - ImageProcessingServerInvalidator, -} from './image/invalidator' import { Labeler, HiveLabeler, KeywordLabeler } from './labeler' import { BackgroundQueue } from './event-stream/background-queue' import DidSqlCache from './did-cache' -import { MountedAlgos } from './feed-gen/types' import { Crawlers } from './crawlers' import { LabelCache } from './label-cache' import { getRedisClient } from './redis' import { RuntimeFlags } from './runtime-flags' -export type { MountedAlgos } from './feed-gen/types' export type { ServerConfigValues } from './config' export { ServerConfig } from './config' export { Database } from './db' @@ -63,7 +55,6 @@ export { ViewMaintainer } from './db/views' export { PeriodicModerationActionReversal } from './db/periodic-moderation-action-reversal' export { DiskBlobStore, MemoryBlobStore } from './storage' export { AppContext } from './context' -export { makeAlgos } from './feed-gen' export class PDS { public ctx: AppContext @@ -81,21 +72,11 @@ export class PDS { static create(opts: { db: Database blobstore: BlobStore - imgInvalidator?: ImageInvalidator repoSigningKey: crypto.Keypair plcRotationKey: crypto.Keypair - algos?: MountedAlgos config: ServerConfig }): PDS { - const { - db, - blobstore, - repoSigningKey, - plcRotationKey, - algos = {}, - config, - } = opts - let maybeImgInvalidator = opts.imgInvalidator + const { db, blobstore, repoSigningKey, plcRotationKey, config } = opts const auth = new ServerAuth({ jwtSecret: config.jwtSecret, adminPass: config.adminPassword, @@ -142,35 +123,6 @@ export class PDS { app.use(loggerMiddleware) app.use(compression()) - let imgUriEndpoint = config.imgUriEndpoint - if (!imgUriEndpoint) { - const imgProcessingCache = new BlobDiskCache(config.blobCacheLocation) - const imgProcessingServer = new ImageProcessingServer( - config.imgUriSalt, - config.imgUriKey, - blobstore, - imgProcessingCache, - ) - maybeImgInvalidator ??= new ImageProcessingServerInvalidator( - imgProcessingCache, - ) - app.use('/image', imgProcessingServer.app) - imgUriEndpoint = `${config.publicUrl}/image` - } - - let imgInvalidator: ImageInvalidator - if (maybeImgInvalidator) { - imgInvalidator = maybeImgInvalidator - } else { - throw new Error('Missing PDS image invalidator') - } - - const imgUriBuilder = new ImageUriBuilder( - imgUriEndpoint, - config.imgUriSalt, - config.imgUriKey, - ) - const backgroundQueue = new BackgroundQueue(db) const crawlers = new Crawlers( config.hostname, @@ -198,17 +150,12 @@ export class PDS { } const labelCache = new LabelCache(db) - - const appviewAgent = config.bskyAppViewEndpoint - ? new AtpAgent({ service: config.bskyAppViewEndpoint }) - : undefined + const appviewAgent = new AtpAgent({ service: config.bskyAppViewEndpoint }) const services = createServices({ repoSigningKey, messageDispatcher, blobstore, - imgUriBuilder, - imgInvalidator, labeler, labelCache, appviewAgent, @@ -247,11 +194,9 @@ export class PDS { services, mailer, moderationMailer, - imgUriBuilder, backgroundQueue, appviewAgent, crawlers, - algos, }) const xrpcOpts: XrpcServerOptions = { diff --git a/packages/pds/src/services/index.ts b/packages/pds/src/services/index.ts index b49693cc8cf..a60451785ec 100644 --- a/packages/pds/src/services/index.ts +++ b/packages/pds/src/services/index.ts @@ -3,16 +3,11 @@ import * as crypto from '@atproto/crypto' import { BlobStore } from '@atproto/repo' import Database from '../db' import { MessageDispatcher } from '../event-stream/message-queue' -import { ImageUriBuilder } from '../image/uri' -import { ImageInvalidator } from '../image/invalidator' import { AccountService } from './account' import { AuthService } from './auth' import { RecordService } from './record' import { RepoService } from './repo' import { ModerationService } from './moderation' -import { ActorService } from '../app-view/services/actor' -import { GraphService } from '../app-view/services/graph' -import { FeedService } from '../app-view/services/feed' import { IndexingService } from '../app-view/services/indexing' import { Labeler } from '../labeler' import { LabelService } from '../app-view/services/label' @@ -25,8 +20,6 @@ export function createServices(resources: { repoSigningKey: crypto.Keypair messageDispatcher: MessageDispatcher blobstore: BlobStore - imgUriBuilder: ImageUriBuilder - imgInvalidator: ImageInvalidator labeler: Labeler labelCache: LabelCache appviewAgent?: AtpAgent @@ -39,8 +32,6 @@ export function createServices(resources: { repoSigningKey, messageDispatcher, blobstore, - imgUriBuilder, - imgInvalidator, labeler, labelCache, appviewAgent, @@ -67,16 +58,8 @@ export function createServices(resources: { appviewDid, appviewCdnUrlPattern, ), - moderation: ModerationService.creator( - messageDispatcher, - blobstore, - imgUriBuilder, - imgInvalidator, - ), + moderation: ModerationService.creator(messageDispatcher, blobstore), appView: { - actor: ActorService.creator(imgUriBuilder, labelCache), - graph: GraphService.creator(imgUriBuilder), - feed: FeedService.creator(imgUriBuilder, labelCache), indexing: IndexingService.creator(backgroundQueue), label: LabelService.creator(labelCache), }, @@ -91,10 +74,7 @@ export type Services = { local: FromDb moderation: FromDb appView: { - feed: FromDb indexing: FromDb - actor: FromDb - graph: FromDb label: FromDb } } diff --git a/packages/pds/src/services/moderation/index.ts b/packages/pds/src/services/moderation/index.ts index 0a5ba6d02b0..6104ffe728b 100644 --- a/packages/pds/src/services/moderation/index.ts +++ b/packages/pds/src/services/moderation/index.ts @@ -9,8 +9,6 @@ import { ModerationAction, ModerationReport } from '../../db/tables/moderation' import { RecordService } from '../record' import { ModerationViews } from './views' import SqlRepoStorage from '../../sql-repo-storage' -import { ImageInvalidator } from '../../image/invalidator' -import { ImageUriBuilder } from '../../image/uri' import { TAKEDOWN } from '../../lexicon/types/com/atproto/admin/defs' import { addHoursToDate } from '../../util/date' @@ -19,24 +17,11 @@ export class ModerationService { public db: Database, public messageDispatcher: MessageQueue, public blobstore: BlobStore, - public imgUriBuilder: ImageUriBuilder, - public imgInvalidator: ImageInvalidator, ) {} - static creator( - messageDispatcher: MessageQueue, - blobstore: BlobStore, - imgUriBuilder: ImageUriBuilder, - imgInvalidator: ImageInvalidator, - ) { + static creator(messageDispatcher: MessageQueue, blobstore: BlobStore) { return (db: Database) => - new ModerationService( - db, - messageDispatcher, - blobstore, - imgUriBuilder, - imgInvalidator, - ) + new ModerationService(db, messageDispatcher, blobstore) } views = new ModerationViews(this.db, this.messageDispatcher) @@ -497,14 +482,7 @@ export class ModerationService { .where('takedownId', 'is', null) .executeTakeFirst() await Promise.all( - info.blobCids.map(async (cid) => { - await this.blobstore.quarantine(cid) - const paths = ImageUriBuilder.commonSignedUris.map((id) => { - const uri = this.imgUriBuilder.getCommonSignedUri(id, cid) - return uri.replace(this.imgUriBuilder.endpoint, '') - }) - await this.imgInvalidator.invalidate(cid.toString(), paths) - }), + info.blobCids.map((cid) => this.blobstore.quarantine(cid)), ) } } diff --git a/packages/pds/tests/__snapshots__/feed-generation.test.ts.snap b/packages/pds/tests/__snapshots__/feed-generation.test.ts.snap deleted file mode 100644 index b1c5319fd7d..00000000000 --- a/packages/pds/tests/__snapshots__/feed-generation.test.ts.snap +++ /dev/null @@ -1,1382 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`feed generation does not embed taken-down feed generator records in posts 1`] = ` -Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewNotFound", - "notFound": true, - "uri": "record(2)", - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "weird feed", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, -} -`; - -exports[`feed generation embeds feed generator records in posts 1`] = ` -Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.feed.defs#generatorView", - "cid": "cids(2)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "description": "Provides all feed candidates", - "did": "user(1)", - "displayName": "All", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 2, - "uri": "record(2)", - "viewer": Object { - "like": "record(6)", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "cool feed!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, -} -`; - -exports[`feed generation getActorFeeds fetches feed generators by actor. 1`] = ` -Array [ - Object { - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides odd-indexed feed candidates", - "did": "user(0)", - "displayName": "Odd", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - Object { - "cid": "cids(2)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides all feed candidates, blindly ignoring pagination limit", - "did": "user(0)", - "displayName": "Bad Pagination", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - Object { - "cid": "cids(3)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides even-indexed feed candidates", - "did": "user(0)", - "displayName": "Even", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - Object { - "cid": "cids(4)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides all feed candidates", - "did": "user(0)", - "displayName": "All", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 2, - "uri": "record(6)", - "viewer": Object { - "like": "record(7)", - }, - }, -] -`; - -exports[`feed generation getFeed paginates, handling replies and reposts. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(0)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(4)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(2)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(6)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(6)", - "viewer": Object { - "like": "record(9)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(10)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(3)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(3)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(13)", - "muted": false, - }, - }, - "cid": "cids(9)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(4)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(6)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(6)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(4)", - "uri": "record(6)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(12)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, -] -`; - -exports[`feed generation getFeed resolves basic feed contents. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(0)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(2)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-a", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(5)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(5)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(4)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(5)", - "uri": "record(5)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(2)", - "viewer": Object { - "like": "record(9)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(10)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - }, - }, -] -`; - -exports[`feed generation getFeedGenerator describes a feed gen & returns online status 1`] = ` -Object { - "isOnline": true, - "isValid": true, - "view": Object { - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides all feed candidates", - "did": "user(0)", - "displayName": "All", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 2, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, -} -`; - -exports[`feed generation getFeedGenerators describes multiple feed gens 1`] = ` -Object { - "feeds": Array [ - Object { - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides all feed candidates", - "did": "user(0)", - "displayName": "All", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 2, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - Object { - "cid": "cids(2)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "description": "Provides even-indexed feed candidates", - "did": "user(0)", - "displayName": "Even", - "indexedAt": "1970-01-01T00:00:00.000Z", - "likeCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - ], -} -`; diff --git a/packages/pds/tests/__snapshots__/indexing.test.ts.snap b/packages/pds/tests/__snapshots__/indexing.test.ts.snap deleted file mode 100644 index c4bc3f83cf0..00000000000 --- a/packages/pds/tests/__snapshots__/indexing.test.ts.snap +++ /dev/null @@ -1,141 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`indexing indexes posts. 1`] = ` -Object { - "thread": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 9, - "byteStart": 0, - }, - }, - ], - "text": "@bob.test how are you?", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "replies": Array [], - }, -} -`; - -exports[`indexing indexes posts. 2`] = ` -Object { - "createNotifications": Array [ - Object { - "author": "user(1)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "reason": "mention", - "reasonSubject": null, - "recordCid": "cids(0)", - "recordUri": "record(0)", - "userDid": "user(0)", - }, - ], - "deleteNotifications": Array [], -} -`; - -exports[`indexing indexes profiles. 1`] = ` -Object { - "did": "user(0)", - "displayName": "dan", - "followersCount": 0, - "followsCount": 0, - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "postsCount": 0, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`indexing indexes profiles. 2`] = ` -Object { - "did": "user(0)", - "displayName": "danny", - "followersCount": 0, - "followsCount": 0, - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "postsCount": 0, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`indexing indexes profiles. 3`] = ` -Object { - "did": "user(0)", - "followersCount": 0, - "followsCount": 0, - "handle": "dan.test", - "labels": Array [], - "postsCount": 0, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`indexing indexes profiles. 4`] = ` -Object { - "createNotifications": Array [], - "deleteNotifications": Array [], - "updateNotifications": Array [], -} -`; diff --git a/packages/pds/tests/_util.ts b/packages/pds/tests/_util.ts index 0b94f09148b..16061b8af51 100644 --- a/packages/pds/tests/_util.ts +++ b/packages/pds/tests/_util.ts @@ -15,7 +15,6 @@ import DiskBlobStore from '../src/storage/disk-blobstore' import AppContext from '../src/context' import { DAY, HOUR } from '@atproto/common' import { lexToJson } from '@atproto/lexicon' -import { MountedAlgos } from '../src/feed-gen/types' const ADMIN_PASSWORD = 'admin-pass' const MODERATOR_PASSWORD = 'moderator-pass' @@ -31,7 +30,6 @@ export type TestServerInfo = { export type TestServerOpts = { migration?: string - algos?: MountedAlgos } export const runTestServer = async ( @@ -97,9 +95,6 @@ export const runTestServer = async ( appUrlPasswordReset: 'app://forgot-password', emailNoReplyAddress: 'noreply@blueskyweb.xyz', publicUrl: 'https://pds.public.url', - imgUriSalt: '9dd04221f5755bce5f55f47464c27e1e', - imgUriKey: - 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8', dbPostgresUrl: process.env.DB_POSTGRES_URL, blobstoreLocation: `${blobstoreLoc}/blobs`, blobstoreTmp: `${blobstoreLoc}/tmp`, @@ -109,8 +104,9 @@ export const runTestServer = async ( maxSubscriptionBuffer: 200, repoBackfillLimitMs: HOUR, sequencerLeaderLockId: uniqueLockId(), + bskyAppViewEndpoint: 'http://fake_address.invalid', + bskyAppViewDid: 'did:example:fake', dbTxLockNonce: await randomStr(32, 'base32'), - bskyAppViewProxy: false, ...params, }) @@ -153,7 +149,6 @@ export const runTestServer = async ( repoSigningKey, plcRotationKey, config: cfg, - algos: opts.algos, }) const pdsServer = await pds.start() const pdsPort = (pdsServer.address() as AddressInfo).port diff --git a/packages/pds/tests/account-deletion.test.ts b/packages/pds/tests/account-deletion.test.ts index 31ffcd1af5b..b99807ec6d5 100644 --- a/packages/pds/tests/account-deletion.test.ts +++ b/packages/pds/tests/account-deletion.test.ts @@ -237,29 +237,6 @@ describe('account deletion', () => { ) }) - it('no longer displays the users posts in feeds', async () => { - const feed = await agent.api.app.bsky.feed.getTimeline(undefined, { - headers: sc.getHeaders(sc.dids.alice), - }) - const found = feed.data.feed.filter( - (item) => item.post.author.did === carol.did, - ) - expect(found.length).toBe(0) - }) - - it('removes notifications from the user', async () => { - const notifs = await agent.api.app.bsky.notification.listNotifications( - undefined, - { - headers: sc.getHeaders(sc.dids.alice), - }, - ) - const found = notifs.data.notifications.filter( - (item) => item.author.did === sc.dids.carol, - ) - expect(found.length).toBe(0) - }) - it('can delete an empty user', async () => { const eve = await sc.createAccount('eve', { handle: 'eve.test', diff --git a/packages/pds/tests/views/admin/__snapshots__/get-moderation-action.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-moderation-action.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-moderation-action.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-moderation-action.test.ts.snap diff --git a/packages/pds/tests/views/admin/__snapshots__/get-moderation-actions.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-moderation-actions.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap diff --git a/packages/pds/tests/views/admin/__snapshots__/get-moderation-report.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-moderation-report.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-moderation-report.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-moderation-report.test.ts.snap diff --git a/packages/pds/tests/views/admin/__snapshots__/get-moderation-reports.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-moderation-reports.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap diff --git a/packages/pds/tests/views/admin/__snapshots__/get-record.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-record.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-record.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-record.test.ts.snap diff --git a/packages/pds/tests/views/admin/__snapshots__/get-repo.test.ts.snap b/packages/pds/tests/admin/__snapshots__/get-repo.test.ts.snap similarity index 100% rename from packages/pds/tests/views/admin/__snapshots__/get-repo.test.ts.snap rename to packages/pds/tests/admin/__snapshots__/get-repo.test.ts.snap diff --git a/packages/pds/tests/views/admin/get-moderation-action.test.ts b/packages/pds/tests/admin/get-moderation-action.test.ts similarity index 94% rename from packages/pds/tests/views/admin/get-moderation-action.test.ts rename to packages/pds/tests/admin/get-moderation-action.test.ts index 66562a73ec2..54b86984416 100644 --- a/packages/pds/tests/views/admin/get-moderation-action.test.ts +++ b/packages/pds/tests/admin/get-moderation-action.test.ts @@ -6,10 +6,10 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' -import { runTestServer, forSnapshot, CloseFn, adminAuth } from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../../src/lexicon/types/com/atproto/moderation/defs' +import { runTestServer, forSnapshot, CloseFn, adminAuth } from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get moderation action view', () => { let agent: AtpAgent diff --git a/packages/pds/tests/views/admin/get-moderation-actions.test.ts b/packages/pds/tests/admin/get-moderation-actions.test.ts similarity index 96% rename from packages/pds/tests/views/admin/get-moderation-actions.test.ts rename to packages/pds/tests/admin/get-moderation-actions.test.ts index 31ee1686c3c..1ad5e066c60 100644 --- a/packages/pds/tests/views/admin/get-moderation-actions.test.ts +++ b/packages/pds/tests/admin/get-moderation-actions.test.ts @@ -7,16 +7,16 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' +} from '../../src/lexicon/types/com/atproto/moderation/defs' import { runTestServer, forSnapshot, CloseFn, adminAuth, paginateAll, -} from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get moderation actions view', () => { let agent: AtpAgent diff --git a/packages/pds/tests/views/admin/get-moderation-report.test.ts b/packages/pds/tests/admin/get-moderation-report.test.ts similarity index 94% rename from packages/pds/tests/views/admin/get-moderation-report.test.ts rename to packages/pds/tests/admin/get-moderation-report.test.ts index c1363a0c49f..7d433539b37 100644 --- a/packages/pds/tests/views/admin/get-moderation-report.test.ts +++ b/packages/pds/tests/admin/get-moderation-report.test.ts @@ -6,10 +6,10 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' -import { runTestServer, forSnapshot, CloseFn, adminAuth } from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../../src/lexicon/types/com/atproto/moderation/defs' +import { runTestServer, forSnapshot, CloseFn, adminAuth } from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get moderation action view', () => { let agent: AtpAgent diff --git a/packages/pds/tests/views/admin/get-moderation-reports.test.ts b/packages/pds/tests/admin/get-moderation-reports.test.ts similarity index 98% rename from packages/pds/tests/views/admin/get-moderation-reports.test.ts rename to packages/pds/tests/admin/get-moderation-reports.test.ts index 14be4ce821a..20f1c97f781 100644 --- a/packages/pds/tests/views/admin/get-moderation-reports.test.ts +++ b/packages/pds/tests/admin/get-moderation-reports.test.ts @@ -7,16 +7,16 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' +} from '../../src/lexicon/types/com/atproto/moderation/defs' import { runTestServer, forSnapshot, CloseFn, adminAuth, paginateAll, -} from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get moderation reports view', () => { let agent: AtpAgent diff --git a/packages/pds/tests/views/admin/get-record.test.ts b/packages/pds/tests/admin/get-record.test.ts similarity index 95% rename from packages/pds/tests/views/admin/get-record.test.ts rename to packages/pds/tests/admin/get-record.test.ts index 797a4b726f2..d70707b2b70 100644 --- a/packages/pds/tests/views/admin/get-record.test.ts +++ b/packages/pds/tests/admin/get-record.test.ts @@ -7,16 +7,16 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' +} from '../../src/lexicon/types/com/atproto/moderation/defs' import { runTestServer, forSnapshot, CloseFn, adminAuth, TestServerInfo, -} from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get record view', () => { let server: TestServerInfo diff --git a/packages/pds/tests/views/admin/get-repo.test.ts b/packages/pds/tests/admin/get-repo.test.ts similarity index 95% rename from packages/pds/tests/views/admin/get-repo.test.ts rename to packages/pds/tests/admin/get-repo.test.ts index c0f8d500c90..3cb997f6ff2 100644 --- a/packages/pds/tests/views/admin/get-repo.test.ts +++ b/packages/pds/tests/admin/get-repo.test.ts @@ -6,7 +6,7 @@ import { import { REASONOTHER, REASONSPAM, -} from '../../../src/lexicon/types/com/atproto/moderation/defs' +} from '../../src/lexicon/types/com/atproto/moderation/defs' import { runTestServer, forSnapshot, @@ -15,9 +15,9 @@ import { TestServerInfo, moderatorAuth, triageAuth, -} from '../../_util' -import { SeedClient } from '../../seeds/client' -import basicSeed from '../../seeds/basic' +} from '../_util' +import { SeedClient } from '../seeds/client' +import basicSeed from '../seeds/basic' describe('pds admin get repo view', () => { let server: TestServerInfo diff --git a/packages/pds/tests/views/admin/invites.test.ts b/packages/pds/tests/admin/invites.test.ts similarity index 99% rename from packages/pds/tests/views/admin/invites.test.ts rename to packages/pds/tests/admin/invites.test.ts index d315b7dbdd7..6cdfdbaba93 100644 --- a/packages/pds/tests/views/admin/invites.test.ts +++ b/packages/pds/tests/admin/invites.test.ts @@ -4,9 +4,9 @@ import { adminAuth, moderatorAuth, TestServerInfo, -} from '../../_util' +} from '../_util' import { randomStr } from '@atproto/crypto' -import { SeedClient } from '../../seeds/client' +import { SeedClient } from '../seeds/client' describe('pds admin invite views', () => { let agent: AtpAgent diff --git a/packages/pds/tests/views/admin/repo-search.test.ts b/packages/pds/tests/admin/repo-search.test.ts similarity index 98% rename from packages/pds/tests/views/admin/repo-search.test.ts rename to packages/pds/tests/admin/repo-search.test.ts index e468a58a663..3f25c893901 100644 --- a/packages/pds/tests/views/admin/repo-search.test.ts +++ b/packages/pds/tests/admin/repo-search.test.ts @@ -6,10 +6,10 @@ import { CloseFn, paginateAll, adminAuth, -} from '../../_util' -import { SeedClient } from '../../seeds/client' -import usersBulkSeed from '../../seeds/users-bulk' -import { Database } from '../../../src' +} from '../_util' +import { SeedClient } from '../seeds/client' +import usersBulkSeed from '../seeds/users-bulk' +import { Database } from '../../src' describe('pds admin repo search view', () => { let agent: AtpAgent diff --git a/packages/pds/tests/algos/hot-classic.test.ts b/packages/pds/tests/algos/hot-classic.test.ts deleted file mode 100644 index 82a65f5c852..00000000000 --- a/packages/pds/tests/algos/hot-classic.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import AtpAgent, { AtUri } from '@atproto/api' -import { runTestServer, TestServerInfo } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { makeAlgos } from '../../src' - -describe.skip('algo hot-classic', () => { - let server: TestServerInfo - let agent: AtpAgent - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - - const feedPublisherDid = 'did:example:feed-publisher' - const feedUri = AtUri.make( - feedPublisherDid, - 'app.bsky.feed.generator', - 'hot-classic', - ).toString() - - beforeAll(async () => { - server = await runTestServer( - { - dbPostgresSchema: 'algo_hot_classic', - }, - { - algos: makeAlgos(feedPublisherDid), - }, - ) - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - - alice = sc.dids.alice - bob = sc.dids.bob - await server.processAll() - }) - - afterAll(async () => { - await server.close() - }) - - it('returns well liked posts', async () => { - const img = await sc.uploadFile( - alice, - 'tests/image/fixtures/key-landscape-small.jpg', - 'image/jpeg', - ) - const one = await sc.post(alice, 'first post', undefined, [img]) - const two = await sc.post(bob, 'bobby boi') - const three = await sc.reply(bob, one.ref, one.ref, 'reply') - - for (let i = 0; i < 12; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - await sc.like(sc.dids[name], one.ref) - await sc.like(sc.dids[name], two.ref) - await sc.like(sc.dids[name], three.ref) - } - await server.processAll() - - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - const feedUris = res.data.feed.map((i) => i.post.uri).sort() - const expected = [one.ref.uriStr, two.ref.uriStr].sort() - expect(feedUris).toEqual(expected) - }) - - it('paginates', async () => { - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - const first = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, limit: 1 }, - { headers: sc.getHeaders(alice) }, - ) - const second = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, cursor: first.data.cursor }, - { headers: sc.getHeaders(alice) }, - ) - - expect([...first.data.feed, ...second.data.feed]).toEqual(res.data.feed) - }) -}) diff --git a/packages/pds/tests/algos/whats-hot.test.ts b/packages/pds/tests/algos/whats-hot.test.ts deleted file mode 100644 index 9ad33621af4..00000000000 --- a/packages/pds/tests/algos/whats-hot.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { HOUR } from '@atproto/common' -import AtpAgent, { AtUri } from '@atproto/api' -import { runTestServer, TestServerInfo } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { makeAlgos } from '../../src' - -describe.skip('algo whats-hot', () => { - let server: TestServerInfo - let agent: AtpAgent - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - - const feedPublisherDid = 'did:example:feed-publisher' - const feedUri = AtUri.make( - feedPublisherDid, - 'app.bsky.feed.generator', - 'whats-hot', - ).toString() - - beforeAll(async () => { - server = await runTestServer( - { - dbPostgresSchema: 'algo_whats_hot', - }, - { - algos: makeAlgos(feedPublisherDid), - }, - ) - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - await server.processAll() - }) - - afterAll(async () => { - await server.close() - }) - - it('returns well liked posts', async () => { - if (server.ctx.db.dialect === 'sqlite') return - - const img = await sc.uploadFile( - alice, - 'tests/image/fixtures/key-landscape-small.jpg', - 'image/jpeg', - ) - const one = await sc.post(carol, 'carol is in the chat') - const two = await sc.post(carol, "it's me, carol") - const three = await sc.post(alice, 'first post', undefined, [img]) - const four = await sc.post(bob, 'bobby boi') - const five = await sc.post(bob, 'another one') - - for (let i = 0; i < 20; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - await sc.like(sc.dids[name], three.ref) // will be down-regulated by time - if (i > 3) { - await sc.like(sc.dids[name], one.ref) - } - if (i > 5) { - await sc.like(sc.dids[name], two.ref) - } - if (i > 7) { - await sc.like(sc.dids[name], four.ref) - await sc.like(sc.dids[name], five.ref) - } - } - await server.processAll() - - // move the 3rd post 5 hours into the past to check gravity - await server.ctx.db.db - .updateTable('post') - .where('uri', '=', three.ref.uriStr) - .set({ indexedAt: new Date(Date.now() - 5 * HOUR).toISOString() }) - .execute() - - await server.ctx.db.refreshMaterializedView('algo_whats_hot_view') - - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - expect(res.data.feed[0].post.uri).toBe(one.ref.uriStr) - expect(res.data.feed[1].post.uri).toBe(two.ref.uriStr) - const indexOfThird = res.data.feed.findIndex( - (item) => item.post.uri === three.ref.uriStr, - ) - // doesn't quite matter where this cam in but it should be down-regulated pretty severely from gravity - expect(indexOfThird).toBeGreaterThan(3) - }) - - it('paginates', async () => { - if (server.ctx.db.dialect === 'sqlite') return - - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - const first = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, limit: 3 }, - { headers: sc.getHeaders(alice) }, - ) - const second = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, cursor: first.data.cursor }, - { headers: sc.getHeaders(alice) }, - ) - - expect([...first.data.feed, ...second.data.feed]).toEqual(res.data.feed) - }) -}) diff --git a/packages/pds/tests/algos/with-friends.test.ts b/packages/pds/tests/algos/with-friends.test.ts deleted file mode 100644 index 7e6e79357d9..00000000000 --- a/packages/pds/tests/algos/with-friends.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -import AtpAgent, { AtUri } from '@atproto/api' -import { runTestServer, TestServerInfo } from '../_util' -import { RecordRef, SeedClient } from '../seeds/client' -import userSeed from '../seeds/users' -import { makeAlgos } from '../../src' - -describe.skip('algo with friends', () => { - let server: TestServerInfo - let agent: AtpAgent - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - let dan: string - - const feedPublisherDid = 'did:example:feed-publisher' - const feedUri = AtUri.make( - feedPublisherDid, - 'app.bsky.feed.generator', - 'with-friends', - ).toString() - - beforeAll(async () => { - server = await runTestServer( - { - dbPostgresSchema: 'algo_with_friends', - }, - { - algos: makeAlgos(feedPublisherDid), - }, - ) - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await userSeed(sc) - - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - dan = sc.dids.dan - - await server.processAll() - }) - - afterAll(async () => { - await server.close() - }) - - let expectedFeed: string[] - - it('setup', async () => { - for (let i = 0; i < 10; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - } - - const hitLikeThreshold = async (ref: RecordRef) => { - for (let i = 0; i < 10; i++) { - const name = `user${i}` - await sc.like(sc.dids[name], ref) - } - } - - // bob and dan are mutuals of alice, all userN are out-of-network. - await sc.follow(alice, bob) - await sc.follow(alice, carol) - await sc.follow(alice, dan) - await sc.follow(bob, alice) - await sc.follow(dan, alice) - const one = await sc.post(bob, 'one') - const two = await sc.post(bob, 'two') - const three = await sc.post(carol, 'three') - const four = await sc.post(carol, 'four') - const five = await sc.post(dan, 'five') - const six = await sc.post(dan, 'six') - const seven = await sc.post(sc.dids.user0, 'seven') - const eight = await sc.post(sc.dids.user0, 'eight') - const nine = await sc.post(sc.dids.user1, 'nine') - const ten = await sc.post(sc.dids.user1, 'ten') - - // 1, 2, 3, 4, 6, 8, 10 hit like threshold - await hitLikeThreshold(one.ref) - await hitLikeThreshold(two.ref) - await hitLikeThreshold(three.ref) - await hitLikeThreshold(four.ref) - await hitLikeThreshold(six.ref) - await hitLikeThreshold(eight.ref) - await hitLikeThreshold(ten.ref) - - // 1, 4, 7, 8, 10 liked by mutual - await sc.like(bob, one.ref) - await sc.like(dan, four.ref) - await sc.like(bob, seven.ref) - await sc.like(dan, eight.ref) - await sc.like(bob, nine.ref) - await sc.like(dan, ten.ref) - - // all liked by non-mutual - await sc.like(carol, one.ref) - await sc.like(carol, two.ref) - await sc.like(carol, three.ref) - await sc.like(carol, four.ref) - await sc.like(carol, five.ref) - await sc.like(carol, six.ref) - await sc.like(carol, seven.ref) - await sc.like(carol, eight.ref) - await sc.like(carol, nine.ref) - await sc.like(carol, ten.ref) - - expectedFeed = [ - ten.ref.uriStr, - eight.ref.uriStr, - four.ref.uriStr, - one.ref.uriStr, - ] - }) - - it('returns popular in & out of network posts', async () => { - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - const feedUris = res.data.feed.map((i) => i.post.uri) - expect(feedUris).toEqual(expectedFeed) - }) - - it('paginates', async () => { - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri }, - { headers: sc.getHeaders(alice) }, - ) - const first = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, limit: 2 }, - { headers: sc.getHeaders(alice) }, - ) - const second = await agent.api.app.bsky.feed.getFeed( - { feed: feedUri, cursor: first.data.cursor }, - { headers: sc.getHeaders(alice) }, - ) - - expect([...first.data.feed, ...second.data.feed]).toEqual(res.data.feed) - }) -}) diff --git a/packages/pds/tests/feed-generation.test.ts b/packages/pds/tests/feed-generation.test.ts deleted file mode 100644 index 41b21901ba4..00000000000 --- a/packages/pds/tests/feed-generation.test.ts +++ /dev/null @@ -1,518 +0,0 @@ -import { AtUri, AtpAgent } from '@atproto/api' -import { Handler as SkeletonHandler } from '@atproto/pds/src/lexicon/types/app/bsky/feed/getFeedSkeleton' -import { UnknownFeedError } from '@atproto/api/src/client/types/app/bsky/feed/getFeed' -import { SeedClient } from './seeds/client' -import basicSeed from './seeds/basic' -import { TestNetworkNoAppView } from '@atproto/dev-env' -import { TestFeedGen } from '@atproto/dev-env/src/feed-gen' -import { TID } from '@atproto/common' -import { adminAuth, forSnapshot, paginateAll } from './_util' -import { - FeedViewPost, - GeneratorView, -} from '@atproto/api/src/client/types/app/bsky/feed/defs' -import { SkeletonFeedPost } from '../src/lexicon/types/app/bsky/feed/defs' -import { RecordRef } from './seeds/client' -import { ids } from '../src/lexicon/lexicons' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' - -describe('feed generation', () => { - let network: TestNetworkNoAppView - let agent: AtpAgent - let sc: SeedClient - let gen: TestFeedGen - - let alice: string - let feedUriAll: string - let feedUriAllRef: RecordRef - let feedUriEven: string - let feedUriOdd: string // Unsupported by feed gen - let feedUriBadPagination: string - let feedUriPrime: string // Taken-down - let feedUriPrimeRef: RecordRef - - beforeAll(async () => { - network = await TestNetworkNoAppView.create({ - dbPostgresSchema: 'feed_generation', - }) - agent = network.pds.getClient() - sc = new SeedClient(agent) - await basicSeed(sc) - await network.processAll() - alice = sc.dids.alice - const allUri = AtUri.make(alice, 'app.bsky.feed.generator', 'all') - const feedUriBadPagination = AtUri.make( - alice, - 'app.bsky.feed.generator', - 'bad-pagination', - ) - const evenUri = AtUri.make(alice, 'app.bsky.feed.generator', 'even') - const primeUri = AtUri.make(alice, 'app.bsky.feed.generator', 'prime') - gen = await network.createFeedGen({ - [allUri.toString()]: feedGenHandler('all'), - [evenUri.toString()]: feedGenHandler('even'), - [feedUriBadPagination.toString()]: feedGenHandler('bad-pagination'), - [primeUri.toString()]: feedGenHandler('prime'), - }) - }) - - afterAll(async () => { - await network.close() - }) - - it('describes the feed generator', async () => { - const res = await agent.api.app.bsky.feed.describeFeedGenerator() - expect(res.data.did).toBe(network.pds.ctx.cfg.feedGenDid) - }) - - it('feed gen records can be created.', async () => { - const all = await agent.api.app.bsky.feed.generator.create( - { repo: alice, rkey: 'all' }, - { - did: gen.did, - displayName: 'All', - description: 'Provides all feed candidates', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - const even = await agent.api.app.bsky.feed.generator.create( - { repo: alice, rkey: 'even' }, - { - did: gen.did, - displayName: 'Even', - description: 'Provides even-indexed feed candidates', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - // Unsupported by feed gen - const odd = await agent.api.app.bsky.feed.generator.create( - { repo: alice, rkey: 'odd' }, - { - did: gen.did, - displayName: 'Temp', // updated in next test - description: 'Temp', // updated in next test - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - const badPagination = await agent.api.app.bsky.feed.generator.create( - { repo: alice, rkey: 'bad-pagination' }, - { - did: gen.did, - displayName: 'Bad Pagination', - description: - 'Provides all feed candidates, blindly ignoring pagination limit', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - // Taken-down - const prime = await agent.api.app.bsky.feed.generator.create( - { repo: alice, rkey: 'prime' }, - { - did: gen.did, - displayName: 'Prime', - description: 'Provides prime-indexed feed candidates', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: prime.uri, - cid: prime.cid, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - feedUriAll = all.uri - feedUriAllRef = new RecordRef(all.uri, all.cid) - feedUriEven = even.uri - feedUriOdd = odd.uri - feedUriBadPagination = badPagination.uri - feedUriPrime = prime.uri - feedUriPrimeRef = new RecordRef(prime.uri, prime.cid) - }) - - it('feed gen records can be updated', async () => { - await agent.api.com.atproto.repo.putRecord( - { - repo: alice, - collection: ids.AppBskyFeedGenerator, - rkey: 'odd', - record: { - did: gen.did, - displayName: 'Odd', - description: 'Provides odd-indexed feed candidates', - createdAt: new Date().toISOString(), - }, - }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - }) - - it('getActorFeeds fetches feed generators by actor.', async () => { - // add some likes - await sc.like(sc.dids.bob, feedUriAllRef) - await sc.like(sc.dids.carol, feedUriAllRef) - - const results = (results) => results.flatMap((res) => res.feeds) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getActorFeeds( - { actor: alice, cursor, limit: 2 }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - return res.data - } - - const paginatedAll: GeneratorView[] = results(await paginateAll(paginator)) - - expect(paginatedAll.length).toEqual(4) - expect(paginatedAll[0].uri).toEqual(feedUriOdd) - expect(paginatedAll[1].uri).toEqual(feedUriBadPagination) - expect(paginatedAll[2].uri).toEqual(feedUriEven) - expect(paginatedAll[3].uri).toEqual(feedUriAll) - expect(paginatedAll.map((fg) => fg.uri)).not.toContain(feedUriPrime) // taken-down - expect(forSnapshot(paginatedAll)).toMatchSnapshot() - }) - - it('embeds feed generator records in posts', async () => { - const res = await agent.api.app.bsky.feed.post.create( - { repo: sc.dids.bob }, - { - text: 'cool feed!', - embed: { - $type: 'app.bsky.embed.record', - record: feedUriAllRef.raw, - }, - createdAt: new Date().toISOString(), - }, - sc.getHeaders(sc.dids.bob), - ) - const view = await agent.api.app.bsky.feed.getPosts( - { uris: [res.uri] }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(view.data.posts.length).toBe(1) - expect(forSnapshot(view.data.posts[0])).toMatchSnapshot() - }) - - it('does not embed taken-down feed generator records in posts', async () => { - const res = await agent.api.app.bsky.feed.post.create( - { repo: sc.dids.bob }, - { - text: 'weird feed', - embed: { - $type: 'app.bsky.embed.record', - record: feedUriPrimeRef.raw, - }, - createdAt: new Date().toISOString(), - }, - sc.getHeaders(sc.dids.bob), - ) - const view = await agent.api.app.bsky.feed.getPosts( - { uris: [res.uri] }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(view.data.posts.length).toBe(1) - expect(forSnapshot(view.data.posts[0])).toMatchSnapshot() - }) - - describe('getFeedGenerator', () => { - it('describes a feed gen & returns online status', async () => { - const resEven = await agent.api.app.bsky.feed.getFeedGenerator( - { feed: feedUriAll }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(forSnapshot(resEven.data)).toMatchSnapshot() - expect(resEven.data.isOnline).toBe(true) - expect(resEven.data.isValid).toBe(true) - }) - - it('does not describe taken-down feed', async () => { - const tryGetFeed = agent.api.app.bsky.feed.getFeedGenerator( - { feed: feedUriPrime }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - await expect(tryGetFeed).rejects.toThrow('could not find feed') - }) - - // @TODO temporarily skipping while external feedgens catch-up on describeFeedGenerator - it.skip('handles an unsupported algo', async () => { - const resOdd = await agent.api.app.bsky.feed.getFeedGenerator( - { feed: feedUriOdd }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(resOdd.data.isOnline).toBe(true) - expect(resOdd.data.isValid).toBe(false) - }) - - // @TODO temporarily skipping while external feedgens catch-up on describeFeedGenerator - it.skip('handles an offline feed', async () => { - // make an invalid feed gen in bob's repo - const allUriBob = AtUri.make( - sc.dids.bob, - 'app.bsky.feed.generator', - 'all', - ) - const bobFg = await network.createFeedGen({ - [allUriBob.toString()]: feedGenHandler('all'), - }) - - await agent.api.app.bsky.feed.generator.create( - { repo: sc.dids.bob, rkey: 'all' }, - { - did: bobFg.did, - displayName: 'All by bob', - description: 'Provides all feed candidates - by bob', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(sc.dids.bob), - ) - - // now take it offline - await bobFg.close() - - const res = await agent.api.app.bsky.feed.getFeedGenerator( - { - feed: allUriBob.toString(), - }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - expect(res.data.isOnline).toBe(false) - expect(res.data.isValid).toBe(false) - }) - }) - - describe('getFeedGenerators', () => { - it('describes multiple feed gens', async () => { - const resEven = await agent.api.app.bsky.feed.getFeedGenerators( - { feeds: [feedUriEven, feedUriAll, feedUriPrime] }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(forSnapshot(resEven.data)).toMatchSnapshot() - expect(resEven.data.feeds.map((fg) => fg.uri)).not.toContain(feedUriPrime) // taken-down - }) - }) - - describe('getPopularFeedGenerators', () => { - it('gets popular feed generators', async () => { - const res = await agent.api.app.bsky.unspecced.getPopularFeedGenerators( - {}, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect(res.data.feeds.map((f) => f.likeCount)).toEqual([2, 0, 0, 0]) - expect(res.data.feeds.map((f) => f.uri)).not.toContain(feedUriPrime) // taken-down - }) - - it('paginates', async () => { - const resFull = - await agent.api.app.bsky.unspecced.getPopularFeedGenerators( - {}, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - - const resOne = - await agent.api.app.bsky.unspecced.getPopularFeedGenerators( - { limit: 2 }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - const resTwo = - await agent.api.app.bsky.unspecced.getPopularFeedGenerators( - { cursor: resOne.data.cursor }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - expect([...resOne.data.feeds, ...resTwo.data.feeds]).toEqual( - resFull.data.feeds, - ) - }) - - it('searches', async () => { - const res = await agent.api.app.bsky.unspecced.getPopularFeedGenerators( - { query: 'pagination' }, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - - expect(res.data.feeds[0].displayName).toBe('Bad Pagination') - }) - }) - - describe('getFeed', () => { - it('resolves basic feed contents.', async () => { - const feed = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriEven }, - { headers: sc.getHeaders(alice) }, - ) - expect(feed.data.feed.map((item) => item.post.uri)).toEqual([ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.carol][0].ref.uriStr, - sc.replies[sc.dids.carol][0].ref.uriStr, - ]) - expect(forSnapshot(feed.data.feed)).toMatchSnapshot() - }) - - it('paginates, handling replies and reposts.', async () => { - const results = (results) => results.flatMap((res) => res.feed) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriAll, cursor, limit: 2 }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll: FeedViewPost[] = results(await paginateAll(paginator)) - - // Unknown post uri is omitted - expect(paginatedAll.map((item) => item.post.uri)).toEqual([ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - sc.posts[sc.dids.carol][0].ref.uriStr, - sc.replies[sc.dids.carol][0].ref.uriStr, - sc.posts[sc.dids.dan][1].ref.uriStr, - ]) - expect(forSnapshot(paginatedAll)).toMatchSnapshot() - }) - - it('paginates, handling feed not respecting limit.', async () => { - const res = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriBadPagination, limit: 3 }, - { headers: sc.getHeaders(alice) }, - ) - // refused to respect pagination limit, so it got cut short by appview but the cursor remains. - expect(res.data.feed.length).toBeLessThanOrEqual(3) - expect(parseInt(res.data.cursor || '', 10)).toBeGreaterThanOrEqual(3) - expect(res.data.feed.map((item) => item.post.uri)).toEqual([ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - sc.posts[sc.dids.carol][0].ref.uriStr, - ]) - }) - - it('fails on unknown feed.', async () => { - const tryGetFeed = agent.api.app.bsky.feed.getFeed( - { feed: feedUriOdd }, - { headers: sc.getHeaders(alice) }, - ) - await expect(tryGetFeed).rejects.toThrow(UnknownFeedError) - }) - - it('resolves contents of taken-down feed.', async () => { - const tryGetFeed = agent.api.app.bsky.feed.getFeed( - { feed: feedUriPrime }, - { headers: sc.getHeaders(alice) }, - ) - await expect(tryGetFeed).resolves.toBeDefined() - }) - - it('receives proper auth details.', async () => { - const feed = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriEven }, - { headers: sc.getHeaders(alice) }, - ) - expect(feed.data['$auth']?.['aud']).toEqual(gen.did) - expect(feed.data['$auth']?.['iss']).toEqual(alice) - }) - - it('receives proper auth details.', async () => { - const feed = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriEven }, - { headers: sc.getHeaders(alice) }, - ) - expect(feed.data['$auth']?.['aud']).toEqual(gen.did) - expect(feed.data['$auth']?.['iss']).toEqual(alice) - }) - - it('provides timing info in server-timing header.', async () => { - const result = await agent.api.app.bsky.feed.getFeed( - { feed: feedUriEven }, - { headers: sc.getHeaders(alice) }, - ) - expect(result.headers['server-timing']).toMatch( - /^skele;dur=\d+, hydr;dur=\d+$/, - ) - }) - - it('returns an upstream failure error when the feed is down.', async () => { - await gen.close() // @NOTE must be last test - const tryGetFeed = agent.api.app.bsky.feed.getFeed( - { feed: feedUriEven }, - { headers: sc.getHeaders(alice) }, - ) - await expect(tryGetFeed).rejects.toThrow('feed unavailable') - }) - }) - - const feedGenHandler = - (feedName: 'even' | 'all' | 'prime' | 'bad-pagination'): SkeletonHandler => - async ({ req, params }) => { - const { limit, cursor } = params - const candidates: SkeletonFeedPost[] = [ - { post: sc.posts[sc.dids.alice][0].ref.uriStr }, - { post: sc.posts[sc.dids.bob][0].ref.uriStr }, - { post: sc.posts[sc.dids.carol][0].ref.uriStr }, - { post: `at://did:plc:unknown/app.bsky.feed.post/${TID.nextStr()}` }, // Doesn't exist - { post: sc.replies[sc.dids.carol][0].ref.uriStr }, // Reply - // Repost (accurate) - { - post: sc.posts[sc.dids.dan][1].ref.uriStr, - reason: { - $type: 'app.bsky.feed.defs#skeletonReasonRepost', - repost: sc.reposts[sc.dids.carol][0].uriStr, - }, - }, - // Repost (inaccurate) - { - post: sc.posts[alice][1].ref.uriStr, - reason: { - $type: 'app.bsky.feed.defs#skeletonReasonRepost', - repost: sc.reposts[sc.dids.carol][0].uriStr, - }, - }, - ] - const offset = cursor ? parseInt(cursor, 10) : 0 - const fullFeed = candidates.filter((_, i) => { - if (feedName === 'even') { - return i % 2 === 0 - } - if (feedName === 'prime') { - return [2, 3, 5, 7, 11, 13].includes(i) - } - return true - }) - const feedResults = - feedName === 'bad-pagination' - ? fullFeed.slice(offset) // does not respect limit - : fullFeed.slice(offset, offset + limit) - const lastResult = feedResults.at(-1) - return { - encoding: 'application/json', - body: { - feed: feedResults, - cursor: lastResult - ? (fullFeed.indexOf(lastResult) + 1).toString() - : undefined, - $auth: jwtBody(req.headers.authorization), // for testing purposes - }, - } - } -}) - -const jwtBody = (authHeader?: string): Record | undefined => { - if (!authHeader?.startsWith('Bearer')) return undefined - const jwt = authHeader.replace('Bearer ', '') - const [, bodyb64] = jwt.split('.') - const body = JSON.parse(Buffer.from(bodyb64, 'base64').toString()) - if (!body || typeof body !== 'object') return undefined - return body -} diff --git a/packages/pds/tests/file-uploads.test.ts b/packages/pds/tests/file-uploads.test.ts index fa36a4fb473..cd26c7fa0a8 100644 --- a/packages/pds/tests/file-uploads.test.ts +++ b/packages/pds/tests/file-uploads.test.ts @@ -5,8 +5,6 @@ import { CloseFn, runTestServer, TestServerInfo } from './_util' import { Database, ServerConfig } from '../src' import DiskBlobStore from '../src/storage/disk-blobstore' import * as uint8arrays from 'uint8arrays' -import * as image from '../src/image' -import axios from 'axios' import { randomBytes } from '@atproto/crypto' import { BlobRef } from '@atproto/lexicon' import { ids } from '../src/lexicon/lexicons' @@ -147,24 +145,6 @@ describe('file uploads', () => { expect(uint8arrays.equals(smallFile, new Uint8Array(data))).toBeTruthy() }) - it('serves the referenced blob', async () => { - const profile = await aliceAgent.api.app.bsky.actor.getProfile({ - actor: 'alice.test', - }) - const avatar = profile.data.avatar as string - expect(typeof avatar).toBe('string') - const url = avatar.replace(cfg.publicUrl, serverUrl) - const res = await axios.get(url, { responseType: 'stream' }) - expect(res.headers['content-type']).toBe('image/jpeg') - const info = await image.getInfo(res.data) - expect(info).toEqual( - expect.objectContaining({ - height: 1000, - width: 1000, - }), - ) - }) - let largeBlob: BlobRef let largeFile: Uint8Array diff --git a/packages/pds/tests/handles.test.ts b/packages/pds/tests/handles.test.ts index b0827b2e953..d6b6fd60caa 100644 --- a/packages/pds/tests/handles.test.ts +++ b/packages/pds/tests/handles.test.ts @@ -50,6 +50,15 @@ describe('handles', () => { await close() }) + const getHandleFromDb = async (did: string): Promise => { + const res = await ctx.db.db + .selectFrom('did_handle') + .selectAll() + .where('did', '=', did) + .executeTakeFirst() + return res?.handle + } + it('resolves handles', async () => { const res = await agent.api.com.atproto.identity.resolveHandle({ handle: 'alice.test', @@ -93,35 +102,6 @@ describe('handles', () => { sc.accounts[alice].refreshJwt = res.data.refreshJwt }) - it('returns the correct handle in views', async () => { - const profile = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - expect(profile.data.handle).toBe(newHandle) - - const timeline = await agent.api.app.bsky.feed.getTimeline( - {}, - { headers: sc.getHeaders(bob) }, - ) - - const alicePosts = timeline.data.feed.filter( - (post) => post.post.author.did === alice, - ) - for (const post of alicePosts) { - expect(post.post.author.handle).toBe(newHandle) - } - - const followers = await agent.api.app.bsky.graph.getFollowers( - { actor: bob }, - { headers: sc.getHeaders(bob) }, - ) - - const aliceFollows = followers.data.followers.filter((f) => f.did === alice) - expect(aliceFollows.length).toBe(1) - expect(aliceFollows[0].handle).toBe(newHandle) - }) - it('does not allow taking a handle that already exists', async () => { const attempt = agent.api.com.atproto.identity.updateHandle( { handle: 'Bob.test' }, @@ -194,11 +174,8 @@ describe('handles', () => { }, { headers: sc.getHeaders(alice), encoding: 'application/json' }, ) - const profile = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - expect(profile.data.handle).toBe('alice.external') + const dbHandle = await getHandleFromDb(alice) + expect(dbHandle).toBe('alice.external') const data = await idResolver.did.resolveAtprotoData(alice) expect(data.handle).toBe('alice.external') @@ -225,11 +202,8 @@ describe('handles', () => { 'External handle did not resolve to DID', ) - const profile = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - expect(profile.data.handle).toBe('alice.external') + const dbHandle = await getHandleFromDb(alice) + expect(dbHandle).toBe('alice.external') }) it('allows admin overrules of service domains', async () => { @@ -244,11 +218,8 @@ describe('handles', () => { }, ) - const profile = await agent.api.app.bsky.actor.getProfile( - { actor: bob }, - { headers: sc.getHeaders(bob) }, - ) - expect(profile.data.handle).toBe('bob-alt.test') + const dbHandle = await getHandleFromDb(bob) + expect(dbHandle).toBe('bob-alt.test') }) it('allows admin override of reserved domains', async () => { @@ -263,11 +234,8 @@ describe('handles', () => { }, ) - const profile = await agent.api.app.bsky.actor.getProfile( - { actor: bob }, - { headers: sc.getHeaders(bob) }, - ) - expect(profile.data.handle).toBe('dril.test') + const dbHandle = await getHandleFromDb(bob) + expect(dbHandle).toBe('dril.test') }) it('requires admin auth', async () => { diff --git a/packages/pds/tests/image/server.test.ts b/packages/pds/tests/image/server.test.ts deleted file mode 100644 index 76dc7f57978..00000000000 --- a/packages/pds/tests/image/server.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import * as http from 'http' -import os from 'os' -import path from 'path' -import fs from 'fs' -import { AddressInfo } from 'net' -import axios, { AxiosInstance } from 'axios' -import { getInfo } from '../../src/image/sharp' -import { BlobDiskCache, ImageProcessingServer } from '../../src/image/server' -import { DiskBlobStore } from '../../src' -import { cidForCbor } from '@atproto/common' -import { CID } from 'multiformats/cid' - -describe('image processing server', () => { - let server: ImageProcessingServer - let httpServer: http.Server - let client: AxiosInstance - - let fileCid: CID - - beforeAll(async () => { - const salt = '9dd04221f5755bce5f55f47464c27e1e' - const key = - 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8' - const storage = await DiskBlobStore.create( - path.join(os.tmpdir(), 'img-processing-tests'), - ) - // this CID isn't accurate for the data, but it works for the sake of the test - fileCid = await cidForCbor('key-landscape-small') - await storage.putPermanent( - fileCid, - fs.createReadStream('tests/image/fixtures/key-landscape-small.jpg'), - ) - const cache = new BlobDiskCache() - server = new ImageProcessingServer(salt, key, storage, cache) - httpServer = server.app.listen() - const { port } = httpServer.address() as AddressInfo - client = axios.create({ - baseURL: `http://localhost:${port}`, - validateStatus: () => true, - }) - }) - - afterAll(async () => { - if (httpServer) httpServer.close() - if (server) await server.cache.clearAll() - }) - - it('processes image from storage.', async () => { - const res = await client.get( - server.uriBuilder.getSignedPath({ - cid: fileCid, - format: 'jpeg', - fit: 'cover', - width: 500, - height: 500, - min: true, - }), - { responseType: 'stream' }, - ) - - const info = await getInfo(res.data) - expect(info).toEqual( - expect.objectContaining({ - height: 500, - width: 500, - size: 67221, - }), - ) - expect(res.headers).toEqual( - expect.objectContaining({ - 'content-type': 'image/jpeg', - 'cache-control': 'public, max-age=31536000', - 'content-length': '67221', - }), - ) - }) - - it('caches results.', async () => { - const path = server.uriBuilder.getSignedPath({ - cid: fileCid, - format: 'jpeg', - width: 25, // Special number for this test - height: 25, - }) - const res1 = await client.get(path, { responseType: 'arraybuffer' }) - expect(res1.headers['x-cache']).toEqual('miss') - const res2 = await client.get(path, { responseType: 'arraybuffer' }) - expect(res2.headers['x-cache']).toEqual('hit') - const res3 = await client.get(path, { responseType: 'arraybuffer' }) - expect(res3.headers['x-cache']).toEqual('hit') - expect(Buffer.compare(res1.data, res2.data)).toEqual(0) - expect(Buffer.compare(res1.data, res3.data)).toEqual(0) - }) - - it('errors on bad signature.', async () => { - const path = server.uriBuilder.getSignedPath({ - cid: fileCid, - format: 'jpeg', - fit: 'cover', - width: 500, - height: 500, - min: true, - }) - expect(path).toEqual( - `/G37yf764s6331dxOWiaOYEiLdg8OJxeE-RNxPDKB9Ck/rs:fill:500:500:1:0/plain/${fileCid.toString()}@jpeg`, - ) - const res = await client.get(path.replace('/G', '/bad_'), {}) - expect(res.status).toEqual(400) - expect(res.data).toEqual({ message: 'Invalid path: bad signature' }) - }) - - it('errors on missing file.', async () => { - const missingCid = await cidForCbor('missing-file') - const res = await client.get( - server.uriBuilder.getSignedPath({ - cid: missingCid, - format: 'jpeg', - fit: 'cover', - width: 500, - height: 500, - min: true, - }), - ) - expect(res.status).toEqual(404) - expect(res.data).toEqual({ message: 'Image not found' }) - }) -}) diff --git a/packages/pds/tests/image/sharp.test.ts b/packages/pds/tests/image/sharp.test.ts deleted file mode 100644 index d0a46b662b3..00000000000 --- a/packages/pds/tests/image/sharp.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { createReadStream } from 'fs' -import { Options, getInfo, resize } from '../../src/image/sharp' - -describe('sharp image processor', () => { - it('scales up to cover.', async () => { - const result = await processFixture('key-landscape-small.jpg', { - format: 'jpeg', - fit: 'cover', - width: 500, - height: 500, - min: true, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 500, - width: 500, - }), - ) - }) - - it('scales up to inside (landscape).', async () => { - const result = await processFixture('key-landscape-small.jpg', { - format: 'jpeg', - fit: 'inside', - width: 500, - height: 500, - min: true, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 290, - width: 500, - }), - ) - }) - - it('scales up to inside (portrait).', async () => { - const result = await processFixture('key-portrait-small.jpg', { - format: 'jpeg', - fit: 'inside', - width: 500, - height: 500, - min: true, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 500, - width: 290, - }), - ) - }) - - it('scales up to min.', async () => { - const result = await processFixture('key-landscape-small.jpg', { - format: 'jpeg', - width: 500, - height: 500, - min: { height: 200, width: 200 }, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 200, - width: 345, - }), - ) - }) - - it('does not scale image up when min is false.', async () => { - const result = await processFixture('key-landscape-small.jpg', { - format: 'jpeg', - width: 500, - height: 500, - min: false, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 87, - width: 150, - mime: 'image/jpeg', - }), - ) - }) - - it('scales down to cover.', async () => { - const result = await processFixture('key-landscape-large.jpg', { - format: 'jpeg', - fit: 'cover', - width: 500, - height: 500, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 500, - width: 500, - }), - ) - }) - - it('scales down to inside (landscape).', async () => { - const result = await processFixture('key-landscape-large.jpg', { - format: 'jpeg', - fit: 'inside', - width: 500, - height: 500, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 290, - width: 500, - }), - ) - }) - - it('scales down to inside (portrait).', async () => { - const result = await processFixture('key-portrait-large.jpg', { - format: 'jpeg', - fit: 'inside', - width: 500, - height: 500, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 500, - width: 290, - }), - ) - }) - - it('converts jpeg to png.', async () => { - const result = await processFixture('key-landscape-small.jpg', { - format: 'png', - width: 500, - height: 500, - min: false, - }) - expect(result).toEqual( - expect.objectContaining({ - height: 87, - width: 150, - size: expect.any(Number), - mime: 'image/png', - }), - ) - }) - - it('controls quality (jpeg).', async () => { - const high = await processFixture('key-portrait-small.jpg', { - format: 'jpeg', - width: 500, - height: 500, - quality: 90, - }) - const low = await processFixture('key-portrait-small.jpg', { - format: 'jpeg', - width: 500, - height: 500, - quality: 10, - }) - expect(high.size).toBeGreaterThan(1000) - expect(low.size).toBeLessThan(1000) - }) - - it('controls quality (png).', async () => { - const high = await processFixture('key-portrait-small.jpg', { - format: 'png', - width: 500, - height: 500, - quality: 80, - }) - const low = await processFixture('key-portrait-small.jpg', { - format: 'png', - width: 500, - height: 500, - quality: 10, - }) - expect(high.size).toBeGreaterThan(3000) - expect(low.size).toBeLessThan(3000) - }) - - async function processFixture(fixture: string, options: Options) { - const image = createReadStream(`${__dirname}/fixtures/${fixture}`) - const resized = await resize(image, options) - return await getInfo(resized) - } -}) diff --git a/packages/pds/tests/image/uri.test.ts b/packages/pds/tests/image/uri.test.ts deleted file mode 100644 index ddf5468fe51..00000000000 --- a/packages/pds/tests/image/uri.test.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { cidForCbor } from '@atproto/common' -import { CID } from 'multiformats/cid' -import { ImageUriBuilder, BadPathError } from '../../src/image/uri' - -describe('image uri builder', () => { - let uriBuilder: ImageUriBuilder - let cid: CID - - beforeAll(async () => { - const endpoint = 'https://example.com' - const salt = '9dd04221f5755bce5f55f47464c27e1e' - const key = - 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8' - uriBuilder = new ImageUriBuilder(endpoint, salt, key) - cid = await cidForCbor('test cid') - }) - - it('signs and verifies uri options.', () => { - const path = uriBuilder.getSignedPath({ - cid, - format: 'png', - height: 200, - width: 300, - }) - expect(path).toEqual( - `/8Lpp5Y4ZQFkwTxDDgc1hz8haG6-lUBHsGsyNYoDEaXc/rs:fill:300:200:0:0/plain/${cid.toString()}@png`, - ) - expect(uriBuilder.getVerifiedOptions(path)).toEqual({ - signature: '8Lpp5Y4ZQFkwTxDDgc1hz8haG6-lUBHsGsyNYoDEaXc', - cid, - format: 'png', - fit: 'cover', - height: 200, - width: 300, - min: false, - }) - }) - - it('errors on bad signature.', () => { - const tryGetVerifiedOptions = (path) => () => - uriBuilder.getVerifiedOptions(path) - - tryGetVerifiedOptions( - // Confirm this is a good signed uri - `/BtHM_4IOak5MOc2gOPDxbfS4_HG6VPcry2OAV03L29g/rs:fill:300:200:0:0/plain/${cid.toString()}@png`, - ) - - expect( - tryGetVerifiedOptions( - // Tamper with signature - `/DtHM_4IOak5MOc2gOPDxbfS4_HG6VPcry2OAV03L29g/rs:fill:300:200:0:0/plain/${cid.toString()}@png`, - ), - ).toThrow(new BadPathError('Invalid path: bad signature')) - - expect( - tryGetVerifiedOptions( - // Tamper with params - `/DtHM_4IOak5MOc2gOPDxbfS4_HG6VPcry2OAV03L29g/rs:fill:300:200:0:0/plain/${cid.toString()}@jpeg`, - ), - ).toThrow(new BadPathError('Invalid path: bad signature')) - - expect( - tryGetVerifiedOptions( - // Missing signature - `/rs:fill:300:200:0:0/plain/${cid.toString()}@jpeg`, - ), - ).toThrow(new BadPathError('Invalid path: missing signature')) - }) - - it('supports basic options.', () => { - const path = ImageUriBuilder.getPath({ - cid, - format: 'png', - height: 200, - width: 300, - }) - expect(path).toEqual(`/rs:fill:300:200:0:0/plain/${cid.toString()}@png`) - expect(ImageUriBuilder.getOptions(path)).toEqual({ - cid, - format: 'png', - fit: 'cover', - height: 200, - width: 300, - min: false, - }) - }) - - it('supports fit option.', () => { - const path = ImageUriBuilder.getPath({ - cid, - format: 'png', - fit: 'inside', - height: 200, - width: 300, - }) - expect(path).toEqual(`/rs:fit:300:200:0:0/plain/${cid.toString()}@png`) - expect(ImageUriBuilder.getOptions(path)).toEqual({ - cid, - format: 'png', - fit: 'inside', - height: 200, - width: 300, - min: false, - }) - }) - - it('supports min=true option.', () => { - const path = ImageUriBuilder.getPath({ - cid, - format: 'png', - height: 200, - width: 300, - min: true, - }) - expect(path).toEqual(`/rs:fill:300:200:1:0/plain/${cid.toString()}@png`) - expect(ImageUriBuilder.getOptions(path)).toEqual({ - cid, - format: 'png', - fit: 'cover', - height: 200, - width: 300, - min: true, - }) - }) - - it('supports min={height,width} option.', () => { - const path = ImageUriBuilder.getPath({ - cid, - format: 'jpeg', - height: 200, - width: 300, - min: { height: 50, width: 100 }, - }) - expect(path).toEqual( - `/rs:fill:300:200:0:0/mw:100/mh:50/plain/${cid.toString()}@jpeg`, - ) - expect(ImageUriBuilder.getOptions(path)).toEqual({ - cid, - format: 'jpeg', - fit: 'cover', - height: 200, - width: 300, - min: { height: 50, width: 100 }, - }) - }) - - it('errors on bad cid/format part.', () => { - expect( - tryGetOptions(`/rs:fill:300:200:1:0/plain/${cid.toString()}@mp4`), - ).toThrow(new BadPathError('Invalid path: bad cid/format part')) - expect(tryGetOptions(`/rs:fill:300:200:1:0/plain/@jpg`)).toThrow( - new BadPathError('Invalid path: bad cid/format part'), - ) - expect( - tryGetOptions(`/rs:fill:300:200:1:0/plain/${cid.toString()}@`), - ).toThrow(new BadPathError('Invalid path: bad cid/format part')) - expect( - tryGetOptions(`/rs:fill:300:200:1:0/plain/${cid.toString()}@`), - ).toThrow(new BadPathError('Invalid path: bad cid/format part')) - expect( - tryGetOptions(`/rs:fill:300:200:1:0/plain/${cid.toString()}@x@jpeg`), - ).toThrow(new BadPathError('Invalid path: bad cid/format part')) - }) - - it('errors on mismatching min settings.', () => { - expect( - tryGetOptions( - `/rs:fill:300:200:1:0/mw:100/mh:50/plain/${cid.toString()}@jpeg`, - ), - ).toThrow(new BadPathError('Invalid path: bad min width/height param')) - expect( - tryGetOptions(`/rs:fill:300:200:0:0/mw:100/plain/${cid.toString()}@jpeg`), - ).toThrow(new BadPathError('Invalid path: bad min width/height param')) - }) - - it('errors on bad fit setting.', () => { - expect( - tryGetOptions(`/rs:blah:300:200:1:0/plain/${cid.toString()}@jpeg`), - ).toThrow(new BadPathError('Invalid path: bad resize fit param')) - }) - - it('errors on bad dimension settings.', () => { - expect( - tryGetOptions(`/rs:fill:30x:200:1:0/plain/${cid.toString()}@jpeg`), - ).toThrow(new BadPathError('Invalid path: bad resize height/width param')) - expect( - tryGetOptions(`/rs:fill:300:20x:1:0/plain/${cid.toString()}@jpeg`), - ).toThrow(new BadPathError('Invalid path: bad resize height/width param')) - expect( - tryGetOptions( - `/rs:fill:300:200:1:0/mw:10x/mh:50/plain/${cid.toString()}@jpeg`, - ), - ).toThrow(new BadPathError('Invalid path: bad min width/height param')) - expect( - tryGetOptions( - `/rs:fill:300:200:1:0/mw:100/mh:5x/plain/${cid.toString()}@jpeg`, - ), - ).toThrow(new BadPathError('Invalid path: bad min width/height param')) - }) - - function tryGetOptions(path: string) { - return () => ImageUriBuilder.getOptions(path) - } -}) diff --git a/packages/pds/tests/indexing.test.ts b/packages/pds/tests/indexing.test.ts deleted file mode 100644 index a99053a07c7..00000000000 --- a/packages/pds/tests/indexing.test.ts +++ /dev/null @@ -1,299 +0,0 @@ -import AtpAgent, { - AppBskyActorProfile, - AppBskyFeedPost, - AppBskyFeedLike, - AppBskyFeedRepost, -} from '@atproto/api' -import { AtUri } from '@atproto/syntax' -import { CloseFn, forSnapshot, runTestServer, TestServerInfo } from './_util' -import { SeedClient } from './seeds/client' -import usersSeed from './seeds/users' -import { Database } from '../src' -import { prepareCreate, prepareDelete, prepareUpdate } from '../src/repo' -import { ids } from '../src/lexicon/lexicons' - -describe('indexing', () => { - let server: TestServerInfo - let close: CloseFn - let agent: AtpAgent - let sc: SeedClient - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'indexing', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await usersSeed(sc) - }) - - afterAll(async () => { - await close() - }) - - it('indexes posts.', async () => { - const { db, services } = server.ctx - const createdAt = new Date().toISOString() - const createRecord = await prepareCreate({ - did: sc.dids.alice, - collection: ids.AppBskyFeedPost, - record: { - $type: ids.AppBskyFeedPost, - text: '@bob.test how are you?', - facets: [ - { - index: { byteStart: 0, byteEnd: 9 }, - features: [ - { - $type: `${ids.AppBskyRichtextFacet}#mention`, - did: sc.dids.bob, - }, - ], - }, - ], - createdAt, - } as AppBskyFeedPost.Record, - }) - const { uri } = createRecord - const deleteRecord = prepareDelete({ - did: sc.dids.alice, - collection: ids.AppBskyFeedPost, - rkey: uri.rkey, - }) - - // Create - await services - .repo(db) - .processWrites({ did: sc.dids.alice, writes: [createRecord] }, 1) - await server.processAll() - - const getAfterCreate = await agent.api.app.bsky.feed.getPostThread( - { uri: uri.toString() }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - expect(forSnapshot(getAfterCreate.data)).toMatchSnapshot() - const createNotifications = await getNotifications(db, uri) - - // Delete - await services - .repo(db) - .processWrites({ did: sc.dids.alice, writes: [deleteRecord] }, 1) - await server.processAll() - - const getAfterDelete = agent.api.app.bsky.feed.getPostThread( - { uri: uri.toString() }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - await expect(getAfterDelete).rejects.toThrow(/Post not found:/) - const deleteNotifications = await getNotifications(db, uri) - - expect( - forSnapshot({ - createNotifications, - deleteNotifications, - }), - ).toMatchSnapshot() - }) - - it('indexes profiles.', async () => { - const { db, services } = server.ctx - const createRecord = await prepareCreate({ - did: sc.dids.dan, - collection: ids.AppBskyActorProfile, - rkey: 'self', - record: { - $type: ids.AppBskyActorProfile, - displayName: 'dan', - } as AppBskyActorProfile.Record, - }) - const { uri } = createRecord - const updateRecord = await prepareUpdate({ - did: sc.dids.dan, - collection: ids.AppBskyActorProfile, - rkey: uri.rkey, - record: { - $type: ids.AppBskyActorProfile, - displayName: 'danny', - } as AppBskyActorProfile.Record, - }) - const deleteRecord = prepareDelete({ - did: sc.dids.dan, - collection: ids.AppBskyActorProfile, - rkey: uri.rkey, - }) - - // Create - await services - .repo(db) - .processWrites({ did: sc.dids.dan, writes: [createRecord] }, 1) - await server.processAll() - - const getAfterCreate = await agent.api.app.bsky.actor.getProfile( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - expect(forSnapshot(getAfterCreate.data)).toMatchSnapshot() - const createNotifications = await getNotifications(db, uri) - - // Update - await services - .repo(db) - .processWrites({ did: sc.dids.dan, writes: [updateRecord] }, 1) - await server.processAll() - - const getAfterUpdate = await agent.api.app.bsky.actor.getProfile( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - expect(forSnapshot(getAfterUpdate.data)).toMatchSnapshot() - const updateNotifications = await getNotifications(db, uri) - - // Delete - await services - .repo(db) - .processWrites({ did: sc.dids.dan, writes: [deleteRecord] }, 1) - await server.processAll() - - const getAfterDelete = await agent.api.app.bsky.actor.getProfile( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - expect(forSnapshot(getAfterDelete.data)).toMatchSnapshot() - const deleteNotifications = await getNotifications(db, uri) - - expect( - forSnapshot({ - createNotifications, - updateNotifications, - deleteNotifications, - }), - ).toMatchSnapshot() - }) - - it('does not notify user of own like or repost', async () => { - const { db, services } = server.ctx - const createdAt = new Date().toISOString() - - const originalPost = await prepareCreate({ - did: sc.dids.bob, - collection: ids.AppBskyFeedPost, - record: { - $type: ids.AppBskyFeedPost, - text: 'original post', - createdAt, - } as AppBskyFeedPost.Record, - }) - - const originalPostRef = { - uri: originalPost.uri.toString(), - cid: originalPost.cid.toString(), - } - - // own actions - const ownLike = await prepareCreate({ - did: sc.dids.bob, - collection: ids.AppBskyFeedLike, - record: { - $type: ids.AppBskyFeedLike, - subject: originalPostRef, - createdAt, - } as AppBskyFeedLike.Record, - }) - const ownRepost = await prepareCreate({ - did: sc.dids.bob, - collection: ids.AppBskyFeedRepost, - record: { - $type: ids.AppBskyFeedRepost, - subject: originalPostRef, - createdAt, - } as AppBskyFeedRepost.Record, - }) - - // other actions - const aliceLike = await prepareCreate({ - did: sc.dids.alice, - collection: ids.AppBskyFeedLike, - record: { - $type: ids.AppBskyFeedLike, - subject: originalPostRef, - createdAt, - } as AppBskyFeedLike.Record, - }) - const aliceRepost = await prepareCreate({ - did: sc.dids.alice, - collection: ids.AppBskyFeedRepost, - record: { - $type: ids.AppBskyFeedRepost, - subject: originalPostRef, - createdAt, - } as AppBskyFeedRepost.Record, - }) - - await services.repo(db).processWrites( - { - did: sc.dids.bob, - writes: [originalPost, ownLike, ownRepost], - }, - 1, - ) - await services.repo(db).processWrites( - { - did: sc.dids.alice, - writes: [aliceLike, aliceRepost], - }, - 1, - ) - - await server.processAll() - - const { - data: { notifications }, - } = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - - expect(notifications).toHaveLength(2) - expect( - notifications.every((n) => { - return n.author.did !== sc.dids.bob - }), - ).toBeTruthy() - - // Cleanup - const del = (uri: AtUri) => { - return prepareDelete({ - did: uri.host, - collection: uri.collection, - rkey: uri.rkey, - }) - } - - // Delete - await services.repo(db).processWrites( - { - did: sc.dids.bob, - writes: [del(originalPost.uri), del(ownLike.uri), del(ownRepost.uri)], - }, - 1, - ) - await services.repo(db).processWrites( - { - did: sc.dids.alice, - writes: [del(aliceLike.uri), del(aliceRepost.uri)], - }, - 1, - ) - await server.processAll() - }) - - async function getNotifications(db: Database, uri: AtUri) { - return await db.db - .selectFrom('user_notification') - .selectAll() - .where('recordUri', '=', uri.toString()) - .orderBy('indexedAt') - .execute() - } -}) diff --git a/packages/pds/tests/labeler/apply-labels.test.ts b/packages/pds/tests/labeler/apply-labels.test.ts index 756fd2c13fd..80fedc459d5 100644 --- a/packages/pds/tests/labeler/apply-labels.test.ts +++ b/packages/pds/tests/labeler/apply-labels.test.ts @@ -1,32 +1,25 @@ import AtpAgent from '@atproto/api' -import { - adminAuth, - CloseFn, - moderatorAuth, - runTestServer, - TestServerInfo, -} from '../_util' +import { TestNetworkNoAppView } from '@atproto/dev-env' +import { adminAuth, moderatorAuth } from '../_util' import { SeedClient } from '../seeds/client' import basicSeed from '../seeds/basic' describe('unspecced.applyLabels', () => { - let server: TestServerInfo - let close: CloseFn + let network: TestNetworkNoAppView let agent: AtpAgent let sc: SeedClient beforeAll(async () => { - server = await runTestServer({ + network = await TestNetworkNoAppView.create({ dbPostgresSchema: 'apply_labels', }) - close = server.close - agent = new AtpAgent({ service: server.url }) + agent = network.pds.getClient() sc = new SeedClient(agent) await basicSeed(sc) }) afterAll(async () => { - await close() + await network.close() }) it('requires admin auth.', async () => { @@ -34,7 +27,7 @@ describe('unspecced.applyLabels', () => { { labels: [ { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: sc.dids.carol, val: 'cats', neg: false, @@ -56,7 +49,7 @@ describe('unspecced.applyLabels', () => { { labels: [ { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: post.uriStr, cid: post.cidStr, val: 'birds', @@ -64,7 +57,7 @@ describe('unspecced.applyLabels', () => { cts: new Date().toISOString(), }, { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: post.uriStr, cid: post.cidStr, val: 'bats', @@ -86,7 +79,7 @@ describe('unspecced.applyLabels', () => { { labels: [ { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: post.uriStr, cid: post.cidStr, val: 'birds', @@ -94,7 +87,7 @@ describe('unspecced.applyLabels', () => { cts: new Date().toISOString(), }, { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: post.uriStr, cid: post.cidStr, val: 'bats', @@ -116,14 +109,14 @@ describe('unspecced.applyLabels', () => { { labels: [ { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: sc.dids.carol, val: 'birds', neg: false, cts: new Date().toISOString(), }, { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: sc.dids.carol, val: 'bats', neg: false, @@ -144,14 +137,14 @@ describe('unspecced.applyLabels', () => { { labels: [ { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: sc.dids.carol, val: 'birds', neg: true, cts: new Date().toISOString(), }, { - src: server.ctx.cfg.labelerDid, + src: network.pds.ctx.cfg.labelerDid, uri: sc.dids.carol, val: 'bats', neg: true, diff --git a/packages/pds/tests/migrations/blob-creator.test.ts b/packages/pds/tests/migrations/blob-creator.test.ts deleted file mode 100644 index bc9cc72faf4..00000000000 --- a/packages/pds/tests/migrations/blob-creator.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Database } from '../../src' -import { randomStr } from '@atproto/crypto' -import { cidForCbor, TID } from '@atproto/common' -import { Kysely } from 'kysely' -import { AtUri } from '@atproto/syntax' - -describe.skip('blob creator migration', () => { - let db: Database - let rawDb: Kysely - - beforeAll(async () => { - if (process.env.DB_POSTGRES_URL) { - db = Database.postgres({ - url: process.env.DB_POSTGRES_URL, - schema: 'migration_blob_creator', - }) - } else { - db = Database.memory() - } - await db.migrateToOrThrow('_20230310T205728933Z') - - rawDb = db.db - }) - - afterAll(async () => { - await db.close() - }) - - const dids = ['did:example:alice', 'did:example:bob', 'did:example:carol'] - const getCidStr = async () => { - const cid = await cidForCbor({ test: randomStr(20, 'base32') }) - return cid.toString() - } - - const repoBlob = async (did: string, cid: string) => { - const uri = AtUri.make(did, 'com.atproto.collection', TID.nextStr()) - return { - cid, - recordUri: uri.toString(), - commit: await getCidStr(), - did, - takedownId: null, - } - } - - let blobsSnap - let repoBlobsSnap - - it('creates a some blobs', async () => { - const blobs: any[] = [] - const repoBlobs: any[] = [] - for (let i = 0; i < 1000; i++) { - const cid = await getCidStr() - blobs.push({ - cid, - mimeType: 'image/jpeg', - size: Math.floor(Math.random() * 1000000), - tempKey: null, - width: Math.floor(Math.random() * 1000), - height: Math.floor(Math.random() * 1000), - createdAt: new Date().toISOString(), - }) - if (i % 2 === 0) { - repoBlobs.push(await repoBlob(dids[0], cid)) - } else { - repoBlobs.push(await repoBlob(dids[1], cid)) - } - - if (i % 5 === 0) { - repoBlobs.push(await repoBlob(dids[2], cid)) - } - } - await rawDb.insertInto('blob').values(blobs).execute() - await rawDb.insertInto('repo_blob').values(repoBlobs).execute() - - blobsSnap = await rawDb - .selectFrom('blob') - .selectAll() - .orderBy('cid') - .execute() - repoBlobsSnap = await rawDb - .selectFrom('repo_blob') - .selectAll() - .orderBy('cid') - .orderBy('did') - .execute() - }) - - it('migrates up', async () => { - const migration = await db.migrator.migrateTo('_20230313T232322844Z') - expect(migration.error).toBeUndefined() - }) - - it('correctly migrated data', async () => { - const blobs = await rawDb - .selectFrom('blob') - .selectAll() - .orderBy('cid') - .orderBy('creator') - .execute() - const repoBlobs = await rawDb - .selectFrom('repo_blob') - .selectAll() - .orderBy('cid') - .orderBy('did') - .execute() - - expect(blobs.length).toBe(repoBlobs.length) - expect(repoBlobs.length).toBe(repoBlobsSnap.length) - - for (const blob of blobs) { - const snapped = blobsSnap.find((b) => b.cid === blob.cid) - const { creator, ...rest } = blob - expect(snapped).toEqual(rest) - const found = repoBlobsSnap.find( - (b) => b.cid === blob.cid && b.did === creator, - ) - expect(found).toBeDefined() - } - }) - - it('migrates down', async () => { - const migration = await db.migrator.migrateTo('_20230310T205728933Z') - expect(migration.error).toBeUndefined() - - const updatedBlobs = await rawDb - .selectFrom('blob') - .selectAll() - .orderBy('cid') - .execute() - const updatedRepoBlobs = await rawDb - .selectFrom('repo_blob') - .selectAll() - .orderBy('cid') - .orderBy('did') - .execute() - - expect(updatedBlobs).toEqual(blobsSnap) - expect(updatedRepoBlobs).toEqual(repoBlobsSnap) - }) -}) diff --git a/packages/pds/tests/migrations/indexed-at-on-record.test.ts b/packages/pds/tests/migrations/indexed-at-on-record.test.ts deleted file mode 100644 index 664ae3e16cd..00000000000 --- a/packages/pds/tests/migrations/indexed-at-on-record.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Database } from '../../src' -import { randomStr } from '@atproto/crypto' -import { dataToCborBlock, TID } from '@atproto/common' -import { AtUri } from '@atproto/syntax' -import { Kysely } from 'kysely' - -describe.skip('indexedAt on record migration', () => { - let db: Database - let rawDb: Kysely - - beforeAll(async () => { - if (process.env.DB_POSTGRES_URL) { - db = Database.postgres({ - url: process.env.DB_POSTGRES_URL, - schema: 'migration_indexed_at_on_record', - }) - } else { - db = Database.memory() - } - - await db.migrateToOrThrow('_20221230T215012029Z') - rawDb = db.db - }) - - afterAll(async () => { - await db.close() - }) - - const randomDate = () => { - const start = new Date(2022, 0, 1) - const end = new Date() - return new Date( - start.getTime() + Math.random() * (end.getTime() - start.getTime()), - ).toISOString() - } - - const times: { [cid: string]: string } = {} - - it('fills the db with some records & blocks', async () => { - const blocks: any[] = [] - const records: any[] = [] - for (let i = 0; i < 100; i++) { - const date = randomDate() - const record = { test: randomStr(8, 'base32') } - const block = await dataToCborBlock(record) - blocks.push({ - cid: block.cid.toString(), - content: block.bytes, - size: block.bytes.length, - indexedAt: date, - }) - const uri = AtUri.make('did:example:alice', 'fake.posts', TID.nextStr()) - records.push({ - uri: uri.toString(), - cid: block.cid.toString(), - did: uri.hostname, - collection: uri.collection, - rkey: uri.rkey, - }) - times[block.cid.toString()] = date - } - - await rawDb.insertInto('ipld_block').values(blocks).execute() - await rawDb.insertInto('record').values(records).execute() - }) - - it('migrates up', async () => { - await db.migrateToOrThrow('_20230127T215753149Z') - }) - - it('associated the date to the correct record', async () => { - const res = await rawDb.selectFrom('record').selectAll().execute() - res.forEach((row) => { - expect(row.indexedAt).toEqual(times[row.cid]) - }) - }) -}) diff --git a/packages/pds/tests/migrations/repo-sync-data-pt2.test.ts b/packages/pds/tests/migrations/repo-sync-data-pt2.test.ts deleted file mode 100644 index 91971fb7043..00000000000 --- a/packages/pds/tests/migrations/repo-sync-data-pt2.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import AtpAgent from '@atproto/api' -import { Database } from '../../src' -import { Kysely } from 'kysely' -import { CloseFn, runTestServer } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe.skip('repo sync data migration', () => { - let db: Database - let rawDb: Kysely - let close: CloseFn - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'migration_repo_sync_data_pt_two', - }) - db = server.ctx.db - rawDb = db.db - close = server.close - const agent = new AtpAgent({ service: server.url }) - const sc = new SeedClient(agent) - await basicSeed(sc) - }) - - afterAll(async () => { - await close() - }) - - it('migrates down to pt2', async () => { - await db.migrateToOrThrow('_20230201T200606704Z') - }) - - const getSnapshot = async () => { - const [history, blocks] = await Promise.all([ - rawDb - .selectFrom('repo_commit_history') - .selectAll() - .orderBy('creator') - .orderBy('commit') - .execute(), - rawDb - .selectFrom('repo_commit_block') - .selectAll() - .orderBy('creator') - .orderBy('commit') - .orderBy('block') - .execute(), - ]) - return { history, blocks } - } - - let snapshot: { history: any[]; blocks: any[] } - - it('snapshots current state of commits', async () => { - snapshot = await getSnapshot() - }) - - it('migrates down to pt1', async () => { - await db.migrateToOrThrow('_20230127T224743452Z') - }) - - it('deletes some random commits', async () => { - const toDelete: string[] = [] - for (const commit of snapshot.history) { - if (Math.random() < 0.2) { - toDelete.push(commit.commit) - } - } - await rawDb - .deleteFrom('repo_commit_block') - .where('commit', 'in', toDelete) - .execute() - await rawDb - .deleteFrom('repo_commit_history') - .where('commit', 'in', toDelete) - .execute() - }) - - it('migrates up', async () => { - await db.migrateToOrThrow('_20230201T200606704Z') - }) - - it('backfilled missing commits', async () => { - const newSnapshot = await getSnapshot() - expect(newSnapshot).toEqual(snapshot) - }) -}) diff --git a/packages/pds/tests/migrations/repo-sync-data.test.ts b/packages/pds/tests/migrations/repo-sync-data.test.ts deleted file mode 100644 index 2fd17c199eb..00000000000 --- a/packages/pds/tests/migrations/repo-sync-data.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { Database } from '../../src' -import { MemoryBlockstore, Repo, WriteOpAction } from '@atproto/repo' -import { P256Keypair, Keypair, randomStr } from '@atproto/crypto' -import { TID } from '@atproto/common' -import { Kysely } from 'kysely' -import { CID } from 'multiformats/cid' - -describe.skip('repo sync data migration', () => { - let db: Database - let rawDb: Kysely - let memoryStore: MemoryBlockstore - let keypair: Keypair - let repo: Repo - - const aliceDid = 'did:example:alice' - const bobDid = 'did:example:bob' - - beforeAll(async () => { - if (process.env.DB_POSTGRES_URL) { - db = Database.postgres({ - url: process.env.DB_POSTGRES_URL, - schema: 'migration_repo_sync_data', - }) - } else { - db = Database.memory() - } - await db.migrateToOrThrow('_20230127T215753149Z') - rawDb = db.db - memoryStore = new MemoryBlockstore() - keypair = await P256Keypair.create() - repo = await Repo.create(memoryStore, keypair.did(), keypair) - }) - - afterAll(async () => { - await db.close() - }) - - it('fills the db with some repo data', async () => { - for (let i = 0; i < 100; i++) { - repo = await repo.applyWrites( - { - action: WriteOpAction.Create, - collection: randomStr(8, 'base32'), - rkey: TID.nextStr(), - record: { name: randomStr(32, 'base32') }, - }, - keypair, - ) - } - const blocks: any[] = [] - const creators: any[] = [] - for (const entry of memoryStore.blocks.entries()) { - blocks.push({ - cid: entry.cid.toString(), - size: entry.bytes.length, - content: entry.bytes, - }) - creators.push({ - cid: entry.cid.toString(), - did: aliceDid, - }) - const registerTwice = Math.random() > 0.1 - if (registerTwice) { - creators.push({ - cid: entry.cid.toString(), - did: bobDid, - }) - } - } - const rawDb: Kysely = db.db - await Promise.all([ - rawDb.insertInto('ipld_block').values(blocks).execute(), - rawDb.insertInto('ipld_block_creator').values(creators).execute(), - rawDb - .insertInto('repo_root') - .values([ - { - did: aliceDid, - root: repo.cid.toString(), - indexedAt: new Date().toISOString(), - }, - { - did: bobDid, - root: repo.cid.toString(), - indexedAt: new Date().toISOString(), - }, - ]) - .execute(), - ]) - }) - - it('migrates up', async () => { - const migration = await db.migrator.migrateTo('_20230201T200606704Z') - expect(migration.error).toBeUndefined() - }) - - it('fills in missing block creators', async () => { - const aliceBlocks = await rawDb - .selectFrom('ipld_block_creator') - .selectAll() - .where('did', '=', aliceDid) - .execute() - const bobBlocks = await rawDb - .selectFrom('ipld_block_creator') - .selectAll() - .where('did', '=', bobDid) - .execute() - - const aliceCids = aliceBlocks.map((row) => row.cid).sort() - const bobCids = bobBlocks.map((row) => row.cid).sort() - - expect(aliceCids).toEqual(bobCids) - }) - - it('correctly constructs repo history', async () => { - const checkRepoContents = async (did: string) => { - const history = await rawDb - .selectFrom('repo_commit_history') - .where('creator', '=', did) - .selectAll() - .execute() - const blocks = await rawDb - .selectFrom('repo_commit_block') - .where('creator', '=', did) - .selectAll() - .execute() - const commits = await memoryStore.getCommits(repo.cid, null) - if (!commits) { - throw new Error('Could not get commit log from memoryStore') - } - for (let i = 0; i < commits.length; i++) { - const commit = commits[i] - const prev = commits[i - 1]?.commit?.toString() || null - const filteredHistory = history.filter( - (row) => row.commit === commit.commit.toString(), - ) - expect(filteredHistory.length).toBe(1) - expect(filteredHistory[0].prev).toEqual(prev) - - const filteredBlocks = blocks.filter( - (row) => row.commit === commit.commit.toString(), - ) - expect(filteredBlocks.length).toEqual(commit.blocks.size) - filteredBlocks.forEach((block) => { - expect(commit.blocks.has(CID.parse(block.block))).toBeTruthy() - }) - } - } - - await checkRepoContents(aliceDid) - await checkRepoContents(bobDid) - }) -}) diff --git a/packages/pds/tests/migrations/user-partitioned-cids.test.ts b/packages/pds/tests/migrations/user-partitioned-cids.test.ts deleted file mode 100644 index e6eff220445..00000000000 --- a/packages/pds/tests/migrations/user-partitioned-cids.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Database } from '../../src' -import { randomStr } from '@atproto/crypto' -import { dataToCborBlock } from '@atproto/common' -import { Kysely } from 'kysely' -import { Block } from 'multiformats/block' -import * as uint8arrays from 'uint8arrays' - -describe.skip('user partitioned cids migration', () => { - let db: Database - let rawDb: Kysely - - beforeAll(async () => { - if (process.env.DB_POSTGRES_URL) { - db = Database.postgres({ - url: process.env.DB_POSTGRES_URL, - schema: 'migration_user_partitioned_cids', - }) - } else { - db = Database.memory() - } - await db.migrateToOrThrow('_20230201T200606704Z') - - rawDb = db.db - }) - - afterAll(async () => { - await db.close() - }) - - const dids = ['did:example:one', 'did:example:two', 'did:example:three'] - const blocks: Block[] = [] - - it('fills the db with some cids', async () => { - for (let i = 0; i < 4; i++) { - const block = await dataToCborBlock({ - test: randomStr(32, 'base32'), - }) - - blocks.push(block) - } - - const blocksToInsert = blocks.map((b) => ({ - cid: b.cid.toString(), - size: b.bytes.length, - content: b.bytes, - })) - await rawDb.insertInto('ipld_block').values(blocksToInsert).execute() - - // block 0 is owned by only user 0 - // block 1 is owned by only user 1 - // block 2 is owned by users 0 & 1 - // block 3 is owned by all three users - const creatorsToInsert = [ - { cid: blocks[0].cid.toString(), did: dids[0] }, - { cid: blocks[1].cid.toString(), did: dids[1] }, - { cid: blocks[2].cid.toString(), did: dids[0] }, - { cid: blocks[2].cid.toString(), did: dids[1] }, - { cid: blocks[3].cid.toString(), did: dids[0] }, - { cid: blocks[3].cid.toString(), did: dids[1] }, - { cid: blocks[3].cid.toString(), did: dids[2] }, - ] - await rawDb - .insertInto('ipld_block_creator') - .values(creatorsToInsert) - .execute() - }) - - it('migrates up', async () => { - const migration = await db.migrator.migrateTo('_20230202T170426672Z') - expect(migration.error).toBeUndefined() - }) - - it('correctly partitions user ipld blocks', async () => { - const fromDb = await rawDb.selectFrom('ipld_block').selectAll().execute() - - const first = fromDb.filter((b) => b.cid === blocks[0].cid.toString()) - expect(first.length).toBe(1) - expect(first[0].creator).toEqual(dids[0]) - expect(uint8arrays.equals(first[0].content, blocks[0].bytes)).toBeTruthy() - - const second = fromDb.filter((b) => b.cid === blocks[1].cid.toString()) - expect(second.length).toBe(1) - expect(second[0].creator).toEqual(dids[1]) - expect(uint8arrays.equals(second[0].content, blocks[1].bytes)).toBeTruthy() - - const third = fromDb.filter((b) => b.cid === blocks[2].cid.toString()) - expect(third.length).toBe(2) - const thirdCreators = third.map((row) => row.creator) - expect(thirdCreators.sort()).toEqual(dids.slice(0, 2).sort()) - third.forEach((row) => { - expect(uint8arrays.equals(row.content, blocks[2].bytes)).toBeTruthy() - }) - - const fourth = fromDb.filter((b) => b.cid === blocks[3].cid.toString()) - expect(fourth.length).toBe(3) - const fourthCreators = fourth.map((row) => row.creator) - expect(fourthCreators.sort()).toEqual(dids.sort()) - fourth.forEach((row) => { - expect(uint8arrays.equals(row.content, blocks[3].bytes)).toBeTruthy() - }) - }) -}) diff --git a/packages/pds/tests/migrations/user-table-did-pkey.test.ts b/packages/pds/tests/migrations/user-table-did-pkey.test.ts deleted file mode 100644 index 881907e71b8..00000000000 --- a/packages/pds/tests/migrations/user-table-did-pkey.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Database } from '../../src' -import { randomStr } from '@atproto/crypto' -import { Kysely } from 'kysely' - -describe.skip('user table did pkey migration', () => { - let db: Database - let rawDb: Kysely - - beforeAll(async () => { - if (process.env.DB_POSTGRES_URL) { - db = Database.postgres({ - url: process.env.DB_POSTGRES_URL, - schema: 'migration_user_table_did_pkey', - }) - } else { - db = Database.memory() - } - await db.migrateToOrThrow('_20230202T172831900Z') - - rawDb = db.db - }) - - afterAll(async () => { - await db.close() - }) - - const randDateBefore = (beforeUnix: number): Date => { - return new Date(beforeUnix - Math.floor(1000000 * Math.random())) - } - - let userSnap - let didHandleSnap - - it('creates a bunch of users', async () => { - const didHandles: any[] = [] - const users: any[] = [] - for (let i = 0; i < 1000; i++) { - const did = `did:plc:${randomStr(24, 'base32')}` - const handle = `${randomStr(8, 'base32')}.bsky.social` - const email = `${randomStr(8, 'base32')}@test.com` - const password = randomStr(32, 'base32') - const lastSeenNotifs = randDateBefore(Date.now()) - const createdAt = randDateBefore(lastSeenNotifs.getTime()) - const passwordResetToken = - Math.random() > 0.9 ? randomStr(4, 'base32') : null - const passwordResetGrantedAt = - Math.random() > 0.5 ? randDateBefore(lastSeenNotifs.getTime()) : null - didHandles.push({ did, handle }) - users.push({ - handle, - email, - password, - lastSeenNotifs: lastSeenNotifs.toISOString(), - createdAt: createdAt.toISOString(), - passwordResetToken, - passwordResetGrantedAt: passwordResetGrantedAt?.toISOString() || null, - }) - } - await rawDb.insertInto('did_handle').values(didHandles).execute() - await rawDb.insertInto('user').values(users).execute() - - didHandleSnap = await rawDb - .selectFrom('did_handle') - .selectAll() - .orderBy('did') - .execute() - userSnap = await rawDb - .selectFrom('user') - .selectAll() - .orderBy('email') - .execute() - - // console.log( - // await rawDb.selectFrom('user').select('lastSeenNotifs').execute(), - // ) - }) - - it('migrates up', async () => { - const migration = await db.migrator.migrateTo('_20230208T222001557Z') - expect(migration.error).toBeUndefined() - }) - - it('correctly migrated data', async () => { - const updatedDidHandle = await rawDb - .selectFrom('did_handle') - .selectAll() - .orderBy('did') - .execute() - const updatedUser = await rawDb - .selectFrom('user_account') - .selectAll() - .orderBy('email') - .execute() - const updatedUserState = await rawDb - .selectFrom('user_state') - .selectAll() - .orderBy('did') - .execute() - - expect(updatedDidHandle).toEqual(didHandleSnap) - - expect(updatedUser.length).toBe(userSnap.length) - for (let i = 0; i < updatedUser.length; i++) { - const { handle, password, lastSeenNotifs, ...rest } = userSnap[i] - const expectedDid = didHandleSnap.find((row) => row.handle === handle).did - const expected = { did: expectedDid, passwordScrypt: password, ...rest } - expect(updatedUser[i]).toEqual(expected) - const lastSeen = updatedUserState.find( - (row) => row.did === expectedDid, - )?.lastSeenNotifs - expect(lastSeen).toEqual(lastSeenNotifs) - } - }) - - it('migrates down', async () => { - const migration = await db.migrator.migrateTo('_20230202T172831900Z') - expect(migration.error).toBeUndefined() - - const updatedDidHandle = await rawDb - .selectFrom('did_handle') - .selectAll() - .orderBy('did') - .execute() - const updatedUser = await rawDb - .selectFrom('user') - .selectAll() - .orderBy('email') - .execute() - - expect(updatedDidHandle).toEqual(didHandleSnap) - expect(updatedUser).toEqual(userSnap) - }) -}) diff --git a/packages/pds/tests/moderation.test.ts b/packages/pds/tests/moderation.test.ts index 0861d852aca..34e52a156a0 100644 --- a/packages/pds/tests/moderation.test.ts +++ b/packages/pds/tests/moderation.test.ts @@ -1130,18 +1130,11 @@ describe('moderation', () => { describe('blob takedown', () => { let post: { ref: RecordRef; images: ImageRef[] } let blob: ImageRef - let imageUri: string let actionId: number + beforeAll(async () => { post = sc.posts[sc.dids.carol][0] blob = post.images[1] - imageUri = server.ctx.imgUriBuilder - .getCommonSignedUri('feed_thumbnail', blob.image.ref.toString()) - .replace(server.ctx.cfg.publicUrl, server.url) - // Warm image server cache - await fetch(imageUri) - const cached = await fetch(imageUri) - expect(cached.headers.get('x-cache')).toEqual('hit') const takeAction = await agent.api.com.atproto.admin.takeModerationAction( { action: TAKEDOWN, @@ -1178,12 +1171,6 @@ describe('moderation', () => { await expect(referenceBlob).rejects.toThrow('Could not find blob:') }) - it('prevents image blob from being served, even when cached.', async () => { - const fetchImage = await fetch(imageUri) - expect(fetchImage.status).toEqual(404) - expect(await fetchImage.json()).toEqual({ message: 'Image not found' }) - }) - it('restores blob when action is reversed.', async () => { await agent.api.com.atproto.admin.reverseModerationAction( { @@ -1200,12 +1187,6 @@ describe('moderation', () => { // Can post and reference blob const post = await sc.post(sc.dids.alice, 'pic', [], [blob]) expect(post.images[0].image.ref.equals(blob.image.ref)).toBeTruthy() - - // Can fetch through image server - const fetchImage = await fetch(imageUri) - expect(fetchImage.status).toEqual(200) - const size = Number(fetchImage.headers.get('content-length')) - expect(size).toBeGreaterThan(9000) }) }) }) diff --git a/packages/pds/tests/proxied/__snapshots__/timeline-skeleton.test.ts.snap b/packages/pds/tests/proxied/__snapshots__/timeline-skeleton.test.ts.snap deleted file mode 100644 index 1bb947bb64c..00000000000 --- a/packages/pds/tests/proxied/__snapshots__/timeline-skeleton.test.ts.snap +++ /dev/null @@ -1,2798 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`proxies timeline skeleton feed skeleton construction 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "feed": Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(7)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(3)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(12)", - "muted": false, - }, - }, - "cid": "cids(8)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(13)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(10)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(11)", - "uri": "record(14)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(11)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(9)", - "uri": "record(13)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(10)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(10)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(15)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(9)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(11)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(14)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(10)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(11)", - "uri": "record(14)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object { - "like": "record(16)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(13)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(17)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(17)", - "viewer": Object {}, - }, - }, - ], -} -`; - -exports[`proxies timeline skeleton timeline skeleton construction 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "feed": Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(8)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(11)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(8)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(14)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(6)", - "uri": "record(8)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(15)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(8)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(16)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(9)", - "viewer": Object { - "like": "record(17)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(12)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(14)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(18)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(18)", - "viewer": Object {}, - }, - }, - ], -} -`; diff --git a/packages/pds/tests/proxied/timeline-skeleton.test.ts b/packages/pds/tests/proxied/timeline-skeleton.test.ts deleted file mode 100644 index d7617a74a16..00000000000 --- a/packages/pds/tests/proxied/timeline-skeleton.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import AtpAgent, { AtUri } from '@atproto/api' -import { TestNetwork } from '@atproto/dev-env' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { forSnapshot } from '../_util' -import * as bsky from '@atproto/bsky' -import { makeAlgos } from '../../src' - -describe('proxies timeline skeleton', () => { - let network: TestNetwork - let agent: AtpAgent - let sc: SeedClient - - let alice: string - - const feedGenDid = 'did:example:feed-gen' - const feedPublisherDid = 'did:example:feed-publisher' - - beforeAll(async () => { - network = await TestNetwork.create({ - dbPostgresSchema: 'proxy_timeline_skeleton', - pds: { - feedGenDid, - algos: makeAlgos(feedPublisherDid), - enableInProcessAppView: true, - bskyAppViewProxy: false, - }, - bsky: { - feedGenDid, - algos: bsky.makeAlgos(feedPublisherDid), - }, - }) - agent = network.pds.getClient() - sc = new SeedClient(agent) - await basicSeed(sc) - await network.processAll() - alice = sc.dids.alice - }) - - afterAll(async () => { - await network.close() - }) - - it('timeline skeleton construction', async () => { - const res = await agent.api.app.bsky.feed.getTimeline( - {}, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - - expect(forSnapshot(res.data)).toMatchSnapshot() - const pt1 = await agent.api.app.bsky.feed.getTimeline( - { - limit: 2, - }, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - const pt2 = await agent.api.app.bsky.feed.getTimeline( - { - cursor: pt1.data.cursor, - }, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - expect([...pt1.data.feed, ...pt2.data.feed]).toEqual(res.data.feed) - }) - - it('feed skeleton construction', async () => { - const uri = AtUri.make( - feedPublisherDid, - 'app.bsky.feed.generator', - 'mutuals', - ) - const res = await agent.api.app.bsky.feed.getFeed( - { feed: uri.toString() }, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - expect(forSnapshot(res.data)).toMatchSnapshot() - const pt1 = await agent.api.app.bsky.feed.getFeed( - { feed: uri.toString(), limit: 2 }, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - const pt2 = await agent.api.app.bsky.feed.getFeed( - { feed: uri.toString(), cursor: pt1.data.cursor }, - { - headers: { ...sc.getHeaders(alice), 'x-appview-proxy': 'true' }, - }, - ) - expect([...pt1.data.feed, ...pt2.data.feed]).toEqual(res.data.feed) - }) -}) diff --git a/packages/pds/tests/server.test.ts b/packages/pds/tests/server.test.ts index ae9f34fed26..3994df3a9ab 100644 --- a/packages/pds/tests/server.test.ts +++ b/packages/pds/tests/server.test.ts @@ -1,12 +1,13 @@ import { AddressInfo } from 'net' import express from 'express' import axios, { AxiosError } from 'axios' -import AtpAgent from '@atproto/api' +import AtpAgent, { AtUri } from '@atproto/api' import { CloseFn, runTestServer, TestServerInfo } from './_util' import { handler as errorHandler } from '../src/error' import { SeedClient } from './seeds/client' import basicSeed from './seeds/basic' import { Database } from '../src' +import { randomStr } from '@atproto/crypto' describe('server', () => { let server: TestServerInfo @@ -86,8 +87,26 @@ describe('server', () => { }) it('compresses large json responses', async () => { + // first create a large record + const record = { + text: 'blahblabh', + createdAt: new Date().toISOString(), + } + for (let i = 0; i < 100; i++) { + record[randomStr(8, 'base32')] = randomStr(32, 'base32') + } + const createRes = await agent.com.atproto.repo.createRecord( + { + repo: alice, + collection: 'app.bsky.feed.post', + record, + }, + { headers: sc.getHeaders(alice), encoding: 'application/json' }, + ) + const uri = new AtUri(createRes.data.uri) + const res = await axios.get( - `${server.url}/xrpc/app.bsky.feed.getTimeline`, + `${server.url}/xrpc/com.atproto.repo.getRecord?repo=${uri.host}&collection=${uri.collection}&rkey=${uri.rkey}`, { decompress: false, headers: { ...sc.getHeaders(alice), 'accept-encoding': 'gzip' }, @@ -120,7 +139,7 @@ describe('server', () => { it('healthcheck fails when database is unavailable.', async () => { // destroy to release lock & allow db to close - await server.ctx.sequencerLeader.destroy() + await server.ctx.sequencerLeader?.destroy() await db.close() let error: AxiosError diff --git a/packages/pds/tests/views/__snapshots__/author-feed.test.ts.snap b/packages/pds/tests/views/__snapshots__/author-feed.test.ts.snap deleted file mode 100644 index ca56abeb646..00000000000 --- a/packages/pds/tests/views/__snapshots__/author-feed.test.ts.snap +++ /dev/null @@ -1,2495 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds author feed views fetches full author feeds for self (sorted, minimal viewer state). 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(2)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(9)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(10)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(9)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(10)", - "uri": "record(13)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(8)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(8)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(14)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`pds author feed views fetches full author feeds for self (sorted, minimal viewer state). 2`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(0)", - "val": "test-label", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(0)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(3)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object { - "like": "record(6)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object { - "like": "record(6)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(5)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(8)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`pds author feed views fetches full author feeds for self (sorted, minimal viewer state). 3`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(1)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(1)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(1)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "repost": "record(5)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(7)", - "uri": "record(7)", - }, - "root": Object { - "cid": "cids(7)", - "uri": "record(7)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(6)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(10)", - "val": "self-label-a", - }, - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(10)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(7)", - "viewer": Object { - "like": "record(11)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(10)", - "val": "self-label-a", - }, - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(10)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(7)", - "viewer": Object { - "like": "record(11)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(1)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(4)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(1)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`pds author feed views fetches full author feeds for self (sorted, minimal viewer state). 4`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "repost": "record(5)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(11)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(11)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`pds author feed views omits reposts from muted users. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": true, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(1)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(4)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(4)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(2)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": true, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(6)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`pds author feed views reflects fetching user's state in the feed. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(8)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(8)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(4)", - "viewer": Object { - "like": "record(6)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(2)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(11)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(9)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(10)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(10)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(11)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(10)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(9)", - "viewer": Object { - "like": "record(13)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(4)", - "viewer": Object { - "like": "record(6)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(14)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, -] -`; diff --git a/packages/pds/tests/views/__snapshots__/blocks.test.ts.snap b/packages/pds/tests/views/__snapshots__/blocks.test.ts.snap deleted file mode 100644 index 9b168ae33a5..00000000000 --- a/packages/pds/tests/views/__snapshots__/blocks.test.ts.snap +++ /dev/null @@ -1,383 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds views with blocking blocks record embeds 1`] = ` -Object { - "thread": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewBlocked", - "author": Object { - "did": "user(2)", - "viewer": Object { - "blockedBy": false, - "blocking": "record(5)", - }, - }, - "blocked": true, - "uri": "record(4)", - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(3)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(0)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - }, -} -`; - -exports[`pds views with blocking blocks thread parent 1`] = ` -Object { - "thread": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#blockedPost", - "author": Object { - "did": "user(1)", - "viewer": Object { - "blockedBy": true, - }, - }, - "blocked": true, - "uri": "record(4)", - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "alice replies to dan", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "replies": Array [], - }, -} -`; - -exports[`pds views with blocking blocks thread reply 1`] = ` -Object { - "thread": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - "repost": "record(3)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#blockedPost", - "author": Object { - "did": "user(1)", - "viewer": Object { - "blockedBy": false, - "blocking": "record(6)", - }, - }, - "blocked": true, - "uri": "record(5)", - }, - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(2)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label", - }, - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(4)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - }, - ], - }, -} -`; diff --git a/packages/pds/tests/views/__snapshots__/follows.test.ts.snap b/packages/pds/tests/views/__snapshots__/follows.test.ts.snap deleted file mode 100644 index fbcd95eb3a4..00000000000 --- a/packages/pds/tests/views/__snapshots__/follows.test.ts.snap +++ /dev/null @@ -1,703 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds follow views blocks followers by actor takedown 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(2)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(3)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(0)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, -} -`; - -exports[`pds follow views blocks follows by actor takedown 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(2)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(3)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(0)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches followers 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(2)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(3)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(4)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "following": "record(6)", - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(0)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches followers 2`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(1)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(2)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(0)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches followers 3`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(2)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(3)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(0)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches followers 4`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(1)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(0)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches followers 5`] = ` -Object { - "cursor": "0000000000000::bafycid", - "followers": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(1)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(2)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(0)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches follows 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(2)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(3)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(4)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "following": "record(6)", - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(0)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches follows 2`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(1)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(2)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(0)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches follows 3`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(1)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(0)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches follows 4`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(1)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-bob", - "did": "user(2)", - "displayName": "display-bob", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(3)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-dan", - "did": "user(0)", - "displayName": "display-dan", - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; - -exports[`pds follow views fetches follows 5`] = ` -Object { - "cursor": "0000000000000::bafycid", - "follows": Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-carol", - "did": "user(1)", - "displayName": "display-carol", - "handle": "carol.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-alice", - "did": "user(2)", - "displayName": "display-alice", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - ], - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "descript-eve", - "did": "user(0)", - "displayName": "display-eve", - "handle": "eve.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, -} -`; diff --git a/packages/pds/tests/views/__snapshots__/likes.test.ts.snap b/packages/pds/tests/views/__snapshots__/likes.test.ts.snap deleted file mode 100644 index 3a15355409f..00000000000 --- a/packages/pds/tests/views/__snapshots__/likes.test.ts.snap +++ /dev/null @@ -1,120 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds like views fetches post likes 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "likes": Array [ - Object { - "actor": Object { - "did": "user(0)", - "handle": "eve.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "createdAt": "1970-01-01T00:00:00.000Z", - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - Object { - "actor": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(1)", - "muted": false, - }, - }, - "createdAt": "1970-01-01T00:00:00.000Z", - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - Object { - "actor": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "following": "record(2)", - "muted": false, - }, - }, - "createdAt": "1970-01-01T00:00:00.000Z", - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - Object { - "actor": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "createdAt": "1970-01-01T00:00:00.000Z", - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - ], - "uri": "record(0)", -} -`; - -exports[`pds like views fetches reply likes 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "likes": Array [ - Object { - "actor": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "createdAt": "1970-01-01T00:00:00.000Z", - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - ], - "uri": "record(0)", -} -`; diff --git a/packages/pds/tests/views/__snapshots__/mute-lists.test.ts.snap b/packages/pds/tests/views/__snapshots__/mute-lists.test.ts.snap deleted file mode 100644 index 6434e1e51b1..00000000000 --- a/packages/pds/tests/views/__snapshots__/mute-lists.test.ts.snap +++ /dev/null @@ -1,599 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds views with mutes from mute lists embeds lists in posts 1`] = ` -Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.graph.defs#listView", - "cid": "cids(3)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "description": "new descript", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "updated alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(2)", - "viewer": Object { - "muted": false, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "list embed!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, -} -`; - -exports[`pds views with mutes from mute lists flags mutes in threads 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - "repost": "record(3)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": true, - "mutedByList": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(6)", - "viewer": Object { - "muted": true, - }, - }, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - }, - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(10)", - "muted": true, - "mutedByList": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(6)", - "viewer": Object { - "muted": true, - }, - }, - }, - }, - "cid": "cids(4)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(6)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(9)", - "viewer": Object {}, - }, - }, - ], -} -`; - -exports[`pds views with mutes from mute lists returns a users own list mutes 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "lists": Array [ - Object { - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "description": "blah blah", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "new list", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(0)", - "viewer": Object { - "muted": true, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(2)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "description": "big list of mutes", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(3)", - "viewer": Object { - "muted": true, - }, - }, - ], -} -`; - -exports[`pds views with mutes from mute lists returns lists associated with a user 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "lists": Array [ - Object { - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "description": "blah blah", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "new list", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(0)", - "viewer": Object { - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(2)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "description": "big list of mutes", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(3)", - "viewer": Object { - "muted": true, - }, - }, - ], -} -`; - -exports[`pds views with mutes from mute lists returns the contents of a list 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "items": Array [ - Object { - "subject": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": true, - "mutedByList": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(0)", - "viewer": Object { - "muted": true, - }, - }, - }, - }, - }, - Object { - "subject": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(2)", - "muted": true, - "mutedByList": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(0)", - "viewer": Object { - "muted": true, - }, - }, - }, - }, - }, - ], - "list": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "cid": "cids(0)", - "creator": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(2)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "muted": false, - }, - }, - "description": "big list of mutes", - "indexedAt": "1970-01-01T00:00:00.000Z", - "name": "alice mutes", - "purpose": "app.bsky.graph.defs#modlist", - "uri": "record(0)", - "viewer": Object { - "muted": true, - }, - }, -} -`; diff --git a/packages/pds/tests/views/__snapshots__/mutes.test.ts.snap b/packages/pds/tests/views/__snapshots__/mutes.test.ts.snap deleted file mode 100644 index 8929a3c347b..00000000000 --- a/packages/pds/tests/views/__snapshots__/mutes.test.ts.snap +++ /dev/null @@ -1,75 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`mute views fetches mutes for the logged-in user. 1`] = ` -Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "Dr. Lowell DuBuque", - "handle": "elta48.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "Sally Funk", - "handle": "magnus53.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, - Object { - "did": "user(2)", - "handle": "nicolas-krajcik10.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "Patrick Sawayn", - "handle": "jeffrey-sawayn87.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(4)", - "displayName": "Kim Streich", - "handle": "adrienne49.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(5)", - "displayName": "Carlton Abernathy IV", - "handle": "aliya-hodkiewicz.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": true, - }, - }, -] -`; diff --git a/packages/pds/tests/views/__snapshots__/notifications.test.ts.snap b/packages/pds/tests/views/__snapshots__/notifications.test.ts.snap deleted file mode 100644 index 117bcdfbb79..00000000000 --- a/packages/pds/tests/views/__snapshots__/notifications.test.ts.snap +++ /dev/null @@ -1,1922 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds notification views fetches notifications omitting mentions and replies for taken-down posts 1`] = ` -Array [ - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "reply", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "indeed", - }, - "uri": "record(0)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "uri": "record(5)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(7)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-a", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(10)", - "following": "record(9)", - "muted": false, - }, - }, - "cid": "cids(5)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(8)", - "val": "test-label", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(8)", - "val": "test-label-2", - }, - ], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(7)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "uri": "record(8)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(12)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(14)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(10)", - "uri": "record(14)", - }, - }, - "uri": "record(13)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(15)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-a", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(10)", - "following": "record(9)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(14)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(10)", - "uri": "record(14)", - }, - }, - "uri": "record(16)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-a", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(10)", - "following": "record(9)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(17)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-a", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(11)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(10)", - "following": "record(9)", - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(10)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(15)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(2)", - }, -] -`; - -exports[`pds notification views fetches notifications omitting records by a muted user 1`] = ` -Array [ - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(0)", - "val": "test-label", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(0)", - "val": "test-label-2", - }, - ], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "uri": "record(0)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(6)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(5)", - "uri": "record(6)", - }, - }, - "uri": "record(5)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - }, - "uri": "record(7)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(0)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(1)", - }, - "uri": "record(2)", - }, -] -`; - -exports[`pds notification views fetches notifications with a last-seen 1`] = ` -Array [ - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "reply", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "indeed", - }, - "uri": "record(0)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "uri": "record(5)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(7)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(5)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "of course", - }, - "uri": "record(8)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label-2", - }, - ], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "uri": "record(9)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(13)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(15)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(11)", - "uri": "record(15)", - }, - }, - "uri": "record(14)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(16)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(15)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(11)", - "uri": "record(15)", - }, - }, - "uri": "record(17)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(18)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(15)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "mention", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(16)", - "uri": "record(20)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(3)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "uri": "record(19)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(17)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(11)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(18)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": true, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(2)", - }, -] -`; - -exports[`pds notification views fetches notifications without a last-seen 1`] = ` -Array [ - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "reply", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "indeed", - }, - "uri": "record(0)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(3)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "uri": "record(5)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(7)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(5)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "of course", - }, - "uri": "record(8)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label", - }, - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "test-label-2", - }, - ], - "reason": "reply", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "uri": "record(9)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(13)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(15)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(11)", - "uri": "record(15)", - }, - }, - "uri": "record(14)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(16)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(15)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(11)", - "uri": "record(15)", - }, - }, - "uri": "record(17)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "like", - "reasonSubject": "record(4)", - "record": Object { - "$type": "app.bsky.feed.like", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(4)", - }, - }, - "uri": "record(18)", - }, - Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(15)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "mention", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(16)", - "uri": "record(20)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(3)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "uri": "record(19)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(12)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(17)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(11)", - }, - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(18)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(3)", - }, - "uri": "record(2)", - }, -] -`; - -exports[`pds notification views generates notifications for quotes 1`] = ` -Object { - "cursor": "0000000000000::bafycid", - "notifications": Array [ - Object { - "author": Object { - "did": "user(0)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "repost", - "reasonSubject": "record(1)", - "record": Object { - "$type": "app.bsky.feed.repost", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": Object { - "cid": "cids(1)", - "uri": "record(1)", - }, - }, - "uri": "record(0)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [ - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "test-label", - }, - ], - "reason": "quote", - "reasonSubject": "record(1)", - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(1)", - }, - }, - "text": "yoohoo label_me", - }, - "uri": "record(2)", - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "isRead": false, - "labels": Array [], - "reason": "follow", - "record": Object { - "$type": "app.bsky.graph.follow", - "createdAt": "1970-01-01T00:00:00.000Z", - "subject": "user(2)", - }, - "uri": "record(3)", - }, - ], -} -`; diff --git a/packages/pds/tests/views/__snapshots__/posts.test.ts.snap b/packages/pds/tests/views/__snapshots__/posts.test.ts.snap deleted file mode 100644 index 75ff566186e..00000000000 --- a/packages/pds/tests/views/__snapshots__/posts.test.ts.snap +++ /dev/null @@ -1,526 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds posts views fetches posts 1`] = ` -Array [ - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(0)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(5)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(3)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(6)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(7)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object { - "like": "record(10)", - }, - }, - Object { - "author": Object { - "did": "user(3)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(3)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(12)", - "muted": false, - }, - }, - "cid": "cids(8)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(9)", - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(5)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(3)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(3)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(7)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(6)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(7)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(5)", - "uri": "record(7)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(10)", - "uri": "record(14)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(13)", - "viewer": Object {}, - }, -] -`; diff --git a/packages/pds/tests/views/__snapshots__/profile.test.ts.snap b/packages/pds/tests/views/__snapshots__/profile.test.ts.snap deleted file mode 100644 index dbfd30bdbce..00000000000 --- a/packages/pds/tests/views/__snapshots__/profile.test.ts.snap +++ /dev/null @@ -1,286 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds profile views creates new profile 1`] = ` -Object { - "did": "user(0)", - "displayName": "danny boy", - "followersCount": 1, - "followsCount": 1, - "handle": "dan.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "postsCount": 2, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`pds profile views fetches multiple profiles 1`] = ` -Array [ - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(1)", - "displayName": "bobby", - "followersCount": 2, - "followsCount": 2, - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "postsCount": 3, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - Object { - "did": "user(2)", - "followersCount": 2, - "followsCount": 1, - "handle": "carol.test", - "labels": Array [], - "postsCount": 2, - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - Object { - "did": "user(3)", - "followersCount": 1, - "followsCount": 1, - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(3)", - "val": "repo-action-label", - }, - ], - "postsCount": 2, - "viewer": Object { - "blockedBy": false, - "followedBy": "record(5)", - "muted": false, - }, - }, -] -`; - -exports[`pds profile views fetches other's profile, with a follow 1`] = ` -Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "following": "record(0)", - "muted": false, - }, -} -`; - -exports[`pds profile views fetches other's profile, without a follow 1`] = ` -Object { - "did": "user(0)", - "followersCount": 1, - "followsCount": 1, - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "postsCount": 2, - "viewer": Object { - "blockedBy": false, - "followedBy": "record(0)", - "muted": false, - }, -} -`; - -exports[`pds profile views fetches own profile 1`] = ` -Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "its me!", - "did": "user(0)", - "displayName": "ali", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(0)", - "val": "self-label-a", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(0)", - "val": "self-label-b", - }, - ], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`pds profile views handles avatars & banners 1`] = ` -Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "banner": "https://pds.public.url/image/ejOTK5gy9tlarOXM6MhrPOs0C18LFpfd9qQ9lBrcIBE/rs:fill:3000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "description": "new descript", - "did": "user(0)", - "displayName": "ali", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`pds profile views handles unsetting profile fields 1`] = ` -Object { - "did": "user(0)", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; - -exports[`pds profile views updates profile 1`] = ` -Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "new descript", - "did": "user(0)", - "displayName": "ali", - "followersCount": 2, - "followsCount": 3, - "handle": "alice.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "postsCount": 4, - "viewer": Object { - "blockedBy": false, - "muted": false, - }, -} -`; diff --git a/packages/pds/tests/views/__snapshots__/reposts.test.ts.snap b/packages/pds/tests/views/__snapshots__/reposts.test.ts.snap deleted file mode 100644 index 69927a4b5ae..00000000000 --- a/packages/pds/tests/views/__snapshots__/reposts.test.ts.snap +++ /dev/null @@ -1,108 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds repost views fetches reposted-by for a post 1`] = ` -Array [ - Object { - "did": "user(0)", - "handle": "eve.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(0)", - "muted": false, - }, - }, - Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "description": "hi im bob label_me", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(0)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(4)", - "following": "record(3)", - "muted": false, - }, - }, -] -`; - -exports[`pds repost views fetches reposted-by for a reply 1`] = ` -Array [ - Object { - "did": "user(0)", - "handle": "eve.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(0)", - "muted": false, - }, - }, -] -`; diff --git a/packages/pds/tests/views/__snapshots__/thread.test.ts.snap b/packages/pds/tests/views/__snapshots__/thread.test.ts.snap deleted file mode 100644 index df37cbb712d..00000000000 --- a/packages/pds/tests/views/__snapshots__/thread.test.ts.snap +++ /dev/null @@ -1,1883 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`pds thread views blocks ancestors by actor takedown 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#notFoundPost", - "notFound": true, - "uri": "record(5)", - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(0)", - "viewer": Object { - "repost": "record(6)", - }, - }, - "replies": Array [], -} -`; - -exports[`pds thread views blocks ancestors by record takedown 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#notFoundPost", - "notFound": true, - "uri": "record(5)", - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(0)", - "viewer": Object { - "repost": "record(6)", - }, - }, - "replies": Array [], -} -`; - -exports[`pds thread views blocks replies by actor takedown 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(4)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(5)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(7)", - "viewer": Object { - "repost": "record(8)", - }, - }, - "replies": Array [], - }, - ], - }, - ], -} -`; - -exports[`pds thread views blocks replies by record takedown 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(6)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - Object { - "cid": "cids(2)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(4)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [], - }, - ], -} -`; - -exports[`pds thread views fetches ancestors 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(4)", - "viewer": Object { - "like": "record(8)", - }, - }, - "replies": Array [], - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [], - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(0)", - "viewer": Object { - "repost": "record(6)", - }, - }, - "replies": Array [], -} -`; - -exports[`pds thread views fetches deep post thread 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [], - }, - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(7)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(9)", - "viewer": Object { - "repost": "record(10)", - }, - }, - "replies": Array [], - }, - ], - }, - ], -} -`; - -exports[`pds thread views fetches shallow ancestors 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [], - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(0)", - "viewer": Object { - "repost": "record(6)", - }, - }, - "replies": Array [], -} -`; - -exports[`pds thread views fetches shallow post thread 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - }, - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - }, - ], -} -`; - -exports[`pds thread views handles deleted posts correctly 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "Deletion thread", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "Reply", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "Reply reply", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(6)", - "viewer": Object {}, - }, - "replies": Array [], - }, - ], - }, - ], -} -`; - -exports[`pds thread views handles deleted posts correctly 2`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "Deletion thread", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "replies": Array [], -} -`; - -exports[`pds thread views handles deleted posts correctly 3`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "parent": Object { - "$type": "app.bsky.feed.defs#notFoundPost", - "notFound": true, - "uri": "record(5)", - }, - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(5)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(4)", - }, - }, - "text": "Reply reply", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(0)", - "viewer": Object {}, - }, - "replies": Array [], -} -`; - -exports[`pds thread views includes the muted status of post authors. 1`] = ` -Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": true, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "like": "record(4)", - }, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "replies": Array [], - }, - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(8)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(7)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(7)", - "viewer": Object {}, - }, - "replies": Array [ - Object { - "$type": "app.bsky.feed.defs#threadViewPost", - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(3)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(2)", - "following": "record(1)", - "muted": true, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(7)", - }, - "root": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 2, - "uri": "record(9)", - "viewer": Object { - "repost": "record(10)", - }, - }, - "replies": Array [], - }, - ], - }, - ], -} -`; diff --git a/packages/pds/tests/views/__snapshots__/timeline.test.ts.snap b/packages/pds/tests/views/__snapshots__/timeline.test.ts.snap deleted file mode 100644 index 73f5e4f6748..00000000000 --- a/packages/pds/tests/views/__snapshots__/timeline.test.ts.snap +++ /dev/null @@ -1,7343 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`timeline views blocks posts, reposts, replies by actor takedown 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(4)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(5)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewNotFound", - "notFound": true, - "uri": "record(7)", - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(6)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(6)", - "uri": "record(7)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(5)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(5)", - "uri": "record(6)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(5)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewNotFound", - "notFound": true, - "uri": "record(7)", - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(6)", - "uri": "record(7)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(6)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(8)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(9)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(9)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views blocks posts, reposts, replies by record takedown. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(5)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(5)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewNotFound", - "notFound": true, - "uri": "record(9)", - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(8)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(6)", - "uri": "record(9)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(8)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-a", - }, - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(10)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(7)", - "following": "record(6)", - "muted": false, - }, - }, - "cid": "cids(10)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-a", - }, - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": false, - }, - }, - "cid": "cids(13)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(13)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(16)", - "val": "kind", - }, - ], - "uri": "record(16)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(10)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(15)", - "val": "kind", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(11)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(12)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(13)", - "uri": "record(16)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(15)", - "viewer": Object { - "like": "record(17)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-a", - }, - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(13)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(13)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(16)", - "val": "kind", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(16)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(14)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(18)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(18)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views fetches authenticated user's home feed w/ reverse-chronological algorithm 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(12)", - "val": "kind", - }, - ], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "kind", - }, - ], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(8)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(11)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "kind", - }, - ], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(8)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(14)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(6)", - "uri": "record(8)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(15)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(12)", - "val": "kind", - }, - ], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "kind", - }, - ], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(8)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(16)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(11)", - "following": "record(10)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(12)", - "val": "kind", - }, - ], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(9)", - "val": "kind", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(8)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(9)", - "uri": "record(12)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(9)", - "viewer": Object { - "like": "record(17)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": false, - }, - }, - "cid": "cids(9)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(12)", - "val": "kind", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(12)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(14)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(14)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(18)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(18)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views fetches authenticated user's home feed w/ reverse-chronological algorithm 2`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(1)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "kind", - }, - ], - "uri": "record(4)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "kind", - }, - ], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(4)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(2)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(9)", - "uri": "record(11)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(6)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(9)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label", - }, - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(11)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(9)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label", - }, - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(11)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(11)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(1)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "kind", - }, - ], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(4)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(0)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(2)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(14)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object { - "like": "record(15)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(16)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "following": "record(3)", - "muted": false, - }, - }, - "cid": "cids(1)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(4)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "kind", - }, - ], - "uri": "record(4)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "kind", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(4)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(2)", - "viewer": Object { - "like": "record(17)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(5)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "kind", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(13)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(13)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(18)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(18)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views fetches authenticated user's home feed w/ reverse-chronological algorithm 3`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(1)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(4)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "kind", - }, - ], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(1)", - "val": "kind", - }, - ], - "uri": "record(1)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(1)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "repost": "record(5)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(9)", - "uri": "record(11)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(6)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(9)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label", - }, - Object { - "cid": "cids(9)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(11)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(11)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - "root": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "text": "of course", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(11)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(0)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(0)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(1)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(1)", - "val": "kind", - }, - ], - "uri": "record(1)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(0)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(1)", - "uri": "record(1)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(1)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(11)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(14)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(0)", - "uri": "record(0)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object { - "like": "record(15)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(10)", - "viewer": Object { - "like": "record(12)", - }, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(2)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(1)", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(3)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-a", - }, - Object { - "cid": "cids(5)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(3)", - "uri": "record(4)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(3)", - "muted": false, - }, - }, - "cid": "cids(4)", - "embeds": Array [], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(2)", - "val": "kind", - }, - ], - "uri": "record(2)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(1)", - "val": "kind", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(2)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(3)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(4)", - "uri": "record(2)", - }, - }, - }, - "text": "hi im carol", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(1)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(1)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(7)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(8)", - "following": "record(7)", - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(12)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(1)", - "uri": "record(16)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(16)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views fetches authenticated user's home feed w/ reverse-chronological algorithm 4`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(4)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object { - "repost": "record(5)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(4)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(3)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(4)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(2)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(1)", - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(3)", - "viewer": Object { - "like": "record(7)", - "repost": "record(6)", - }, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(6)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000+00:00", - "text": "bobby boy here", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(10)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(7)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(8)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(10)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(13)", - "val": "kind", - }, - ], - "uri": "record(13)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(12)", - "val": "kind", - }, - ], - "uri": "record(12)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(9)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(10)", - "uri": "record(13)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(12)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(11)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(9)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(8)", - "muted": false, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(10)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(13)", - "val": "kind", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(13)", - "viewer": Object {}, - }, - }, -] -`; - -exports[`timeline views omits posts and reposts of muted authors. 1`] = ` -Array [ - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": true, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - "reason": Object { - "$type": "app.bsky.feed.defs#reasonRepost", - "by": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(0)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "reply": Object { - "parent": Object { - "cid": "cids(3)", - "uri": "record(3)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "thanks bob", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(0)", - "viewer": Object {}, - }, - "reply": Object { - "parent": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": true, - }, - }, - "cid": "cids(3)", - "embed": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - ], - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label", - }, - Object { - "cid": "cids(3)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(3)", - "val": "test-label-2", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - ], - }, - "reply": Object { - "parent": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - "root": Object { - "cid": "cids(2)", - "uri": "record(2)", - }, - }, - "text": "hear that label_me label_me_2", - }, - "replyCount": 1, - "repostCount": 0, - "uri": "record(3)", - "viewer": Object {}, - }, - "root": Object { - "$type": "app.bsky.feed.defs#postView", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(6)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": true, - }, - }, - "cid": "cids(8)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(10)", - "val": "kind", - }, - ], - "uri": "record(10)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(9)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(10)", - "uri": "record(13)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "uri": "record(9)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(6)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(8)", - "val": "test-label", - }, - ], - "likeCount": 2, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(7)", - "uri": "record(9)", - }, - }, - "text": "yoohoo label_me", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(8)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(2)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 3, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000000Z", - "text": "again", - }, - "replyCount": 2, - "repostCount": 1, - "uri": "record(2)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(7)", - "embed": Object { - "$type": "app.bsky.embed.record#view", - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "did": "user(3)", - "handle": "carol.test", - "labels": Array [], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(12)", - "following": "record(11)", - "muted": true, - }, - }, - "cid": "cids(8)", - "embeds": Array [ - Object { - "$type": "app.bsky.embed.recordWithMedia#view", - "media": Object { - "$type": "app.bsky.embed.images#view", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "fullsize": "https://pds.public.url/image/AiDXkxVbgBksxb1nfiRn1m6S4K8_mee6o8r-UGLNzOM/rs:fit:2000:2000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - "thumb": "https://pds.public.url/image/uc7FGfiGv0mMqmk9XiqHXrIhNymLHaex7Ge8nEhmXqo/rs:fit:1000:1000:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg", - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "fullsize": "https://pds.public.url/image/xC2No-8rKVDIwIMmCiEBm9EiGLDBBOpf36PHoGf-GDw/rs:fit:2000:2000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - "thumb": "https://pds.public.url/image/g7yazUpNwN8LKumZ2Zmn_ptQbtMLs1Pti5-GDn7H8_8/rs:fit:1000:1000:1:0/plain/bafkreifdklbbcdsyanjz3oqe5pf2omuq5ansthokxlbleagg3eenx62h7e@jpeg", - }, - ], - }, - "record": Object { - "record": Object { - "$type": "app.bsky.embed.record#viewRecord", - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(2)", - "displayName": "bobby", - "handle": "bob.test", - "labels": Array [ - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-a", - }, - Object { - "cid": "cids(4)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(2)", - "uri": "record(7)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "followedBy": "record(6)", - "following": "record(5)", - "muted": true, - }, - }, - "cid": "cids(10)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(10)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(13)", - "val": "kind", - }, - ], - "uri": "record(13)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "langs": Array [ - "en-US", - "i-klingon", - ], - "text": "bob back at it again!", - }, - }, - }, - }, - ], - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(8)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "record(10)", - "val": "kind", - }, - ], - "uri": "record(10)", - "value": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.recordWithMedia", - "media": Object { - "$type": "app.bsky.embed.images", - "images": Array [ - Object { - "alt": "tests/image/fixtures/key-landscape-small.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(5)", - }, - "size": 4114, - }, - }, - Object { - "alt": "tests/image/fixtures/key-alt.jpg", - "image": Object { - "$type": "blob", - "mimeType": "image/jpeg", - "ref": Object { - "$link": "cids(9)", - }, - "size": 12736, - }, - }, - ], - }, - "record": Object { - "record": Object { - "cid": "cids(10)", - "uri": "record(13)", - }, - }, - }, - "text": "hi im carol", - }, - }, - }, - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "embed": Object { - "$type": "app.bsky.embed.record", - "record": Object { - "cid": "cids(8)", - "uri": "record(10)", - }, - }, - "facets": Array [ - Object { - "features": Array [ - Object { - "$type": "app.bsky.richtext.facet#mention", - "did": "user(0)", - }, - ], - "index": Object { - "byteEnd": 18, - "byteStart": 0, - }, - }, - ], - "text": "@alice.bluesky.xyz is the best", - }, - "replyCount": 0, - "repostCount": 1, - "uri": "record(9)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "did": "user(1)", - "handle": "dan.test", - "labels": Array [ - Object { - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "did:example:labeler", - "uri": "user(1)", - "val": "repo-action-label", - }, - ], - "viewer": Object { - "blockedBy": false, - "following": "record(4)", - "muted": false, - }, - }, - "cid": "cids(11)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "text": "dan here!", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(14)", - "viewer": Object {}, - }, - }, - Object { - "post": Object { - "author": Object { - "avatar": "https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg", - "did": "user(0)", - "displayName": "ali", - "handle": "alice.test", - "labels": Array [ - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-a", - }, - Object { - "cid": "cids(1)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(1)", - "val": "self-label-b", - }, - ], - "viewer": Object { - "blockedBy": false, - "muted": false, - }, - }, - "cid": "cids(12)", - "indexedAt": "1970-01-01T00:00:00.000Z", - "labels": Array [ - Object { - "cid": "cids(12)", - "cts": "1970-01-01T00:00:00.000Z", - "neg": false, - "src": "user(0)", - "uri": "record(15)", - "val": "self-label", - }, - ], - "likeCount": 0, - "record": Object { - "$type": "app.bsky.feed.post", - "createdAt": "1970-01-01T00:00:00.000Z", - "labels": Object { - "$type": "com.atproto.label.defs#selfLabels", - "values": Array [ - Object { - "val": "self-label", - }, - ], - }, - "text": "hey there", - }, - "replyCount": 0, - "repostCount": 0, - "uri": "record(15)", - "viewer": Object {}, - }, - }, -] -`; diff --git a/packages/pds/tests/views/actor-likes.test.ts b/packages/pds/tests/views/actor-likes.test.ts deleted file mode 100644 index 15e2dc3e934..00000000000 --- a/packages/pds/tests/views/actor-likes.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import AtpAgent, { AtUri } from '@atproto/api' -import { runTestServer, CloseFn } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds actor likes feed views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'pds_views_actor_likes', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('returns posts liked by actor', async () => { - const { - data: { feed: bobLikes }, - } = await agent.api.app.bsky.feed.getActorLikes( - { actor: sc.accounts[bob].handle }, - { headers: sc.getHeaders(bob) }, - ) - - expect(bobLikes).toHaveLength(3) - - await expect( - agent.api.app.bsky.feed.getActorLikes( - { actor: sc.accounts[bob].handle }, - { headers: sc.getHeaders(carol) }, - ), - ).rejects.toThrow('Profile not found') - }) - - it('viewer has blocked author of liked post(s)', async () => { - const bobBlocksAlice = await agent.api.app.bsky.graph.block.create( - { - repo: bob, // bob blocks alice - }, - { - subject: alice, - createdAt: new Date().toISOString(), - }, - sc.getHeaders(bob), - ) - - const { - data: { feed }, - } = await agent.api.app.bsky.feed.getActorLikes( - { actor: sc.accounts[bob].handle }, - { headers: sc.getHeaders(bob) }, - ) - - expect( - feed.every((item) => { - return item.post.author.did !== alice - }), - ).toBe(true) - - // unblock - await agent.api.app.bsky.graph.block.delete( - { repo: bob, rkey: new AtUri(bobBlocksAlice.uri).rkey }, - sc.getHeaders(bob), - ) - }) - - it('liked post author has blocked viewer', async () => { - const aliceBlocksBob = await agent.api.app.bsky.graph.block.create( - { - repo: alice, // alice blocks bob - }, - { - subject: bob, - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - - const { - data: { feed }, - } = await agent.api.app.bsky.feed.getActorLikes( - { actor: sc.accounts[bob].handle }, - { headers: sc.getHeaders(bob) }, - ) - - expect( - feed.every((item) => { - return item.post.author.did !== alice - }), - ).toBe(true) - - // unblock - await agent.api.app.bsky.graph.block.delete( - { repo: alice, rkey: new AtUri(aliceBlocksBob.uri).rkey }, - sc.getHeaders(alice), - ) - }) -}) diff --git a/packages/pds/tests/views/actor-search.test.ts b/packages/pds/tests/views/actor-search.test.ts deleted file mode 100644 index d110d8e2e68..00000000000 --- a/packages/pds/tests/views/actor-search.test.ts +++ /dev/null @@ -1,464 +0,0 @@ -import AtpAgent from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { - runTestServer, - forSnapshot, - CloseFn, - paginateAll, - adminAuth, -} from '../_util' -import { SeedClient } from '../seeds/client' -import usersBulkSeed from '../seeds/users-bulk' -import { Database } from '../../src' - -describe('pds user search views', () => { - let agent: AtpAgent - let db: Database - let close: CloseFn - let sc: SeedClient - let headers: { [s: string]: string } - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_user_search', - }) - close = server.close - db = server.ctx.db - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await usersBulkSeed(sc) - headers = sc.getHeaders(Object.values(sc.dids)[0]) - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('typeahead gives relevant results', async () => { - const result = await agent.api.app.bsky.actor.searchActorsTypeahead( - { term: 'car' }, - { headers }, - ) - - const handles = result.data.actors.map((u) => u.handle) - - const shouldContain = [ - 'cara-wiegand69.test', - 'eudora-dietrich4.test', // Carol Littel - 'shane-torphy52.test', // Sadie Carter - 'aliya-hodkiewicz.test', // Carlton Abernathy IV - 'carlos6.test', - 'carolina-mcdermott77.test', - ] - - shouldContain.forEach((handle) => expect(handles).toContain(handle)) - - if (db.dialect === 'pg') { - expect(handles).toContain('cayla-marquardt39.test') // Fuzzy match supported by postgres - } else { - expect(handles).not.toContain('cayla-marquardt39.test') - } - - const shouldNotContain = [ - 'sven70.test', - 'hilario84.test', - 'santa-hermann78.test', - 'dylan61.test', - 'preston-harris.test', - 'loyce95.test', - 'melyna-zboncak.test', - ] - - shouldNotContain.forEach((handle) => expect(handles).not.toContain(handle)) - - const sorted = result.data.actors.sort((a, b) => - a.handle > b.handle ? 1 : -1, - ) - if (db.dialect === 'pg') { - expect(forSnapshot(sorted)).toEqual(snapTypeaheadPg) - } else { - expect(forSnapshot(sorted)).toEqual(snapTypeaheadSqlite) - } - }) - - it('typeahead gives empty result set when provided empty term', async () => { - const result = await agent.api.app.bsky.actor.searchActorsTypeahead( - { term: '' }, - { headers }, - ) - - expect(result.data.actors).toEqual([]) - }) - - it('typeahead applies limit', async () => { - const full = await agent.api.app.bsky.actor.searchActorsTypeahead( - { term: 'p' }, - { headers }, - ) - - expect(full.data.actors.length).toBeGreaterThan(5) - - const limited = await agent.api.app.bsky.actor.searchActorsTypeahead( - { term: 'p', limit: 5 }, - { headers }, - ) - - // @NOTE it's expected that searchActorsTypeahead doesn't have stable pagination - - const limitedIndexInFull = limited.data.actors.map((needle) => { - return full.data.actors.findIndex( - (haystack) => needle.did === haystack.did, - ) - }) - - // subset exists in full and is monotonic - expect(limitedIndexInFull.every((idx) => idx !== -1)).toEqual(true) - expect(limitedIndexInFull).toEqual( - [...limitedIndexInFull].sort((a, b) => a - b), - ) - }) - - it('search gives relevant results', async () => { - const result = await agent.api.app.bsky.actor.searchActors( - { term: 'car' }, - { headers }, - ) - - const handles = result.data.actors.map((u) => u.handle) - - const shouldContain = [ - 'cara-wiegand69.test', - 'eudora-dietrich4.test', // Carol Littel - 'shane-torphy52.test', // Sadie Carter - 'aliya-hodkiewicz.test', // Carlton Abernathy IV - 'carlos6.test', - 'carolina-mcdermott77.test', - ] - - shouldContain.forEach((handle) => expect(handles).toContain(handle)) - - if (db.dialect === 'pg') { - expect(handles).toContain('cayla-marquardt39.test') // Fuzzy match supported by postgres - } else { - expect(handles).not.toContain('cayla-marquardt39.test') - } - - const shouldNotContain = [ - 'sven70.test', - 'hilario84.test', - 'santa-hermann78.test', - 'dylan61.test', - 'preston-harris.test', - 'loyce95.test', - 'melyna-zboncak.test', - ] - - shouldNotContain.forEach((handle) => expect(handles).not.toContain(handle)) - - const sorted = result.data.actors.sort((a, b) => - a.handle > b.handle ? 1 : -1, - ) - if (db.dialect === 'pg') { - expect(forSnapshot(sorted)).toEqual(snapSearchPg) - } else { - expect(forSnapshot(sorted)).toEqual(snapSearchSqlite) - } - }) - - it('search gives empty result set when provided empty term', async () => { - const result = await agent.api.app.bsky.actor.searchActors( - { term: '' }, - { headers }, - ) - - expect(result.data.actors).toEqual([]) - }) - - it('paginates', async () => { - const results = (results) => results.flatMap((res) => res.actors) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.actor.searchActors( - { term: 'p', cursor, limit: 3 }, - { headers }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.actors.length).toBeLessThanOrEqual(3), - ) - - const full = await agent.api.app.bsky.actor.searchActors( - { term: 'p' }, - { headers }, - ) - - expect(full.data.actors.length).toBeGreaterThan(5) - const sortedFull = results([full.data]).sort((a, b) => - a.handle > b.handle ? 1 : -1, - ) - const sortedPaginated = results(paginatedAll).sort((a, b) => - a.handle > b.handle ? 1 : -1, - ) - expect(sortedPaginated).toEqual(sortedFull) - }) - - it('search handles bad input', async () => { - // Mostly for sqlite's benefit, since it uses LIKE and these are special characters that will - // get stripped. This input triggers a special case where there are no "safe" words for sqlite to search on. - const result = await agent.api.app.bsky.actor.searchActors( - { term: ' % _ ' }, - { headers }, - ) - - expect(result.data.actors).toEqual([]) - }) - - it('search blocks by actor takedown', async () => { - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: sc.dids['cara-wiegand69.test'], - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - const result = await agent.api.app.bsky.actor.searchActorsTypeahead( - { term: 'car' }, - { headers }, - ) - const handles = result.data.actors.map((u) => u.handle) - expect(handles).toContain('carlos6.test') - expect(handles).toContain('carolina-mcdermott77.test') - expect(handles).not.toContain('cara-wiegand69.test') - }) -}) - -// Not using jest snapshots because it doesn't handle the conditional pg/sqlite very well: -// you can achieve it using named snapshots, but when you run the tests for pg the test suite fails -// since the sqlite snapshots appear obsolete to jest (and vice-versa when you run the sqlite suite). - -const avatar = - 'https://pds.public.url/image/KzkHFsMRQ6oAKCHCRKFA1H-rDdc7VOtvEVpUJ82TwyQ/rs:fill:1000:1000:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg' - -const snapTypeaheadPg = [ - { - did: 'user(0)', - displayName: 'Carlton Abernathy IV', - handle: 'aliya-hodkiewicz.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(1)', - handle: 'cara-wiegand69.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(2)', - handle: 'carlos6.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(3)', - displayName: 'Latoya Windler', - handle: 'carolina-mcdermott77.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(4)', - displayName: 'Rachel Kshlerin', - handle: 'cayla-marquardt39.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(5)', - displayName: 'Carol Littel', - handle: 'eudora-dietrich4.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(6)', - displayName: 'Sadie Carter', - handle: 'shane-torphy52.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, -] - -const snapTypeaheadSqlite = [ - { - did: 'user(0)', - displayName: 'Carlton Abernathy IV', - handle: 'aliya-hodkiewicz.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(1)', - handle: 'cara-wiegand69.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(2)', - handle: 'carlos6.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(3)', - displayName: 'Latoya Windler', - handle: 'carolina-mcdermott77.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(4)', - displayName: 'Carol Littel', - handle: 'eudora-dietrich4.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(5)', - displayName: 'Sadie Carter', - handle: 'shane-torphy52.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, -] - -const snapSearchPg = [ - { - did: 'user(0)', - displayName: 'Carlton Abernathy IV', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'aliya-hodkiewicz.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(1)', - handle: 'cara-wiegand69.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(2)', - handle: 'carlos6.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(3)', - displayName: 'Latoya Windler', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'carolina-mcdermott77.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(4)', - displayName: 'Rachel Kshlerin', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'cayla-marquardt39.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(5)', - displayName: 'Carol Littel', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'eudora-dietrich4.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(6)', - displayName: 'Sadie Carter', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'shane-torphy52.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, -] - -const snapSearchSqlite = [ - { - did: 'user(0)', - displayName: 'Carlton Abernathy IV', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'aliya-hodkiewicz.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(1)', - handle: 'cara-wiegand69.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(2)', - handle: 'carlos6.test', - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(3)', - displayName: 'Latoya Windler', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'carolina-mcdermott77.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(4)', - displayName: 'Carol Littel', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'eudora-dietrich4.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, - { - did: 'user(5)', - displayName: 'Sadie Carter', - indexedAt: '1970-01-01T00:00:00.000Z', - handle: 'shane-torphy52.test', - avatar, - viewer: { blockedBy: false, muted: false }, - labels: [], - }, -] diff --git a/packages/pds/tests/views/author-feed.test.ts b/packages/pds/tests/views/author-feed.test.ts deleted file mode 100644 index 2f9e8603b7b..00000000000 --- a/packages/pds/tests/views/author-feed.test.ts +++ /dev/null @@ -1,363 +0,0 @@ -import AtpAgent, { ComAtprotoAdminTakeModerationAction } from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { - runTestServer, - forSnapshot, - CloseFn, - paginateAll, - adminAuth, -} from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { isRecord } from '../../src/lexicon/types/app/bsky/feed/post' -import { isView as isEmbedRecordWithMedia } from '../../src/lexicon/types/app/bsky/embed/recordWithMedia' -import { isView as isImageEmbed } from '../../src/lexicon/types/app/bsky/embed/images' - -describe('pds author feed views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - let dan: string - - const reverseModerationAction = async (id) => - agent.api.com.atproto.admin.reverseModerationAction( - { - id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - const takedownSubject = async ( - subject: ComAtprotoAdminTakeModerationAction.InputSchema['subject'], - ) => - agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_author_feed', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - dan = sc.dids.dan - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches full author feeds for self (sorted, minimal viewer state).', async () => { - const aliceForAlice = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[alice].handle }, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(forSnapshot(aliceForAlice.data.feed)).toMatchSnapshot() - - const bobForBob = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[bob].handle }, - { - headers: sc.getHeaders(bob), - }, - ) - - expect(forSnapshot(bobForBob.data.feed)).toMatchSnapshot() - - const carolForCarol = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[carol].handle }, - { - headers: sc.getHeaders(carol), - }, - ) - - expect(forSnapshot(carolForCarol.data.feed)).toMatchSnapshot() - - const danForDan = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[dan].handle }, - { - headers: sc.getHeaders(dan), - }, - ) - - expect(forSnapshot(danForDan.data.feed)).toMatchSnapshot() - }) - - it("reflects fetching user's state in the feed.", async () => { - const aliceForCarol = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[alice].handle }, - { - headers: sc.getHeaders(carol), - }, - ) - - aliceForCarol.data.feed.forEach((postView) => { - const { viewer, uri } = postView.post - expect(viewer?.like).toEqual(sc.likes[carol]?.[uri]?.toString()) - expect(viewer?.repost).toEqual(sc.reposts[carol][uri]?.toString()) - }) - - expect(forSnapshot(aliceForCarol.data.feed)).toMatchSnapshot() - }) - - it('omits reposts from muted users.', async () => { - await agent.api.app.bsky.graph.muteActor( - { actor: alice }, // Has a repost by dan: will be omitted from dan's feed - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - await agent.api.app.bsky.graph.muteActor( - { actor: dan }, // Feed author: their posts will still appear - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - const bobForDan = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: sc.accounts[dan].handle }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(bobForDan.data.feed)).toMatchSnapshot() - - await agent.api.app.bsky.graph.unmuteActor( - { actor: alice }, - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - await agent.api.app.bsky.graph.unmuteActor( - { actor: dan }, - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - }) - - it('paginates', async () => { - const results = (results) => results.flatMap((res) => res.feed) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getAuthorFeed( - { - actor: sc.accounts[alice].handle, - cursor, - limit: 2, - }, - { headers: sc.getHeaders(dan) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.feed.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.feed.getAuthorFeed( - { - actor: sc.accounts[alice].handle, - }, - { headers: sc.getHeaders(dan) }, - ) - - expect(full.data.feed.length).toEqual(4) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('blocked by actor takedown.', async () => { - const { data: preBlock } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ) - - expect(preBlock.feed.length).toBeGreaterThan(0) - - const { data: action } = await takedownSubject({ - $type: 'com.atproto.admin.defs#repoRef', - did: alice, - }) - - const attempt = agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ) - await expect(attempt).rejects.toThrow('Profile not found') - - // Cleanup - await reverseModerationAction(action.id) - }) - - it('blocked by record takedown.', async () => { - const { data: preBlock } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ) - - expect(preBlock.feed.length).toBeGreaterThan(0) - - const post = preBlock.feed[0].post - - const { data: action } = await takedownSubject({ - $type: 'com.atproto.repo.strongRef', - uri: post.uri, - cid: post.cid, - }) - - const { data: postBlock } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ) - - expect(postBlock.feed.length).toEqual(preBlock.feed.length - 1) - expect(postBlock.feed.map((item) => item.post.uri)).not.toContain(post.uri) - - // Cleanup - await reverseModerationAction(action.id) - }) - - it('includes takendown posts for admins', async () => { - const { data: preTakedown } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ) - - expect(preTakedown.feed.length).toBeGreaterThan(0) - - const post = preTakedown.feed[0].post - - const { data: takedownAction } = await takedownSubject({ - $type: 'com.atproto.repo.strongRef', - uri: post.uri, - cid: post.cid, - }) - - const [{ data: postTakedownForCarol }, { data: postTakedownForAdmin }] = - await Promise.all([ - agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(carol) }, - ), - agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: { authorization: adminAuth() } }, - ), - ]) - - const takendownPostInCarolsFeed = postTakedownForCarol.feed.find( - (item) => item.post.uri === post.uri || !!post.takedownId, - ) - const takendownPostInAdminsFeed = postTakedownForAdmin.feed.find( - (item) => item.post.uri === post.uri || !!post.takedownId, - ) - expect(takendownPostInCarolsFeed).toBeFalsy() - expect(takendownPostInAdminsFeed).toBeTruthy() - expect(takendownPostInAdminsFeed?.post.takedownId).toEqual( - takedownAction.id, - ) - - // Cleanup - await reverseModerationAction(takedownAction.id) - }) - - it('can filter by posts_with_media', async () => { - const { data: carolFeed } = await agent.api.app.bsky.feed.getAuthorFeed( - { - actor: carol, - filter: 'posts_with_media', - }, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(carolFeed.feed.length).toBeGreaterThan(0) - expect( - carolFeed.feed.every(({ post }) => { - const isRecordWithActorMedia = - isEmbedRecordWithMedia(post.embed) && isImageEmbed(post.embed?.media) - const isActorMedia = isImageEmbed(post.embed) - const isFromActor = post.author.did === carol - - return (isRecordWithActorMedia || isActorMedia) && isFromActor - }), - ).toBeTruthy() - - const { data: bobFeed } = await agent.api.app.bsky.feed.getAuthorFeed( - { - actor: bob, - filter: 'posts_with_media', - }, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(bobFeed.feed.length).toBeGreaterThan(0) - expect( - bobFeed.feed.every(({ post }) => { - return isImageEmbed(post.embed) && post.author.did === bob - }), - ).toBeTruthy() - - const { data: danFeed } = await agent.api.app.bsky.feed.getAuthorFeed( - { - actor: dan, - filter: 'posts_with_media', - }, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(danFeed.feed.length).toEqual(0) - }) - - it('filters by posts_no_replies', async () => { - const { data: carolFeed } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: carol, filter: 'posts_no_replies' }, - { headers: sc.getHeaders(alice) }, - ) - - expect( - carolFeed.feed.every(({ post }) => { - return ( - (isRecord(post.record) && !post.record.reply) || - (isRecord(post.record) && post.record.reply) - ) - }), - ).toBeTruthy() - - const { data: danFeed } = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: dan, filter: 'posts_no_replies' }, - { headers: sc.getHeaders(alice) }, - ) - - expect( - danFeed.feed.every(({ post }) => { - return ( - (isRecord(post.record) && !post.record.reply) || - (isRecord(post.record) && post.record.reply) - ) - }), - ).toBeTruthy() - }) -}) diff --git a/packages/pds/tests/views/blocks.test.ts b/packages/pds/tests/views/blocks.test.ts deleted file mode 100644 index 8d8fb3dba76..00000000000 --- a/packages/pds/tests/views/blocks.test.ts +++ /dev/null @@ -1,531 +0,0 @@ -import assert from 'assert' -import AtpAgent, { AtUri } from '@atproto/api' -import { RecordRef } from '@atproto/bsky/tests/seeds/client' -import { BlockedActorError } from '@atproto/api/src/client/types/app/bsky/feed/getAuthorFeed' -import { BlockedByActorError } from '@atproto/api/src/client/types/app/bsky/feed/getAuthorFeed' -import { isThreadViewPost } from '@atproto/api/src/client/types/app/bsky/feed/defs' -import { - isViewRecord as isEmbedViewRecord, - isViewBlocked as isEmbedViewBlocked, -} from '@atproto/api/src/client/types/app/bsky/embed/record' -import { runTestServer, CloseFn, TestServerInfo, forSnapshot } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds views with blocking', () => { - let server: TestServerInfo - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - let danBlockCarol: { uri: string } - let aliceReplyToDan: { ref: RecordRef } - let carolReplyToDan: { ref: RecordRef } - - let alice: string - let carol: string - let dan: string - let danBlockUri: string - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_block', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - carol = sc.dids.carol - dan = sc.dids.dan - // add follows to ensure blocks work even w follows - await sc.follow(carol, dan) - await sc.follow(dan, carol) - aliceReplyToDan = await sc.reply( - alice, - sc.posts[dan][0].ref, - sc.posts[dan][0].ref, - 'alice replies to dan', - ) - carolReplyToDan = await sc.reply( - carol, - sc.posts[dan][0].ref, - sc.posts[dan][0].ref, - 'carol replies to dan', - ) - // dan blocks carol - danBlockCarol = await agent.api.app.bsky.graph.block.create( - { repo: dan }, - { createdAt: new Date().toISOString(), subject: carol }, - sc.getHeaders(dan), - ) - danBlockUri = danBlockCarol.uri - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('blocks thread post', async () => { - const { data: threadAlice } = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[carol][0].ref.uriStr }, - { headers: sc.getHeaders(dan) }, - ) - expect(threadAlice).toEqual({ - thread: { - $type: 'app.bsky.feed.defs#blockedPost', - uri: sc.posts[carol][0].ref.uriStr, - blocked: true, - author: { - did: carol, - viewer: { - blockedBy: false, - blocking: danBlockUri, - }, - }, - }, - }) - const { data: threadCarol } = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[dan][0].ref.uriStr }, - { headers: sc.getHeaders(carol) }, - ) - expect(threadCarol).toEqual({ - thread: { - $type: 'app.bsky.feed.defs#blockedPost', - uri: sc.posts[dan][0].ref.uriStr, - blocked: true, - author: { - did: dan, - viewer: { - blockedBy: true, - }, - }, - }, - }) - }) - - it('blocks thread reply', async () => { - // Contains reply by carol - const { data: thread } = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(thread)).toMatchSnapshot() - }) - - it('blocks thread parent', async () => { - // Parent is a post by dan - const { data: thread } = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: aliceReplyToDan.ref.uriStr }, - { headers: sc.getHeaders(carol) }, - ) - expect(forSnapshot(thread)).toMatchSnapshot() - }) - - it('blocks record embeds', async () => { - // Contains a deep embed of carol's post, blocked by dan - const { data: thread } = await agent.api.app.bsky.feed.getPostThread( - { depth: 0, uri: sc.posts[alice][2].ref.uriStr }, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(thread)).toMatchSnapshot() - }) - - it('errors on getting author feed', async () => { - const attempt1 = agent.api.app.bsky.feed.getAuthorFeed( - { actor: carol }, - { headers: sc.getHeaders(dan) }, - ) - await expect(attempt1).rejects.toThrow(BlockedActorError) - - const attempt2 = agent.api.app.bsky.feed.getAuthorFeed( - { actor: dan }, - { headers: sc.getHeaders(carol) }, - ) - await expect(attempt2).rejects.toThrow(BlockedByActorError) - }) - - it('strips blocked users out of getTimeline', async () => { - const resCarol = await agent.api.app.bsky.feed.getTimeline( - { limit: 100 }, - { headers: sc.getHeaders(carol) }, - ) - expect( - resCarol.data.feed.some((post) => post.post.author.did === dan), - ).toBeFalsy() - - const resDan = await agent.api.app.bsky.feed.getTimeline( - { limit: 100 }, - { headers: sc.getHeaders(dan) }, - ) - expect( - resDan.data.feed.some((post) => post.post.author.did === carol), - ).toBeFalsy() - }) - - it('strips blocked users out of getPopular', async () => { - for (let i = 0; i < 15; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - await sc.like(sc.dids[name], sc.posts[alice][0].ref) - await sc.like(sc.dids[name], sc.posts[carol][0].ref) - await sc.like(sc.dids[name], sc.posts[dan][0].ref) - } - - const resCarol = await agent.api.app.bsky.unspecced.getPopular( - {}, - { headers: sc.getHeaders(carol) }, - ) - expect( - resCarol.data.feed.some((post) => post.post.author.did === alice), - ).toBeTruthy() - expect( - resCarol.data.feed.some((post) => post.post.author.did === carol), - ).toBeTruthy() - expect( - resCarol.data.feed.some((post) => post.post.author.did === dan), - ).toBeFalsy() - - const resDan = await agent.api.app.bsky.unspecced.getPopular( - {}, - { headers: sc.getHeaders(dan) }, - ) - expect( - resDan.data.feed.some((post) => post.post.author.did === alice), - ).toBeTruthy() - expect( - resDan.data.feed.some((post) => post.post.author.did === carol), - ).toBeFalsy() - expect( - resDan.data.feed.some((post) => post.post.author.did === dan), - ).toBeTruthy() - }) - - it('returns block status on getProfile', async () => { - const resCarol = await agent.api.app.bsky.actor.getProfile( - { actor: dan }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.viewer?.blocking).toBeUndefined - expect(resCarol.data.viewer?.blockedBy).toBe(true) - - const resDan = await agent.api.app.bsky.actor.getProfile( - { actor: carol }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.viewer?.blocking).toBeDefined - expect(resDan.data.viewer?.blockedBy).toBe(false) - }) - - it('returns block status on getProfiles', async () => { - const resCarol = await agent.api.app.bsky.actor.getProfiles( - { actors: [alice, dan] }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.profiles[0].viewer?.blocking).toBeUndefined() - expect(resCarol.data.profiles[0].viewer?.blockedBy).toBe(false) - expect(resCarol.data.profiles[1].viewer?.blocking).toBeUndefined() - expect(resCarol.data.profiles[1].viewer?.blockedBy).toBe(true) - - const resDan = await agent.api.app.bsky.actor.getProfiles( - { actors: [alice, carol] }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.profiles[0].viewer?.blocking).toBeUndefined() - expect(resDan.data.profiles[0].viewer?.blockedBy).toBe(false) - expect(resDan.data.profiles[1].viewer?.blocking).toBeDefined() - expect(resDan.data.profiles[1].viewer?.blockedBy).toBe(false) - }) - - it('does not return block violating follows', async () => { - const resCarol = await agent.api.app.bsky.graph.getFollows( - { actor: carol }, - { headers: sc.getHeaders(alice) }, - ) - expect(resCarol.data.follows.some((f) => f.did === dan)).toBe(false) - - const resDan = await agent.api.app.bsky.graph.getFollows( - { actor: dan }, - { headers: sc.getHeaders(alice) }, - ) - expect(resDan.data.follows.some((f) => f.did === carol)).toBe(false) - }) - - it('does not return block violating followers', async () => { - const resCarol = await agent.api.app.bsky.graph.getFollowers( - { actor: carol }, - { headers: sc.getHeaders(alice) }, - ) - expect(resCarol.data.followers.some((f) => f.did === dan)).toBe(false) - - const resDan = await agent.api.app.bsky.graph.getFollowers( - { actor: dan }, - { headers: sc.getHeaders(alice) }, - ) - expect(resDan.data.followers.some((f) => f.did === carol)).toBe(false) - }) - - it('does not return posts from blocked users', async () => { - const alicePost = sc.posts[alice][0].ref.uriStr - const carolPost = sc.posts[carol][0].ref.uriStr - const danPost = sc.posts[dan][0].ref.uriStr - - const resCarol = await agent.api.app.bsky.feed.getPosts( - { uris: [alicePost, carolPost, danPost] }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.posts.some((p) => p.uri === alicePost)).toBe(true) - expect(resCarol.data.posts.some((p) => p.uri === carolPost)).toBe(true) - expect(resCarol.data.posts.some((p) => p.uri === danPost)).toBe(false) - - const resDan = await agent.api.app.bsky.feed.getPosts( - { uris: [alicePost, carolPost, danPost] }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.posts.some((p) => p.uri === alicePost)).toBe(true) - expect(resDan.data.posts.some((p) => p.uri === carolPost)).toBe(false) - expect(resDan.data.posts.some((p) => p.uri === danPost)).toBe(true) - }) - - it('does not return notifs for blocked accounts', async () => { - const resCarol = await agent.api.app.bsky.notification.listNotifications( - { - limit: 100, - }, - { headers: sc.getHeaders(carol) }, - ) - expect( - resCarol.data.notifications.some((notif) => notif.author.did === dan), - ).toBeFalsy() - - const resDan = await agent.api.app.bsky.notification.listNotifications( - { - limit: 100, - }, - { headers: sc.getHeaders(dan) }, - ) - expect( - resDan.data.notifications.some((notif) => notif.author.did === carol), - ).toBeFalsy() - }) - - it('does not return blocked accounts in actor search', async () => { - const resCarol = await agent.api.app.bsky.actor.searchActors( - { - term: 'dan.test', - }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.actors.some((actor) => actor.did === dan)).toBeFalsy() - - const resDan = await agent.api.app.bsky.actor.searchActors( - { - term: 'carol.test', - }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.actors.some((actor) => actor.did === carol)).toBeFalsy() - }) - - it('does not return blocked accounts in actor search typeahead', async () => { - const resCarol = await agent.api.app.bsky.actor.searchActorsTypeahead( - { - term: 'dan.test', - }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.actors.some((actor) => actor.did === dan)).toBeFalsy() - - const resDan = await agent.api.app.bsky.actor.searchActorsTypeahead( - { - term: 'carol.test', - }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.actors.some((actor) => actor.did === carol)).toBeFalsy() - }) - - it('does not return blocked accounts in get suggestions', async () => { - // unfollow so they _would_ show up in suggestions if not for block - await sc.unfollow(carol, dan) - await sc.unfollow(dan, carol) - - const resCarol = await agent.api.app.bsky.actor.getSuggestions( - { - limit: 100, - }, - { headers: sc.getHeaders(carol) }, - ) - expect(resCarol.data.actors.some((actor) => actor.did === dan)).toBeFalsy() - - const resDan = await agent.api.app.bsky.actor.getSuggestions( - { - limit: 100, - }, - { headers: sc.getHeaders(dan) }, - ) - expect(resDan.data.actors.some((actor) => actor.did === carol)).toBeFalsy() - }) - - it('does not serve blocked replies', async () => { - const getThreadPostUri = (r) => r?.['post']?.['uri'] - // reply then block - const { data: replyThenBlock } = - await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[dan][0].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(replyThenBlock.thread)) - expect(replyThenBlock.thread.replies?.map(getThreadPostUri)).toEqual([ - aliceReplyToDan.ref.uriStr, - ]) - - // unblock - await agent.api.app.bsky.graph.block.delete( - { repo: dan, rkey: new AtUri(danBlockCarol.uri).rkey }, - sc.getHeaders(dan), - ) - const { data: unblock } = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[dan][0].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(unblock.thread)) - expect(unblock.thread.replies?.map(getThreadPostUri)).toEqual([ - carolReplyToDan.ref.uriStr, - aliceReplyToDan.ref.uriStr, - ]) - - // block then reply - danBlockCarol = await agent.api.app.bsky.graph.block.create( - { repo: dan }, - { createdAt: new Date().toISOString(), subject: carol }, - sc.getHeaders(dan), - ) - const carolReplyToDan2 = await sc.reply( - carol, - sc.posts[dan][1].ref, - sc.posts[dan][1].ref, - 'carol replies to dan again', - ) - const { data: blockThenReply } = - await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[dan][0].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(blockThenReply.thread)) - expect(replyThenBlock.thread.replies?.map(getThreadPostUri)).toEqual([ - aliceReplyToDan.ref.uriStr, - ]) - - // cleanup - await agent.api.app.bsky.feed.post.delete( - { repo: carol, rkey: carolReplyToDan2.ref.uri.rkey }, - sc.getHeaders(carol), - ) - }) - - it('does not serve blocked embeds to third-party', async () => { - // embed then block - const { data: embedThenBlock } = - await agent.api.app.bsky.feed.getPostThread( - { depth: 0, uri: sc.posts[dan][1].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(embedThenBlock.thread)) - assert(isEmbedViewBlocked(embedThenBlock.thread.post.embed?.record)) - - // unblock - await agent.api.app.bsky.graph.block.delete( - { repo: dan, rkey: new AtUri(danBlockCarol.uri).rkey }, - sc.getHeaders(dan), - ) - const { data: unblock } = await agent.api.app.bsky.feed.getPostThread( - { depth: 0, uri: sc.posts[dan][1].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(unblock.thread)) - assert(isEmbedViewRecord(unblock.thread.post.embed?.record)) - - // block then embed - danBlockCarol = await agent.api.app.bsky.graph.block.create( - { repo: dan }, - { createdAt: new Date().toISOString(), subject: carol }, - sc.getHeaders(dan), - ) - const carolEmbedsDan = await sc.post( - carol, - 'carol embeds dan', - undefined, - undefined, - sc.posts[dan][0].ref, - ) - const { data: blockThenEmbed } = - await agent.api.app.bsky.feed.getPostThread( - { depth: 0, uri: carolEmbedsDan.ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - assert(isThreadViewPost(blockThenEmbed.thread)) - assert(isEmbedViewBlocked(blockThenEmbed.thread.post.embed?.record)) - - // cleanup - await agent.api.app.bsky.feed.post.delete( - { repo: carol, rkey: carolEmbedsDan.ref.uri.rkey }, - sc.getHeaders(carol), - ) - }) - - it('applies third-party blocking rules in feeds.', async () => { - // alice follows carol and dan, block exists between carol and dan. - const replyBlockedUri = carolReplyToDan.ref.uriStr - const embedBlockedUri = sc.posts[dan][1].ref.uriStr - const { data: timeline } = await agent.api.app.bsky.feed.getTimeline( - { limit: 100 }, - { headers: sc.getHeaders(alice) }, - ) - const replyBlockedPost = timeline.feed.find( - (item) => item.post.uri === replyBlockedUri, - ) - expect(replyBlockedPost).toBeUndefined() - const embedBlockedPost = timeline.feed.find( - (item) => item.post.uri === embedBlockedUri, - ) - assert(embedBlockedPost) - assert(isEmbedViewBlocked(embedBlockedPost.post.embed?.record)) - }) - - it('returns a list of blocks', async () => { - await agent.api.app.bsky.graph.block.create( - { repo: dan }, - { createdAt: new Date().toISOString(), subject: alice }, - sc.getHeaders(dan), - ) - - const res = await agent.api.app.bsky.graph.getBlocks( - {}, - { headers: sc.getHeaders(dan) }, - ) - const dids = res.data.blocks.map((block) => block.did).sort() - expect(dids).toEqual([alice, carol].sort()) - }) - - it('paginates getBlocks', async () => { - const full = await agent.api.app.bsky.graph.getBlocks( - {}, - { headers: sc.getHeaders(dan) }, - ) - const first = await agent.api.app.bsky.graph.getBlocks( - { limit: 1 }, - { headers: sc.getHeaders(dan) }, - ) - const second = await agent.api.app.bsky.graph.getBlocks( - { cursor: first.data.cursor }, - { headers: sc.getHeaders(dan) }, - ) - const combined = [...first.data.blocks, ...second.data.blocks] - expect(combined).toEqual(full.data.blocks) - }) -}) diff --git a/packages/pds/tests/views/follows.test.ts b/packages/pds/tests/views/follows.test.ts deleted file mode 100644 index 606b85f9d48..00000000000 --- a/packages/pds/tests/views/follows.test.ts +++ /dev/null @@ -1,266 +0,0 @@ -import AtpAgent from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { - forSnapshot, - paginateAll, - adminAuth, - runTestServer, - CloseFn, -} from '../_util' -import { SeedClient } from '../seeds/client' -import followsSeed from '../seeds/follows' - -describe('pds follow views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_follows', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await followsSeed(sc) - alice = sc.dids.alice - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches followers', async () => { - const aliceFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceFollowers.data)).toMatchSnapshot() - - const bobFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.bob }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(bobFollowers.data)).toMatchSnapshot() - - const carolFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.carol }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(carolFollowers.data)).toMatchSnapshot() - - const danFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(danFollowers.data)).toMatchSnapshot() - - const eveFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.eve }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(eveFollowers.data)).toMatchSnapshot() - }) - - it('fetches followers by handle', async () => { - const byDid = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - const byHandle = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.accounts[alice].handle }, - { headers: sc.getHeaders(alice) }, - ) - expect(byHandle.data).toEqual(byDid.data) - }) - - it('paginates followers', async () => { - const results = (results) => results.flatMap((res) => res.followers) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.graph.getFollowers( - { - actor: sc.dids.alice, - cursor, - limit: 2, - }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.followers.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(full.data.followers.length).toEqual(4) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('blocks followers by actor takedown', async () => { - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: sc.dids.dan, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - const aliceFollowers = await agent.api.app.bsky.graph.getFollowers( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceFollowers.data)).toMatchSnapshot() - - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('fetches follows', async () => { - const aliceFollowers = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceFollowers.data)).toMatchSnapshot() - - const bobFollowers = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.bob }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(bobFollowers.data)).toMatchSnapshot() - - const carolFollowers = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.carol }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(carolFollowers.data)).toMatchSnapshot() - - const danFollowers = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(danFollowers.data)).toMatchSnapshot() - - const eveFollowers = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.eve }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(eveFollowers.data)).toMatchSnapshot() - }) - - it('fetches follows by handle', async () => { - const byDid = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - const byHandle = await agent.api.app.bsky.graph.getFollows( - { actor: sc.accounts[alice].handle }, - { headers: sc.getHeaders(alice) }, - ) - expect(byHandle.data).toEqual(byDid.data) - }) - - it('paginates follows', async () => { - const results = (results) => results.flatMap((res) => res.follows) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.graph.getFollows( - { - actor: sc.dids.alice, - cursor, - limit: 2, - }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.follows.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(full.data.follows.length).toEqual(4) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('blocks follows by actor takedown', async () => { - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: sc.dids.dan, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - const aliceFollows = await agent.api.app.bsky.graph.getFollows( - { actor: sc.dids.alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceFollows.data)).toMatchSnapshot() - - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) -}) diff --git a/packages/pds/tests/views/likes.test.ts b/packages/pds/tests/views/likes.test.ts deleted file mode 100644 index d77251d8b25..00000000000 --- a/packages/pds/tests/views/likes.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -import AtpAgent from '@atproto/api' -import { SeedClient } from '../seeds/client' -import likesSeed from '../seeds/likes' -import { - CloseFn, - constantDate, - forSnapshot, - paginateAll, - runTestServer, -} from '../_util' - -describe('pds like views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_likes', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await likesSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - const getCursors = (items: { createdAt?: string }[]) => - items.map((item) => item.createdAt ?? constantDate) - - const getSortedCursors = (items: { createdAt?: string }[]) => - getCursors(items).sort((a, b) => tstamp(b) - tstamp(a)) - - const tstamp = (x: string) => new Date(x).getTime() - - it('fetches post likes', async () => { - const alicePost = await agent.api.app.bsky.feed.getLikes( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(alicePost.data)).toMatchSnapshot() - expect(getCursors(alicePost.data.likes)).toEqual( - getSortedCursors(alicePost.data.likes), - ) - }) - - it('fetches reply likes', async () => { - const bobReply = await agent.api.app.bsky.feed.getLikes( - { uri: sc.replies[bob][0].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(bobReply.data)).toMatchSnapshot() - expect(getCursors(bobReply.data.likes)).toEqual( - getSortedCursors(bobReply.data.likes), - ) - }) - - it('paginates', async () => { - const results = (results) => results.flatMap((res) => res.likes) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getLikes( - { - uri: sc.posts[alice][1].ref.uriStr, - cursor, - limit: 2, - }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.likes.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.feed.getLikes( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - - expect(full.data.likes.length).toEqual(4) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) -}) diff --git a/packages/pds/tests/views/mute-lists.test.ts b/packages/pds/tests/views/mute-lists.test.ts deleted file mode 100644 index 64692a81b24..00000000000 --- a/packages/pds/tests/views/mute-lists.test.ts +++ /dev/null @@ -1,355 +0,0 @@ -import AtpAgent, { AtUri } from '@atproto/api' -import { runTestServer, CloseFn, TestServerInfo, forSnapshot } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { RecordRef } from '../seeds/client' - -describe('pds views with mutes from mute lists', () => { - let server: TestServerInfo - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - let alice: string - let bob: string - let carol: string - let dan: string - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_mute_lists', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - dan = sc.dids.dan - // add follows to ensure mutes work even w follows - await sc.follow(carol, dan) - await sc.follow(dan, carol) - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - let listUri: string - let listCid: string - - it('creates a list with some items', async () => { - const avatar = await sc.uploadFile( - alice, - 'tests/image/fixtures/key-portrait-small.jpg', - 'image/jpeg', - ) - // alice creates mute list with bob & carol that dan uses - const list = await agent.api.app.bsky.graph.list.create( - { repo: alice }, - { - name: 'alice mutes', - purpose: 'app.bsky.graph.defs#modlist', - description: 'big list of mutes', - avatar: avatar.image, - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - listUri = list.uri - listCid = list.cid - await agent.api.app.bsky.graph.listitem.create( - { repo: alice }, - { - subject: sc.dids.bob, - list: list.uri, - reason: 'because', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - await agent.api.app.bsky.graph.listitem.create( - { repo: alice }, - { - subject: sc.dids.carol, - list: list.uri, - reason: 'idk', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - }) - - it('uses a list for mutes', async () => { - await agent.api.app.bsky.graph.muteActorList( - { - list: listUri, - }, - { encoding: 'application/json', headers: sc.getHeaders(dan) }, - ) - }) - - it('flags mutes in threads', async () => { - const res = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(res.data.thread)).toMatchSnapshot() - }) - - it('does not show reposted content from a muted account in author feed', async () => { - await sc.repost(alice, sc.posts[carol][0].ref) - - const res = await agent.api.app.bsky.feed.getAuthorFeed( - { actor: alice }, - { headers: sc.getHeaders(dan) }, - ) - expect( - res.data.feed.some((post) => [bob, carol].includes(post.post.author.did)), - ).toBe(false) - }) - - it('removes content from muted users on getTimeline', async () => { - const res = await agent.api.app.bsky.feed.getTimeline( - { limit: 100 }, - { headers: sc.getHeaders(dan) }, - ) - expect( - res.data.feed.some((post) => [bob, carol].includes(post.post.author.did)), - ).toBe(false) - }) - - it('flags muted users on getPopular', async () => { - for (let i = 0; i < 15; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - await sc.like(sc.dids[name], sc.posts[alice][0].ref) - await sc.like(sc.dids[name], sc.posts[bob][0].ref) - await sc.like(sc.dids[name], sc.posts[carol][0].ref) - await sc.like(sc.dids[name], sc.posts[dan][0].ref) - } - - const res = await agent.api.app.bsky.unspecced.getPopular( - {}, - { headers: sc.getHeaders(dan) }, - ) - expect( - res.data.feed.some((post) => [bob, carol].includes(post.post.author.did)), - ).toBe(false) - }) - - it('returns mute status on getProfile', async () => { - const res = await agent.api.app.bsky.actor.getProfile( - { actor: carol }, - { headers: sc.getHeaders(dan) }, - ) - expect(res.data.viewer?.muted).toBe(true) - expect(res.data.viewer?.mutedByList?.uri).toBe(listUri) - }) - - it('returns mute status on getProfiles', async () => { - const res = await agent.api.app.bsky.actor.getProfiles( - { actors: [alice, carol] }, - { headers: sc.getHeaders(dan) }, - ) - expect(res.data.profiles[0].viewer?.muted).toBe(false) - expect(res.data.profiles[0].viewer?.mutedByList).toBeUndefined() - expect(res.data.profiles[1].viewer?.muted).toBe(true) - expect(res.data.profiles[1].viewer?.mutedByList?.uri).toEqual(listUri) - }) - - it('does not return notifs for muted accounts', async () => { - const res = await agent.api.app.bsky.notification.listNotifications( - { - limit: 100, - }, - { headers: sc.getHeaders(dan) }, - ) - expect( - res.data.notifications.some((notif) => - [bob, carol].includes(notif.author.did), - ), - ).toBeFalsy() - }) - - it('flags muted accounts in in get suggestions', async () => { - // unfollow so they _would_ show up in suggestions if not for mute - await sc.unfollow(dan, carol) - - const res = await agent.api.app.bsky.actor.getSuggestions( - { - limit: 100, - }, - { headers: sc.getHeaders(dan) }, - ) - for (const actor of res.data.actors) { - if ([bob, carol].includes(actor.did)) { - expect(actor.viewer?.muted).toBe(true) - expect(actor.viewer?.mutedByList?.uri).toEqual(listUri) - } else { - expect(actor.viewer?.muted).toBe(false) - expect(actor.viewer?.mutedByList).toBeUndefined() - } - } - }) - - it('returns the contents of a list', async () => { - const res = await agent.api.app.bsky.graph.getList( - { list: listUri }, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(res.data)).toMatchSnapshot() - }) - - it('paginates getList', async () => { - const full = await agent.api.app.bsky.graph.getList( - { list: listUri }, - { headers: sc.getHeaders(dan) }, - ) - const first = await agent.api.app.bsky.graph.getList( - { list: listUri, limit: 1 }, - { headers: sc.getHeaders(dan) }, - ) - const second = await agent.api.app.bsky.graph.getList( - { list: listUri, cursor: first.data.cursor }, - { headers: sc.getHeaders(dan) }, - ) - const combined = [...first.data.items, ...second.data.items] - expect(combined).toEqual(full.data.items) - }) - - let otherListUri: string - - it('returns lists associated with a user', async () => { - const listRes = await agent.api.app.bsky.graph.list.create( - { repo: alice }, - { - name: 'new list', - purpose: 'app.bsky.graph.defs#modlist', - description: 'blah blah', - createdAt: new Date().toISOString(), - }, - sc.getHeaders(alice), - ) - otherListUri = listRes.uri - - const res = await agent.api.app.bsky.graph.getLists( - { actor: alice }, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(res.data)).toMatchSnapshot() - }) - - it('paginates getLists', async () => { - const full = await agent.api.app.bsky.graph.getLists( - { actor: alice }, - { headers: sc.getHeaders(dan) }, - ) - const first = await agent.api.app.bsky.graph.getLists( - { actor: alice, limit: 1 }, - { headers: sc.getHeaders(dan) }, - ) - const second = await agent.api.app.bsky.graph.getLists( - { actor: alice, cursor: first.data.cursor }, - { headers: sc.getHeaders(dan) }, - ) - const combined = [...first.data.lists, ...second.data.lists] - expect(combined).toEqual(full.data.lists) - }) - - it('returns a users own list mutes', async () => { - await agent.api.app.bsky.graph.muteActorList( - { - list: otherListUri, - }, - { encoding: 'application/json', headers: sc.getHeaders(dan) }, - ) - - const res = await agent.api.app.bsky.graph.getListMutes( - {}, - { headers: sc.getHeaders(dan) }, - ) - expect(forSnapshot(res.data)).toMatchSnapshot() - }) - - it('paginates getListMutes', async () => { - const full = await agent.api.app.bsky.graph.getListMutes( - {}, - { headers: sc.getHeaders(dan) }, - ) - const first = await agent.api.app.bsky.graph.getListMutes( - { limit: 1 }, - { headers: sc.getHeaders(dan) }, - ) - const second = await agent.api.app.bsky.graph.getListMutes( - { cursor: first.data.cursor }, - { headers: sc.getHeaders(dan) }, - ) - const combined = [...first.data.lists, ...second.data.lists] - expect(combined).toEqual(full.data.lists) - }) - - it('allows unsubscribing from a mute list', async () => { - await agent.api.app.bsky.graph.unmuteActorList( - { - list: otherListUri, - }, - { encoding: 'application/json', headers: sc.getHeaders(dan) }, - ) - - const res = await agent.api.app.bsky.graph.getListMutes( - {}, - { headers: sc.getHeaders(dan) }, - ) - expect(res.data.lists.length).toBe(1) - }) - - it('updates list', async () => { - const uri = new AtUri(listUri) - await agent.api.com.atproto.repo.putRecord( - { - repo: uri.hostname, - collection: uri.collection, - rkey: uri.rkey, - record: { - name: 'updated alice mutes', - purpose: 'app.bsky.graph.defs#modlist', - description: 'new descript', - createdAt: new Date().toISOString(), - }, - }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - - const got = await agent.api.app.bsky.graph.getList( - { list: listUri }, - { headers: sc.getHeaders(alice) }, - ) - expect(got.data.list.name).toBe('updated alice mutes') - expect(got.data.list.description).toBe('new descript') - expect(got.data.list.avatar).toBeUndefined() - expect(got.data.items.length).toBe(2) - }) - - it('embeds lists in posts', async () => { - const postRef = await sc.post( - alice, - 'list embed!', - undefined, - undefined, - new RecordRef(listUri, listCid), - ) - const res = await agent.api.app.bsky.feed.getPosts( - { uris: [postRef.ref.uriStr] }, - { headers: sc.getHeaders(alice) }, - ) - expect(res.data.posts.length).toBe(1) - expect(forSnapshot(res.data.posts[0])).toMatchSnapshot() - }) -}) diff --git a/packages/pds/tests/views/mutes.test.ts b/packages/pds/tests/views/mutes.test.ts deleted file mode 100644 index ac32d43ab6f..00000000000 --- a/packages/pds/tests/views/mutes.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import AtpAgent from '@atproto/api' -import { runTestServer, forSnapshot, CloseFn, paginateAll } from '../_util' -import { SeedClient } from '../seeds/client' -import usersBulkSeed from '../seeds/users-bulk' - -describe('mute views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - let silas: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_mutes', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await usersBulkSeed(sc, 10) - silas = sc.dids['silas77.test'] - const mutes = [ - 'aliya-hodkiewicz.test', - 'adrienne49.test', - 'jeffrey-sawayn87.test', - 'nicolas-krajcik10.test', - 'magnus53.test', - 'elta48.test', - ] - for (const did of mutes) { - await agent.api.app.bsky.graph.muteActor( - { actor: did }, - { headers: sc.getHeaders(silas), encoding: 'application/json' }, - ) - } - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches mutes for the logged-in user.', async () => { - const { data: view } = await agent.api.app.bsky.graph.getMutes( - {}, - { headers: sc.getHeaders(silas) }, - ) - expect(forSnapshot(view.mutes)).toMatchSnapshot() - }) - - it('paginates.', async () => { - const results = (results) => results.flatMap((res) => res.mutes) - const paginator = async (cursor?: string) => { - const { data: view } = await agent.api.app.bsky.graph.getMutes( - { cursor, limit: 2 }, - { headers: sc.getHeaders(silas) }, - ) - return view - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.mutes.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.graph.getMutes( - {}, - { headers: sc.getHeaders(silas) }, - ) - - expect(full.data.mutes.length).toEqual(6) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('removes mute.', async () => { - const { data: initial } = await agent.api.app.bsky.graph.getMutes( - {}, - { headers: sc.getHeaders(silas) }, - ) - expect(initial.mutes.length).toEqual(6) - expect(initial.mutes.map((m) => m.handle)).toContain('elta48.test') - - await agent.api.app.bsky.graph.unmuteActor( - { actor: sc.dids['elta48.test'] }, - { headers: sc.getHeaders(silas), encoding: 'application/json' }, - ) - - const { data: final } = await agent.api.app.bsky.graph.getMutes( - {}, - { headers: sc.getHeaders(silas) }, - ) - expect(final.mutes.length).toEqual(5) - expect(final.mutes.map((m) => m.handle)).not.toContain('elta48.test') - - await agent.api.app.bsky.graph.muteActor( - { actor: sc.dids['elta48.test'] }, - { headers: sc.getHeaders(silas), encoding: 'application/json' }, - ) - }) - - it('does not allow muting self.', async () => { - const promise = agent.api.app.bsky.graph.muteActor( - { actor: silas }, - { headers: sc.getHeaders(silas), encoding: 'application/json' }, - ) - await expect(promise).rejects.toThrow('Cannot mute oneself') - }) -}) diff --git a/packages/pds/tests/views/notifications.test.ts b/packages/pds/tests/views/notifications.test.ts deleted file mode 100644 index 1cc86455126..00000000000 --- a/packages/pds/tests/views/notifications.test.ts +++ /dev/null @@ -1,310 +0,0 @@ -import AtpAgent from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { - runTestServer, - forSnapshot, - CloseFn, - paginateAll, - adminAuth, - TestServerInfo, -} from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { Database } from '../../src' -import { Notification } from '../../src/lexicon/types/app/bsky/notification/listNotifications' - -describe('pds notification views', () => { - let server: TestServerInfo - let agent: AtpAgent - let close: CloseFn - let db: Database - let sc: SeedClient - - // account dids, for convenience - let alice: string - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_notifications', - }) - close = server.close - db = server.ctx.db - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - const sort = (notifs: Notification[]) => { - return notifs.sort((a, b) => { - if (a.indexedAt === b.indexedAt) { - return a.uri > b.uri ? -1 : 1 - } - return a.indexedAt > b.indexedAt ? -a : 1 - }) - } - - it('fetches notification count without a last-seen', async () => { - const notifCountAlice = - await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(alice) }, - ) - - expect(notifCountAlice.data.count).toBe(12) - - const notifCountBob = await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - - expect(notifCountBob.data.count).toBe(4) - }) - - it('generates notifications for all reply ancestors', async () => { - // Add to reply chain, post ancestors: alice -> bob -> alice -> carol. - // Should have added one notification for each of alice and bob. - await sc.reply( - sc.dids.carol, - sc.posts[alice][1].ref, - sc.replies[alice][0].ref, - 'indeed', - ) - await server.processAll() - - const notifCountAlice = - await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(alice) }, - ) - - expect(notifCountAlice.data.count).toBe(13) - - const notifCountBob = await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(sc.dids.bob) }, - ) - - expect(notifCountBob.data.count).toBe(5) - }) - - it('does not give notifs for a deleted subject', async () => { - const root = await sc.post(sc.dids.alice, 'root') - const first = await sc.reply(sc.dids.bob, root.ref, root.ref, 'first') - await sc.deletePost(sc.dids.alice, root.ref.uri) - const second = await sc.reply(sc.dids.carol, root.ref, first.ref, 'second') - - const notifsAlice = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - const hasNotif = notifsAlice.data.notifications.some( - (notif) => notif.uri === second.ref.uriStr, - ) - expect(hasNotif).toBe(false) - - // cleanup - await sc.deletePost(sc.dids.bob, first.ref.uri) - await sc.deletePost(sc.dids.carol, second.ref.uri) - }) - - it('generates notifications for quotes', async () => { - // Dan was quoted by alice - const notifsDan = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(sc.dids.dan) }, - ) - expect(forSnapshot(notifsDan.data)).toMatchSnapshot() - }) - - it('fetches notifications without a last-seen', async () => { - const notifRes = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(alice) }, - ) - - const notifs = sort(notifRes.data.notifications) - expect(notifs.length).toBe(13) - - const readStates = notifs.map((notif) => notif.isRead) - expect(readStates).toEqual(notifs.map(() => false)) - - // @TODO while the exact order of these is not critically important, - // it's odd to see carol's follow after bob's. In the seed they occur in - // the opposite ordering. - expect(forSnapshot(notifs)).toMatchSnapshot() - }) - - it('fetches notifications omitting records by a muted user', async () => { - await agent.api.app.bsky.graph.muteActor( - { actor: sc.dids.carol }, // Replier - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - await agent.api.app.bsky.graph.muteActor( - { actor: sc.dids.dan }, // Mentioner - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - - const notifRes = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(alice) }, - ) - const notifCount = await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(alice) }, - ) - - const notifs = sort(notifRes.data.notifications) - expect(notifs.length).toBe(4) - expect(forSnapshot(notifs)).toMatchSnapshot() - expect(notifCount.data.count).toBe(4) - - // Cleanup - await agent.api.app.bsky.graph.unmuteActor( - { actor: sc.dids.carol }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - await agent.api.app.bsky.graph.unmuteActor( - { actor: sc.dids.dan }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - }) - - it('fetches notifications omitting mentions and replies for taken-down posts', async () => { - const postRef1 = sc.replies[sc.dids.carol][0].ref // Reply - const postRef2 = sc.posts[sc.dids.dan][1].ref // Mention - const actionResults = await Promise.all( - [postRef1, postRef2].map((postRef) => - agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: postRef.uriStr, - cid: postRef.cidStr, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - - const notifRes = await agent.api.app.bsky.notification.listNotifications( - {}, - { headers: sc.getHeaders(alice) }, - ) - const notifCount = await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(alice) }, - ) - - const notifs = sort(notifRes.data.notifications) - expect(notifs.length).toBe(11) - expect(forSnapshot(notifs)).toMatchSnapshot() - expect(notifCount.data.count).toBe(11) - - // Cleanup - await Promise.all( - actionResults.map((result) => - agent.api.com.atproto.admin.reverseModerationAction( - { - id: result.data.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - }) - - it('paginates', async () => { - const results = (results) => - sort(results.flatMap((res) => res.notifications)) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.notification.listNotifications( - { - cursor, - limit: 6, - }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.notifications.length).toBeLessThanOrEqual(6), - ) - - const full = await agent.api.app.bsky.notification.listNotifications( - {}, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(full.data.notifications.length).toEqual(13) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('updates notifications last seen', async () => { - const full = await agent.api.app.bsky.notification.listNotifications( - {}, - { - headers: sc.getHeaders(alice), - }, - ) - - // Need to look-up createdAt time as a cursor since it's not in the method's output - const beforeNotif = await db.db - .selectFrom('user_notification') - .selectAll() - .where('recordUri', '=', full.data.notifications[3].uri) - .executeTakeFirstOrThrow() - - await agent.api.app.bsky.notification.updateSeen( - { seenAt: beforeNotif.indexedAt }, - { encoding: 'application/json', headers: sc.getHeaders(alice) }, - ) - }) - - it('fetches notification count with a last-seen', async () => { - const notifCount = await agent.api.app.bsky.notification.getUnreadCount( - {}, - { headers: sc.getHeaders(alice) }, - ) - - expect(notifCount.data.count).toBe(3) - }) - - it('fetches notifications with a last-seen', async () => { - const notifRes = await agent.api.app.bsky.notification.listNotifications( - {}, - { - headers: sc.getHeaders(alice), - }, - ) - - const notifs = sort(notifRes.data.notifications) - expect(notifs.length).toBe(13) - - const readStates = notifs.map((notif) => notif.isRead) - expect(readStates).toEqual(notifs.map((_, i) => i >= 3)) - - expect(forSnapshot(notifs)).toMatchSnapshot() - }) -}) diff --git a/packages/pds/tests/views/popular.test.ts b/packages/pds/tests/views/popular.test.ts deleted file mode 100644 index ca21ee31f4f..00000000000 --- a/packages/pds/tests/views/popular.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import AtpAgent from '@atproto/api' -import { runTestServer, CloseFn, TestServerInfo } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('popular views', () => { - let server: TestServerInfo - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - - const account = { - email: 'blah@test.com', - password: 'blh-pass', - } - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_popular', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - - await sc.createAccount('eve', { - ...account, - email: 'eve@test.com', - handle: 'eve.test', - password: 'eve-pass', - }) - await sc.createAccount('frank', { - ...account, - email: 'frank@test.com', - handle: 'frank.test', - password: 'frank-pass', - }) - await sc.createAccount('george', { - ...account, - email: 'george@test.com', - handle: 'george.test', - password: 'george-pass', - }) - await sc.createAccount('helen', { - ...account, - email: 'helen@test.com', - handle: 'helen.test', - password: 'helen-pass', - }) - - alice = sc.dids.alice - bob = sc.dids.bob - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('returns well liked posts', async () => { - const img = await sc.uploadFile( - alice, - 'tests/image/fixtures/key-landscape-small.jpg', - 'image/jpeg', - ) - const one = await sc.post(alice, 'first post', undefined, [img]) - const two = await sc.post(bob, 'bobby boi') - const three = await sc.reply(bob, one.ref, one.ref, 'reply') - - for (let i = 0; i < 12; i++) { - const name = `user${i}` - await sc.createAccount(name, { - handle: `user${i}.test`, - email: `user${i}@test.com`, - password: 'password', - }) - await sc.like(sc.dids[name], one.ref) - await sc.like(sc.dids[name], two.ref) - await sc.like(sc.dids[name], three.ref) - } - await server.processAll() - - const res = await agent.api.app.bsky.unspecced.getPopular( - {}, - { headers: sc.getHeaders(alice) }, - ) - const feedUris = res.data.feed.map((i) => i.post.uri).sort() - const expected = [one.ref.uriStr, two.ref.uriStr].sort() - expect(feedUris).toEqual(expected) - }) - - it('does not return muted posts', async () => { - await agent.api.app.bsky.graph.muteActor( - { actor: bob }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - - const res = await agent.api.app.bsky.unspecced.getPopular( - {}, - { headers: sc.getHeaders(alice) }, - ) - expect(res.data.feed.length).toBe(1) - const dids = res.data.feed.map((post) => post.post.author.did) - expect(dids.includes(bob)).toBe(false) - }) -}) diff --git a/packages/pds/tests/views/posts.test.ts b/packages/pds/tests/views/posts.test.ts deleted file mode 100644 index f6aa0551b07..00000000000 --- a/packages/pds/tests/views/posts.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import AtpAgent from '@atproto/api' -import { runTestServer, forSnapshot, TestServerInfo } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds posts views', () => { - let server: TestServerInfo - let agent: AtpAgent - let sc: SeedClient - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_posts', - }) - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - await server.processAll() - }) - - afterAll(async () => { - await server.close() - }) - - it('fetches posts', async () => { - const uris = [ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.alice][1].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - sc.posts[sc.dids.carol][0].ref.uriStr, - sc.posts[sc.dids.dan][1].ref.uriStr, - sc.replies[sc.dids.alice][0].ref.uriStr, - ] - const posts = await agent.api.app.bsky.feed.getPosts( - { uris }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - - expect(posts.data.posts.length).toBe(uris.length) - expect(forSnapshot(posts.data.posts)).toMatchSnapshot() - }) - - it('handles repeat uris', async () => { - const uris = [ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - ] - - const posts = await agent.api.app.bsky.feed.getPosts( - { uris }, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - - expect(posts.data.posts.length).toBe(2) - const receivedUris = posts.data.posts.map((p) => p.uri).sort() - const expected = [ - sc.posts[sc.dids.alice][0].ref.uriStr, - sc.posts[sc.dids.bob][0].ref.uriStr, - ].sort() - expect(receivedUris).toEqual(expected) - }) -}) diff --git a/packages/pds/tests/views/profile.test.ts b/packages/pds/tests/views/profile.test.ts deleted file mode 100644 index b1a3e5003a9..00000000000 --- a/packages/pds/tests/views/profile.test.ts +++ /dev/null @@ -1,285 +0,0 @@ -import fs from 'fs/promises' -import AtpAgent from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { ids } from '../../src/lexicon/lexicons' -import { runTestServer, forSnapshot, CloseFn, adminAuth } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds profile views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let dan: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_profile', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - dan = sc.dids.dan - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches own profile', async () => { - const aliceForAlice = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceForAlice.data)).toMatchSnapshot() - }) - - it('reflects self-labels', async () => { - const aliceForBob = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - - const labels = aliceForBob.data.labels - ?.filter((label) => label.src === alice) - .map((label) => label.val) - .sort() - - expect(labels).toEqual(['self-label-a', 'self-label-b']) - }) - - it("fetches other's profile, with a follow", async () => { - const aliceForBob = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(aliceForBob.data)).toMatchSnapshot() - }) - - it("fetches other's profile, without a follow", async () => { - const danForBob = await agent.api.app.bsky.actor.getProfile( - { actor: dan }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(danForBob.data)).toMatchSnapshot() - }) - - it('fetches multiple profiles', async () => { - const { - data: { profiles }, - } = await agent.api.app.bsky.actor.getProfiles( - { - actors: [ - alice, - 'bob.test', - 'did:example:missing', - 'carol.test', - dan, - 'missing.test', - ], - }, - { headers: sc.getHeaders(bob) }, - ) - - expect(profiles.map((p) => p.handle)).toEqual([ - 'alice.test', - 'bob.test', - 'carol.test', - 'dan.test', - ]) - - expect(forSnapshot(profiles)).toMatchSnapshot() - }) - - it('updates profile', async () => { - await updateProfile(agent, alice, { - displayName: 'ali', - description: 'new descript', - avatar: sc.profiles[alice].avatar, - }) - - const aliceForAlice = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceForAlice.data)).toMatchSnapshot() - }) - - it('handles avatars & banners', async () => { - const avatarImg = await fs.readFile( - 'tests/image/fixtures/key-portrait-small.jpg', - ) - const bannerImg = await fs.readFile( - 'tests/image/fixtures/key-landscape-small.jpg', - ) - const avatarRes = await agent.api.com.atproto.repo.uploadBlob(avatarImg, { - headers: sc.getHeaders(alice), - encoding: 'image/jpeg', - }) - const bannerRes = await agent.api.com.atproto.repo.uploadBlob(bannerImg, { - headers: sc.getHeaders(alice), - encoding: 'image/jpeg', - }) - - await updateProfile(agent, alice, { - displayName: 'ali', - description: 'new descript', - avatar: avatarRes.data.blob, - banner: bannerRes.data.blob, - }) - - const aliceForAlice = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceForAlice.data)).toMatchSnapshot() - }) - - it('handles unsetting profile fields', async () => { - await updateProfile(agent, alice, {}) - - const aliceForAlice = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(alice) }, - ) - - expect(aliceForAlice.data.displayName).toBeUndefined() - expect(aliceForAlice.data.description).toBeUndefined() - expect(aliceForAlice.data.avatar).toBeUndefined() - expect(aliceForAlice.data.banner).toBeUndefined() - expect(forSnapshot(aliceForAlice.data)).toMatchSnapshot() - }) - - it('creates new profile', async () => { - await updateProfile(agent, dan, { displayName: 'danny boy' }) - - const danForDan = await agent.api.app.bsky.actor.getProfile( - { actor: dan }, - { headers: sc.getHeaders(dan) }, - ) - - expect(forSnapshot(danForDan.data)).toMatchSnapshot() - }) - - it('fetches profile by handle', async () => { - const byDid = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { - headers: sc.getHeaders(bob), - }, - ) - - const byHandle = await agent.api.app.bsky.actor.getProfile( - { actor: sc.accounts[alice].handle }, - { headers: sc.getHeaders(bob) }, - ) - - expect(byHandle.data).toEqual(byDid.data) - }) - - it('blocked by actor takedown', async () => { - const { data: action } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: alice, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - const promise = agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - - await expect(promise).rejects.toThrow('Account has been taken down') - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: action.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('includes muted status.', async () => { - const { data: initial } = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - - expect(initial.viewer?.muted).toEqual(false) - - await agent.api.app.bsky.graph.muteActor( - { actor: alice }, - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - const { data: muted } = await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(bob) }, - ) - - expect(muted.viewer?.muted).toEqual(true) - - const { data: fromBobUnrelated } = - await agent.api.app.bsky.actor.getProfile( - { actor: dan }, - { headers: sc.getHeaders(bob) }, - ) - const { data: toAliceUnrelated } = - await agent.api.app.bsky.actor.getProfile( - { actor: alice }, - { headers: sc.getHeaders(dan) }, - ) - - expect(fromBobUnrelated.viewer?.muted).toEqual(false) - expect(toAliceUnrelated.viewer?.muted).toEqual(false) - - await agent.api.app.bsky.graph.unmuteActor( - { actor: alice }, - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - }) - - async function updateProfile( - agent: AtpAgent, - did: string, - record: Record, - ) { - return await agent.api.com.atproto.repo.putRecord( - { - repo: did, - collection: ids.AppBskyActorProfile, - rkey: 'self', - record, - }, - { headers: sc.getHeaders(did), encoding: 'application/json' }, - ) - } -}) diff --git a/packages/pds/tests/views/reposts.test.ts b/packages/pds/tests/views/reposts.test.ts deleted file mode 100644 index 1c61215e3e5..00000000000 --- a/packages/pds/tests/views/reposts.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import AtpAgent from '@atproto/api' -import { runTestServer, forSnapshot, CloseFn, paginateAll } from '../_util' -import { SeedClient } from '../seeds/client' -import repostsSeed from '../seeds/reposts' - -describe('pds repost views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_reposts', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await repostsSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches reposted-by for a post', async () => { - const view = await agent.api.app.bsky.feed.getRepostedBy( - { uri: sc.posts[alice][2].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - expect(view.data.uri).toEqual(sc.posts[sc.dids.alice][2].ref.uriStr) - expect(forSnapshot(view.data.repostedBy)).toMatchSnapshot() - }) - - it('fetches reposted-by for a reply', async () => { - const view = await agent.api.app.bsky.feed.getRepostedBy( - { uri: sc.replies[bob][0].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - expect(view.data.uri).toEqual(sc.replies[sc.dids.bob][0].ref.uriStr) - expect(forSnapshot(view.data.repostedBy)).toMatchSnapshot() - }) - - it('paginates', async () => { - const results = (results) => results.flatMap((res) => res.repostedBy) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getRepostedBy( - { - uri: sc.posts[alice][2].ref.uriStr, - cursor, - limit: 2, - }, - { headers: sc.getHeaders(alice) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.repostedBy.length).toBeLessThanOrEqual(2), - ) - - const full = await agent.api.app.bsky.feed.getRepostedBy( - { uri: sc.posts[alice][2].ref.uriStr }, - { headers: sc.getHeaders(alice) }, - ) - - expect(full.data.repostedBy.length).toEqual(4) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) -}) diff --git a/packages/pds/tests/views/suggestions.test.ts b/packages/pds/tests/views/suggestions.test.ts deleted file mode 100644 index 4bec6dc3dd2..00000000000 --- a/packages/pds/tests/views/suggestions.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import AtpAgent from '@atproto/api' -import { runTestServer, CloseFn } from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds user search views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_suggestions', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - await server.processAll() - - const suggestions = [ - { did: sc.dids.bob, order: 1 }, - { did: sc.dids.carol, order: 2 }, - { did: sc.dids.dan, order: 3 }, - ] - await server.ctx.db.db - .insertInto('suggested_follow') - .values(suggestions) - .execute() - }) - - afterAll(async () => { - await close() - }) - - it('actor suggestion gives users', async () => { - const result = await agent.api.app.bsky.actor.getSuggestions( - {}, - { headers: sc.getHeaders(sc.dids.carol) }, - ) - - // does not include carol, because she is requesting - expect(result.data.actors.length).toBe(2) - expect(result.data.actors[0].handle).toEqual('bob.test') - expect(result.data.actors[0].displayName).toEqual('bobby') - expect(result.data.actors[1].handle).toEqual('dan.test') - expect(result.data.actors[1].displayName).toBeUndefined() - }) - - it('does not suggest followed users', async () => { - const result = await agent.api.app.bsky.actor.getSuggestions( - {}, - { headers: sc.getHeaders(sc.dids.alice) }, - ) - - // alice follows everyone - expect(result.data.actors.length).toBe(0) - }) - - it('paginates', async () => { - const result1 = await agent.api.app.bsky.actor.getSuggestions( - { limit: 1 }, - { headers: sc.getHeaders(sc.dids.carol) }, - ) - const result2 = await agent.api.app.bsky.actor.getSuggestions( - { limit: 1, cursor: result1.data.cursor }, - { headers: sc.getHeaders(sc.dids.carol) }, - ) - - expect(result1.data.actors.length).toBe(1) - expect(result1.data.actors[0].handle).toEqual('bob.test') - expect(result2.data.actors.length).toBe(1) - expect(result2.data.actors[0].handle).toEqual('dan.test') - }) -}) diff --git a/packages/pds/tests/views/thread.test.ts b/packages/pds/tests/views/thread.test.ts deleted file mode 100644 index 1efee8b0526..00000000000 --- a/packages/pds/tests/views/thread.test.ts +++ /dev/null @@ -1,456 +0,0 @@ -import assert from 'assert' -import AtpAgent, { AppBskyFeedGetPostThread } from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { isThreadViewPost } from '@atproto/api/src/client/types/app/bsky/feed/defs' -import { - runTestServer, - forSnapshot, - CloseFn, - adminAuth, - TestServerInfo, -} from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' - -describe('pds thread views', () => { - let server: TestServerInfo - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - - beforeAll(async () => { - server = await runTestServer({ - dbPostgresSchema: 'views_thread', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - await server.processAll() - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - }) - - beforeAll(async () => { - // Add a repost of a reply so that we can confirm viewer state in the thread - await sc.repost(bob, sc.replies[alice][0].ref) - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it('fetches deep post thread', async () => { - const thread = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - }) - - it('fetches shallow post thread', async () => { - const thread = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - }) - - it('fetches ancestors', async () => { - const thread = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.replies[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - }) - - it('fetches shallow ancestors', async () => { - const thread = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, parentHeight: 1, uri: sc.replies[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - }) - - it('fails for an unknown post', async () => { - const promise = agent.api.app.bsky.feed.getPostThread( - { uri: 'at://did:example:fake/does.not.exist/self' }, - { headers: sc.getHeaders(bob) }, - ) - - await expect(promise).rejects.toThrow( - AppBskyFeedGetPostThread.NotFoundError, - ) - }) - - it('includes the muted status of post authors.', async () => { - await agent.api.app.bsky.graph.muteActor( - { actor: alice }, - { headers: sc.getHeaders(bob), encoding: 'application/json' }, - ) - const thread = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - - await agent.api.app.bsky.graph.unmuteActor( - { actor: alice }, - { encoding: 'application/json', headers: sc.getHeaders(bob) }, - ) - }) - - it('handles deleted posts correctly', async () => { - const alice = sc.dids.alice - const bob = sc.dids.bob - - const indexes = { - aliceRoot: -1, - bobReply: -1, - aliceReplyReply: -1, - } - - await sc.post(alice, 'Deletion thread') - indexes.aliceRoot = sc.posts[alice].length - 1 - - await sc.reply( - bob, - sc.posts[alice][indexes.aliceRoot].ref, - sc.posts[alice][indexes.aliceRoot].ref, - 'Reply', - ) - indexes.bobReply = sc.replies[bob].length - 1 - await sc.reply( - alice, - sc.posts[alice][indexes.aliceRoot].ref, - sc.replies[bob][indexes.bobReply].ref, - 'Reply reply', - ) - indexes.aliceReplyReply = sc.replies[alice].length - 1 - await server.processAll() - - const thread1 = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][indexes.aliceRoot].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - expect(forSnapshot(thread1.data.thread)).toMatchSnapshot() - - await sc.deletePost(bob, sc.replies[bob][indexes.bobReply].ref.uri) - await server.processAll() - - const thread2 = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][indexes.aliceRoot].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - expect(forSnapshot(thread2.data.thread)).toMatchSnapshot() - - const thread3 = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.replies[alice][indexes.aliceReplyReply].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - expect(forSnapshot(thread3.data.thread)).toMatchSnapshot() - }) - - it('reflects self-labels', async () => { - const { data: thread } = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - assert(isThreadViewPost(thread.thread), 'post does not exist') - const post = thread.thread.post - - const postSelfLabels = post.labels - ?.filter((label) => label.src === alice) - .map((label) => label.val) - - expect(postSelfLabels).toEqual(['self-label']) - - const authorSelfLabels = post.author.labels - ?.filter((label) => label.src === alice) - .map((label) => label.val) - .sort() - - expect(authorSelfLabels).toEqual(['self-label-a', 'self-label-b']) - }) - - it('blocks post by actor takedown', async () => { - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: alice, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - // Same as shallow post thread test, minus alice - const promise = agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - await expect(promise).rejects.toThrow( - AppBskyFeedGetPostThread.NotFoundError, - ) - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('blocks replies by actor takedown', async () => { - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: carol, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - // Same as deep post thread test, minus carol - const thread = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('blocks ancestors by actor takedown', async () => { - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did: bob, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - // Same as ancestor post thread test, minus bob - const thread = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.replies[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('blocks post by record takedown', async () => { - const postRef = sc.posts[alice][1].ref - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: postRef.uriStr, - cid: postRef.cidStr, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - const promise = agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: postRef.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - await expect(promise).rejects.toThrow( - AppBskyFeedGetPostThread.NotFoundError, - ) - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('blocks ancestors by record takedown', async () => { - const threadPreTakedown = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.replies[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - const parent = threadPreTakedown.data.thread.parent?.['post'] - - const { data: modAction } = - await agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: parent.uri, - cid: parent.cid, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - - // Same as ancestor post thread test, minus parent post - const thread = await agent.api.app.bsky.feed.getPostThread( - { depth: 1, uri: sc.replies[alice][0].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - - // Cleanup - await agent.api.com.atproto.admin.reverseModerationAction( - { - id: modAction.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ) - }) - - it('blocks replies by record takedown', async () => { - const threadPreTakedown = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - const post1 = threadPreTakedown.data.thread.replies?.[0].post - const post2 = threadPreTakedown.data.thread.replies?.[1].replies[0].post - - const actionResults = await Promise.all( - [post1, post2].map((post) => - agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: post.uri, - cid: post.cid, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - - // Same as deep post thread test, minus some replies - const thread = await agent.api.app.bsky.feed.getPostThread( - { uri: sc.posts[alice][1].ref.uriStr }, - { headers: sc.getHeaders(bob) }, - ) - - expect(forSnapshot(thread.data.thread)).toMatchSnapshot() - - // Cleanup - await Promise.all( - actionResults.map((result) => - agent.api.com.atproto.admin.reverseModerationAction( - { - id: result.data.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - }) -}) diff --git a/packages/pds/tests/views/timeline.test.ts b/packages/pds/tests/views/timeline.test.ts deleted file mode 100644 index 5dd9ba4a893..00000000000 --- a/packages/pds/tests/views/timeline.test.ts +++ /dev/null @@ -1,310 +0,0 @@ -import assert from 'assert' -import AtpAgent from '@atproto/api' -import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs' -import { FeedViewPost } from '../../src/lexicon/types/app/bsky/feed/defs' -import { - runTestServer, - forSnapshot, - CloseFn, - getOriginator, - paginateAll, - adminAuth, -} from '../_util' -import { SeedClient } from '../seeds/client' -import basicSeed from '../seeds/basic' -import { FeedAlgorithm } from '../../src/app-view/api/app/bsky/util/feed' - -describe('timeline views', () => { - let agent: AtpAgent - let close: CloseFn - let sc: SeedClient - - // account dids, for convenience - let alice: string - let bob: string - let carol: string - let dan: string - - beforeAll(async () => { - const server = await runTestServer({ - dbPostgresSchema: 'views_home_feed', - }) - close = server.close - agent = new AtpAgent({ service: server.url }) - sc = new SeedClient(agent) - await basicSeed(sc) - alice = sc.dids.alice - bob = sc.dids.bob - carol = sc.dids.carol - dan = sc.dids.dan - // Label posts as "kind" to check labels on embed views - const labelPostA = sc.posts[bob][0].ref - const labelPostB = sc.posts[carol][0].ref - await server.ctx.services.appView - .label(server.ctx.db) - .formatAndCreate( - server.ctx.cfg.labelerDid, - labelPostA.uriStr, - labelPostA.cidStr, - { create: ['kind'] }, - ) - await server.ctx.services.appView - .label(server.ctx.db) - .formatAndCreate( - server.ctx.cfg.labelerDid, - labelPostB.uriStr, - labelPostB.cidStr, - { create: ['kind'] }, - ) - await server.processAll() - }) - - afterAll(async () => { - await close() - }) - - it("fetches authenticated user's home feed w/ reverse-chronological algorithm", async () => { - const expectOriginatorFollowedBy = (did) => (item: FeedViewPost) => { - const originator = getOriginator(item) - // The user expects to see posts & reposts from themselves and follows - if (did !== originator) { - expect(sc.follows[did]).toHaveProperty(originator) - } - } - - const aliceTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { - headers: sc.getHeaders(alice), - }, - ) - - expect(forSnapshot(aliceTL.data.feed)).toMatchSnapshot() - aliceTL.data.feed.forEach(expectOriginatorFollowedBy(alice)) - - const bobTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { - headers: sc.getHeaders(bob), - }, - ) - - expect(forSnapshot(bobTL.data.feed)).toMatchSnapshot() - bobTL.data.feed.forEach(expectOriginatorFollowedBy(bob)) - - const carolTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { - headers: sc.getHeaders(carol), - }, - ) - - expect(forSnapshot(carolTL.data.feed)).toMatchSnapshot() - carolTL.data.feed.forEach(expectOriginatorFollowedBy(carol)) - - const danTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { - headers: sc.getHeaders(dan), - }, - ) - - expect(forSnapshot(danTL.data.feed)).toMatchSnapshot() - danTL.data.feed.forEach(expectOriginatorFollowedBy(dan)) - }) - - it("fetches authenticated user's home feed w/ default algorithm", async () => { - const defaultTL = await agent.api.app.bsky.feed.getTimeline( - {}, - { - headers: sc.getHeaders(alice), - }, - ) - const reverseChronologicalTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { - headers: sc.getHeaders(alice), - }, - ) - expect(defaultTL.data.feed).toEqual(reverseChronologicalTL.data.feed) - }) - - it('omits posts and reposts of muted authors.', async () => { - await agent.api.app.bsky.graph.muteActor( - { actor: bob }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - await agent.api.app.bsky.graph.muteActor( - { actor: carol }, - { headers: sc.getHeaders(alice), encoding: 'application/json' }, - ) - - const aliceTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceTL.data.feed)).toMatchSnapshot() - - // Cleanup - await agent.api.app.bsky.graph.unmuteActor( - { actor: bob }, - { encoding: 'application/json', headers: sc.getHeaders(alice) }, - ) - await agent.api.app.bsky.graph.unmuteActor( - { actor: carol }, - { encoding: 'application/json', headers: sc.getHeaders(alice) }, - ) - }) - - it('paginates reverse-chronological feed', async () => { - const results = (results) => results.flatMap((res) => res.feed) - const paginator = async (cursor?: string) => { - const res = await agent.api.app.bsky.feed.getTimeline( - { - algorithm: FeedAlgorithm.ReverseChronological, - cursor, - limit: 4, - }, - { headers: sc.getHeaders(carol) }, - ) - return res.data - } - - const paginatedAll = await paginateAll(paginator) - paginatedAll.forEach((res) => - expect(res.feed.length).toBeLessThanOrEqual(4), - ) - - const full = await agent.api.app.bsky.feed.getTimeline( - { - algorithm: FeedAlgorithm.ReverseChronological, - }, - { headers: sc.getHeaders(carol) }, - ) - - expect(full.data.feed.length).toEqual(7) - expect(results(paginatedAll)).toEqual(results([full.data])) - }) - - it('reflects self-labels', async () => { - const carolTL = await agent.api.app.bsky.feed.getTimeline( - {}, - { headers: sc.getHeaders(carol) }, - ) - - const alicePost = carolTL.data.feed.find( - ({ post }) => post.uri === sc.posts[alice][0].ref.uriStr, - )?.post - - assert(alicePost, 'post does not exist') - - const postSelfLabels = alicePost.labels - ?.filter((label) => label.src === alice) - .map((label) => label.val) - - expect(postSelfLabels).toEqual(['self-label']) - - const authorSelfLabels = alicePost.author.labels - ?.filter((label) => label.src === alice) - .map((label) => label.val) - .sort() - - expect(authorSelfLabels).toEqual(['self-label-a', 'self-label-b']) - }) - - it('blocks posts, reposts, replies by actor takedown', async () => { - const actionResults = await Promise.all( - [bob, carol].map((did) => - agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.admin.defs#repoRef', - did, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - - const aliceTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceTL.data.feed)).toMatchSnapshot() - - // Cleanup - await Promise.all( - actionResults.map((result) => - agent.api.com.atproto.admin.reverseModerationAction( - { - id: result.data.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - }) - - it('blocks posts, reposts, replies by record takedown.', async () => { - const postRef1 = sc.posts[dan][1].ref // Repost - const postRef2 = sc.replies[bob][0].ref // Post and reply parent - const actionResults = await Promise.all( - [postRef1, postRef2].map((postRef) => - agent.api.com.atproto.admin.takeModerationAction( - { - action: TAKEDOWN, - subject: { - $type: 'com.atproto.repo.strongRef', - uri: postRef.uriStr, - cid: postRef.cidStr, - }, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - - const aliceTL = await agent.api.app.bsky.feed.getTimeline( - { algorithm: FeedAlgorithm.ReverseChronological }, - { headers: sc.getHeaders(alice) }, - ) - - expect(forSnapshot(aliceTL.data.feed)).toMatchSnapshot() - - // Cleanup - await Promise.all( - actionResults.map((result) => - agent.api.com.atproto.admin.reverseModerationAction( - { - id: result.data.id, - createdBy: 'did:example:admin', - reason: 'Y', - }, - { - encoding: 'application/json', - headers: { authorization: adminAuth() }, - }, - ), - ), - ) - }) -}) diff --git a/services/pds/index.js b/services/pds/index.js index 5c4d8e924a7..4be4833e942 100644 --- a/services/pds/index.js +++ b/services/pds/index.js @@ -12,17 +12,12 @@ require('dd-trace') // Only works with commonjs // Tracer code above must come before anything else const path = require('path') -const { - KmsKeypair, - S3BlobStore, - CloudfrontInvalidator, -} = require('@atproto/aws') +const { KmsKeypair, S3BlobStore } = require('@atproto/aws') const { Database, ServerConfig, PDS, ViewMaintainer, - makeAlgos, PeriodicModerationActionReversal, } = require('@atproto/pds') const { Secp256k1Keypair } = require('@atproto/crypto') @@ -68,19 +63,12 @@ const main = async () => { password: env.smtpPassword, }), }) - const cfInvalidator = new CloudfrontInvalidator({ - distributionId: env.cfDistributionId, - pathPrefix: cfg.imgUriEndpoint && new URL(cfg.imgUriEndpoint).pathname, - }) - const algos = env.feedPublisherDid ? makeAlgos(env.feedPublisherDid) : {} const pds = PDS.create({ db, blobstore: s3Blobstore, repoSigningKey, plcRotationKey, config: cfg, - imgInvalidator: cfInvalidator, - algos, }) const viewMaintainer = new ViewMaintainer(migrateDb) const viewMaintainerRunning = viewMaintainer.run() @@ -151,8 +139,6 @@ const getEnv = () => ({ smtpUsername: process.env.SMTP_USERNAME, smtpPassword: process.env.SMTP_PASSWORD, s3Bucket: process.env.S3_BUCKET_NAME, - cfDistributionId: process.env.CF_DISTRIBUTION_ID, - feedPublisherDid: process.env.FEED_PUBLISHER_DID, }) const maintainXrpcResource = (span, req) => {