···22 class Feed
33 def get_posts(params, context)
44 p context.user
55- { posts: ["at://did:plc:brka7yc4gssxdquiwpii22pr/app.bsky.feed.post/3mckyk6xwhc2y"] }
55+ {posts: ["at://did:plc:brka7yc4gssxdquiwpii22pr/app.bsky.feed.post/3mckyk6xwhc2y"]}
66 end
7788- def display_name
99- "Post Roulette"
1010- end
88+ def display_name = "Post Roulette"
1191212- def description
1313- "This is my testing feed for now"
1414- end
1010+ def description = "This is my testing feed for now"
1511 end
1616-end1212+end
+5-5
lib/firehose/firehose.rb
···11-require 'skyfall'
22-require 'redis'
11+require "skyfall"
22+require "redis"
33+require_relative "../shared/redis"
3445module PostRouletteFeed
66+ using PostRouletteFeedRedis
57 class Firehose
68 def initialize redis_url
79 @sky = Skyfall::Firehose.new("bsky.network", :subscribe_repos)
···10121113 def run
1214 redis = Redis.new(url: @redis_url)
1313-1415 @sky.on_message do |msg|
1515- if redis.exists? "watching:#{msg.did}"
1616+ if redis.watching? msg.did
1617 p "watching", msg
1718 end
1819 end
···2021 end
2122 end
2223end
2323-
+19
lib/shared/redis.rb
···11+require "redis"
22+33+module PostRouletteFeedRedis
44+ refine Redis do
55+ def watching?(did)
66+ exists? watching_did_key(did)
77+ end
88+99+ def watch(did)
1010+ set watching_did_key(did), true
1111+ end
1212+1313+ private
1414+1515+ def watching_did_key(did)
1616+ "watching:#{did}"
1717+ end
1818+ end
1919+end
+38-8
lib/workers/followgraphseeder.rb
···11-require 'sidekiq'
22-require 'minisky'
11+require "sidekiq"
22+require "minisky"
33+require "sequel"
44+require_relative "../shared/redis"
3546module PostRouletteFeed
57 class FollowGraphSeeder
68 include Sidekiq::Worker
7988- def perform(did)
99- atproto = Minisky.new('public.api.bsky.app', nil)
1010+ using PostRouletteFeedRedis
1111+1212+ def initialize
1313+ @redis_url = ENV.fetch("REDIS_URL")
1414+ @database_url = ENV.fetch("DATABASE_URL")
1515+ end
1616+1717+ def perform(follower_did)
1818+ atproto = Minisky.new("public.api.bsky.app", nil)
10191120 dids = []
1221 cursor = nil
13221414- while true do
1515- json = atproto.get_request('app.bsky.graph.getFollows', {
1616- actor: did,
2323+ loop do
2424+ json = atproto.get_request("app.bsky.graph.getFollows", {
2525+ actor: follower_did,
1726 limit: 100,
1827 cursor: cursor
1928 })
2929+ dids.concat(Array(json["follows"]).map { |follow| follow["did"] })
2030 cursor = json["cursor"]
2131 break if cursor.nil?
2232 end
3333+ # signal to redis that we need to start watching these users
3434+ redis = Redis.new(url: @redis_url)
3535+ dids.each do |did|
3636+ redis.watch did
3737+ end
3838+ ## create the users / connections in postgres
3939+ db = Sequel.connect(@database_url)
4040+ users_dataset = db[:users]
4141+ user_relationships_dataset = db[:users_relationships]
4242+ # create the user that is viewing the feed
4343+ follower_id_rows = users_dataset.insert_conflict(target: :did, update: {}).returning(:id).insert(did: follower_did, is_feed_subscriber: true)
4444+ # we add the chain in case the user was already created before, as may be the case
4545+ # if someone followed them and used this feed in the past
4646+ follower_id_rows.first&.fetch(:id) || users_dataset.where(did: follower_did).get(:id)
4747+ # create all of the users that the user is following
4848+ followed_users = dids.each { |did| {did: did} }
4949+ followed_users_rows = users_dataset.insert_conflict(target: :did, update: {}).returning(:id).multi_insert(followed_users)
5050+ # create the relationships that signify the follower is following all these users
5151+ user_relationships_dataset.insert_conflict(target: :follower_id, update: {}).multi_insert(followed_users_rows.each { |row| })
5252+ p dids.length
2353 p "done"
2454 end
2555 end
2626-end5656+end