See the best posts from any Bluesky account
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Rename feed rkeys to 1k-favs / 10k-favs and update display strings

Display names: "favs.blue 1000 ❤️s" and "favs.blue 10,000 ❤️s"
Descriptions reference https://favs.blue.

https://claude.ai/code/session_01NJ15XWB5biJMu4e3zVHdC7

Claude f0249659 bf35f0d1

+30 -30
+8 -8
app/services/feed_generator.ts
··· 5 5 /** 6 6 * Feed-generator service. Two hardcoded feeds: 7 7 * 8 - * top-1k — posts that have crossed 1,000 likes 9 - * top-10k — posts that have crossed 10,000 likes 8 + * 1k-favs — posts that have crossed 1,000 likes 9 + * 10k-favs — posts that have crossed 10,000 likes 10 10 * 11 11 * Ordering is by the time a post *first crossed* the threshold, newest first. 12 12 * Posts are never removed from a feed if their like count later drops. ··· 25 25 26 26 export const FEEDS: readonly FeedDefinition[] = [ 27 27 { 28 - rkey: 'top-1k', 28 + rkey: '1k-favs', 29 29 threshold: 1000, 30 - displayName: 'Past 1k likes', 31 - description: 'Posts as they cross 1,000 likes, newest-crossing first. Powered by favs.blue.', 30 + displayName: 'favs.blue 1000 ❤️s', 31 + description: 'All bluesky posts with over 1000 likes, powered by https://favs.blue', 32 32 }, 33 33 { 34 - rkey: 'top-10k', 34 + rkey: '10k-favs', 35 35 threshold: 10_000, 36 - displayName: 'Past 10k likes', 37 - description: 'Posts as they cross 10,000 likes, newest-crossing first. Powered by favs.blue.', 36 + displayName: 'favs.blue 10,000 ❤️s', 37 + description: 'All bluesky posts with over 10,000 likes, powered by https://favs.blue', 38 38 }, 39 39 ] as const 40 40
+2 -2
commands/feeds_publish.ts
··· 7 7 * Ace command: `node ace feeds:publish --handle <handle> --password <app-password>` 8 8 * 9 9 * Publishes `app.bsky.feed.generator` records on an atproto account's PDS for 10 - * each configured feed (top-1k, top-10k). This is a one-shot bootstrap step 10 + * each configured feed (1k-favs, 10k-favs). This is a one-shot bootstrap step 11 11 * that makes the feeds discoverable in Bluesky clients. 12 12 * 13 13 * Flags: ··· 28 28 */ 29 29 export default class FeedsPublish extends BaseCommand { 30 30 static commandName = 'feeds:publish' 31 - static description = 'Publish app.bsky.feed.generator records for top-1k and top-10k' 31 + static description = 'Publish app.bsky.feed.generator records for 1k-favs and 10k-favs' 32 32 static options: CommandOptions = { startApp: true } 33 33 34 34 @flags.string({ description: 'Handle of the account that will own the feed records' })
+9 -9
tests/functional/feed_generator.spec.ts
··· 48 48 // describeFeedGenerator 49 49 // --------------------------------------------------------------------- 50 50 51 - test('describeFeedGenerator lists top-1k and top-10k', async ({ client, assert }) => { 51 + test('describeFeedGenerator lists 1k-favs and 10k-favs', async ({ client, assert }) => { 52 52 const response = await client.get('/xrpc/app.bsky.feed.describeFeedGenerator') 53 53 response.assertStatus(200) 54 54 const body = response.body() ··· 56 56 assert.isArray(body.feeds) 57 57 const uris = body.feeds.map((f: { uri: string }) => f.uri).sort() 58 58 assert.deepEqual(uris, [ 59 - `at://${PUBLISHER}/app.bsky.feed.generator/top-10k`, 60 - `at://${PUBLISHER}/app.bsky.feed.generator/top-1k`, 59 + `at://${PUBLISHER}/app.bsky.feed.generator/10k-favs`, 60 + `at://${PUBLISHER}/app.bsky.feed.generator/1k-favs`, 61 61 ]) 62 62 }) 63 63 ··· 100 100 assert.equal(response.body().error, 'UnknownFeed') 101 101 }) 102 102 103 - test('getFeedSkeleton for top-1k returns posts that crossed 1k, newest-crossing first', async ({ 103 + test('getFeedSkeleton for 1k-favs returns posts that crossed 1k, newest-crossing first', async ({ 104 104 client, 105 105 assert, 106 106 }) => { ··· 122 122 }) 123 123 124 124 const response = await client.get( 125 - `/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://${PUBLISHER}/app.bsky.feed.generator/top-1k` 125 + `/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://${PUBLISHER}/app.bsky.feed.generator/1k-favs` 126 126 ) 127 127 response.assertStatus(200) 128 128 const body = response.body() ··· 134 134 ]) 135 135 }) 136 136 137 - test('getFeedSkeleton for top-10k only returns 10k crossings', async ({ client, assert }) => { 137 + test('getFeedSkeleton for 10k-favs only returns 10k crossings', async ({ client, assert }) => { 138 138 await NotifiedThreshold.create({ 139 139 subjectUri: 'at://did:plc:a/app.bsky.feed.post/one-k', 140 140 threshold: 1000, ··· 147 147 }) 148 148 149 149 const response = await client.get( 150 - `/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://${PUBLISHER}/app.bsky.feed.generator/top-10k` 150 + `/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://${PUBLISHER}/app.bsky.feed.generator/10k-favs` 151 151 ) 152 152 response.assertStatus(200) 153 153 const uris = response.body().feed.map((f: { post: string }) => f.post) ··· 165 165 }) 166 166 } 167 167 168 - const feedParam = encodeURIComponent(`at://${PUBLISHER}/app.bsky.feed.generator/top-1k`) 168 + const feedParam = encodeURIComponent(`at://${PUBLISHER}/app.bsky.feed.generator/1k-favs`) 169 169 const first = await client.get(`/xrpc/app.bsky.feed.getFeedSkeleton?feed=${feedParam}&limit=2`) 170 170 first.assertStatus(200) 171 171 const firstBody = first.body() ··· 191 191 client, 192 192 assert, 193 193 }) => { 194 - const feedParam = encodeURIComponent(`at://${PUBLISHER}/app.bsky.feed.generator/top-1k`) 194 + const feedParam = encodeURIComponent(`at://${PUBLISHER}/app.bsky.feed.generator/1k-favs`) 195 195 const tooBig = await client.get( 196 196 `/xrpc/app.bsky.feed.getFeedSkeleton?feed=${feedParam}&limit=9999` 197 197 )
+11 -11
tests/unit/feed_generator.spec.ts
··· 26 26 test.group('feed_generator / config', () => { 27 27 test('exports exactly the two required feeds', ({ assert }) => { 28 28 const rkeys = FEEDS.map((f) => f.rkey).sort() 29 - assert.deepEqual(rkeys, ['top-10k', 'top-1k']) 29 + assert.deepEqual(rkeys, ['10k-favs', '1k-favs']) 30 30 const thresholds = FEEDS.map((f) => f.threshold).sort((a, b) => a - b) 31 31 assert.deepEqual(thresholds, [1000, 10_000]) 32 32 }) ··· 58 58 const original = process.env.FEED_PUBLISHER_DID 59 59 try { 60 60 process.env.FEED_PUBLISHER_DID = 'did:plc:pub' 61 - assert.equal(feedUri('top-1k'), 'at://did:plc:pub/app.bsky.feed.generator/top-1k') 61 + assert.equal(feedUri('1k-favs'), 'at://did:plc:pub/app.bsky.feed.generator/1k-favs') 62 62 63 63 delete process.env.FEED_PUBLISHER_DID 64 - assert.isNull(feedUri('top-1k')) 64 + assert.isNull(feedUri('1k-favs')) 65 65 } finally { 66 66 if (original === undefined) delete process.env.FEED_PUBLISHER_DID 67 67 else process.env.FEED_PUBLISHER_DID = original ··· 73 73 try { 74 74 process.env.FEED_PUBLISHER_DID = PUBLISHER 75 75 assert.equal( 76 - findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/top-1k`)?.threshold, 76 + findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/1k-favs`)?.threshold, 77 77 1000 78 78 ) 79 79 assert.equal( 80 - findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/top-10k`)?.threshold, 80 + findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/10k-favs`)?.threshold, 81 81 10_000 82 82 ) 83 83 // Wrong publisher DID 84 - assert.isNull(findFeedByUri('at://did:plc:someoneelse/app.bsky.feed.generator/top-1k')) 84 + assert.isNull(findFeedByUri('at://did:plc:someoneelse/app.bsky.feed.generator/1k-favs')) 85 85 // Wrong collection 86 - assert.isNull(findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.post/top-1k`)) 86 + assert.isNull(findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.post/1k-favs`)) 87 87 // Unknown rkey 88 - assert.isNull(findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/top-1m`)) 88 + assert.isNull(findFeedByUri(`at://${PUBLISHER}/app.bsky.feed.generator/1m-favs`)) 89 89 // Malformed URI 90 90 assert.isNull(findFeedByUri('not-an-at-uri')) 91 91 } finally { ··· 112 112 test.group('feed_generator / getSkeleton', (group) => { 113 113 group.each.setup(() => testUtils.db().withGlobalTransaction()) 114 114 115 - const feedUri1k = `at://${PUBLISHER}/app.bsky.feed.generator/top-1k` 116 - const feedUri10k = `at://${PUBLISHER}/app.bsky.feed.generator/top-10k` 115 + const feedUri1k = `at://${PUBLISHER}/app.bsky.feed.generator/1k-favs` 116 + const feedUri10k = `at://${PUBLISHER}/app.bsky.feed.generator/10k-favs` 117 117 118 118 group.each.setup(() => { 119 119 const original = process.env.FEED_PUBLISHER_DID ··· 157 157 assert.isUndefined(result.cursor) 158 158 }) 159 159 160 - test('filters by threshold — top-10k excludes 1k-only crossings', async ({ assert }) => { 160 + test('filters by threshold — 10k-favs excludes 1k-only crossings', async ({ assert }) => { 161 161 await NotifiedThreshold.create({ 162 162 subjectUri: 'at://did:plc:a/app.bsky.feed.post/one-k', 163 163 threshold: 1000,