···2 class Feed
3 def get_posts(params, context)
4 p context.user
5- { posts: ["at://did:plc:brka7yc4gssxdquiwpii22pr/app.bsky.feed.post/3mckyk6xwhc2y"] }
6 end
78- def display_name
9- "Post Roulette"
10- end
1112- def description
13- "This is my testing feed for now"
14- end
15 end
16-end
···2 class Feed
3 def get_posts(params, context)
4 p context.user
5+ {posts: ["at://did:plc:brka7yc4gssxdquiwpii22pr/app.bsky.feed.post/3mckyk6xwhc2y"]}
6 end
78+ def display_name = "Post Roulette"
00910+ def description = "This is my testing feed for now"
0011 end
12+end
+5-5
lib/firehose/firehose.rb
···1-require 'skyfall'
2-require 'redis'
034module PostRouletteFeed
05 class Firehose
6 def initialize redis_url
7 @sky = Skyfall::Firehose.new("bsky.network", :subscribe_repos)
···1011 def run
12 redis = Redis.new(url: @redis_url)
13-14 @sky.on_message do |msg|
15- if redis.exists? "watching:#{msg.did}"
16 p "watching", msg
17 end
18 end
···20 end
21 end
22end
23-
···1+require "skyfall"
2+require "redis"
3+require_relative "../shared/redis"
45module PostRouletteFeed
6+ using PostRouletteFeedRedis
7 class Firehose
8 def initialize redis_url
9 @sky = Skyfall::Firehose.new("bsky.network", :subscribe_repos)
···1213 def run
14 redis = Redis.new(url: @redis_url)
015 @sky.on_message do |msg|
16+ if redis.watching? msg.did
17 p "watching", msg
18 end
19 end
···21 end
22 end
23end
0
+19
lib/shared/redis.rb
···0000000000000000000
···1+require "redis"
2+3+module PostRouletteFeedRedis
4+ refine Redis do
5+ def watching?(did)
6+ exists? watching_did_key(did)
7+ end
8+9+ def watch(did)
10+ set watching_did_key(did), true
11+ end
12+13+ private
14+15+ def watching_did_key(did)
16+ "watching:#{did}"
17+ end
18+ end
19+end
+38-8
lib/workers/followgraphseeder.rb
···1-require 'sidekiq'
2-require 'minisky'
0034module PostRouletteFeed
5 class FollowGraphSeeder
6 include Sidekiq::Worker
78- def perform(did)
9- atproto = Minisky.new('public.api.bsky.app', nil)
00000001011 dids = []
12 cursor = nil
1314- while true do
15- json = atproto.get_request('app.bsky.graph.getFollows', {
16- actor: did,
17 limit: 100,
18 cursor: cursor
19 })
020 cursor = json["cursor"]
21 break if cursor.nil?
22 end
0000000000000000000023 p "done"
24 end
25 end
26-end
···1+require "sidekiq"
2+require "minisky"
3+require "sequel"
4+require_relative "../shared/redis"
56module PostRouletteFeed
7 class FollowGraphSeeder
8 include Sidekiq::Worker
910+ using PostRouletteFeedRedis
11+12+ def initialize
13+ @redis_url = ENV.fetch("REDIS_URL")
14+ @database_url = ENV.fetch("DATABASE_URL")
15+ end
16+17+ def perform(follower_did)
18+ atproto = Minisky.new("public.api.bsky.app", nil)
1920 dids = []
21 cursor = nil
2223+ loop do
24+ json = atproto.get_request("app.bsky.graph.getFollows", {
25+ actor: follower_did,
26 limit: 100,
27 cursor: cursor
28 })
29+ dids.concat(Array(json["follows"]).map { |follow| follow["did"] })
30 cursor = json["cursor"]
31 break if cursor.nil?
32 end
33+ # signal to redis that we need to start watching these users
34+ redis = Redis.new(url: @redis_url)
35+ dids.each do |did|
36+ redis.watch did
37+ end
38+ ## create the users / connections in postgres
39+ db = Sequel.connect(@database_url)
40+ users_dataset = db[:users]
41+ user_relationships_dataset = db[:users_relationships]
42+ # create the user that is viewing the feed
43+ follower_id_rows = users_dataset.insert_conflict(target: :did, update: {}).returning(:id).insert(did: follower_did, is_feed_subscriber: true)
44+ # we add the chain in case the user was already created before, as may be the case
45+ # if someone followed them and used this feed in the past
46+ follower_id_rows.first&.fetch(:id) || users_dataset.where(did: follower_did).get(:id)
47+ # create all of the users that the user is following
48+ followed_users = dids.each { |did| {did: did} }
49+ followed_users_rows = users_dataset.insert_conflict(target: :did, update: {}).returning(:id).multi_insert(followed_users)
50+ # create the relationships that signify the follower is following all these users
51+ user_relationships_dataset.insert_conflict(target: :follower_id, update: {}).multi_insert(followed_users_rows.each { |row| })
52+ p dids.length
53 p "done"
54 end
55 end
56+end