this repo has no description
1#!/usr/bin/env bun
2import { AtpAgent } from '@atproto/api'
3
4// Read credentials from .env
5const username = process.env.BSKY_USERNAME
6const password = process.env.BSKY_PASSWORD
7
8if (!username || !password) {
9 console.error('Please provide BSKY_USERNAME and BSKY_PASSWORD in .env file')
10 process.exit(1)
11}
12
13const agent = new AtpAgent({ service: 'https://bsky.social' })
14
15console.log('Logging in...')
16await agent.login({
17 identifier: username,
18 password: password
19})
20
21console.log('Fetching timeline...\n')
22
23// Get the user's timeline
24const timeline = await agent.getTimeline({ limit: 50 })
25
26// Filter posts that mention Chicago or ATProto
27const chicagoPosts = timeline.data.feed.filter(item => {
28 const text = item.post.record?.text?.toLowerCase() || ''
29 return text.includes('chicago') ||
30 text.includes('atproto') ||
31 text.includes('#atprotochicago')
32})
33
34console.log(`Found ${chicagoPosts.length} posts mentioning Chicago/ATProto out of ${timeline.data.feed.length} recent posts:\n`)
35
36if (chicagoPosts.length === 0) {
37 console.log('No matching posts found. Try posting with #ATProtoChicago!')
38} else {
39 chicagoPosts.forEach((item, index) => {
40 const author = item.post.author.displayName || item.post.author.handle
41 const text = item.post.record?.text || ''
42 const time = new Date(item.post.record?.createdAt).toLocaleString()
43
44 console.log(`${index + 1}. ${author} (${time})`)
45 console.log(` ${text.substring(0, 100)}${text.length > 100 ? '...' : ''}`)
46 console.log(` Likes: ${item.post.likeCount || 0}, Reposts: ${item.post.repostCount || 0}`)
47 console.log('')
48 })
49}
50
51// Bonus: Show posts with the most engagement
52console.log('\n📊 Bonus: Top 5 posts by engagement:')
53console.log('=====================================')
54
55const sortedByEngagement = timeline.data.feed
56 .sort((a, b) => {
57 const aEngagement = (a.post.likeCount || 0) + (a.post.repostCount || 0) * 2
58 const bEngagement = (b.post.likeCount || 0) + (b.post.repostCount || 0) * 2
59 return bEngagement - aEngagement
60 })
61 .slice(0, 5)
62
63sortedByEngagement.forEach((item, index) => {
64 const author = item.post.author.displayName || item.post.author.handle
65 const text = item.post.record?.text || ''
66 const engagement = (item.post.likeCount || 0) + (item.post.repostCount || 0) * 2
67
68 console.log(`${index + 1}. ${author} (score: ${engagement})`)
69 console.log(` ${text.substring(0, 80)}${text.length > 80 ? '...' : ''}`)
70 console.log(` Likes: ${item.post.likeCount || 0}, Reposts: ${item.post.repostCount || 0}`)
71 console.log('')
72})