[WIP] Post Roulette feed where it sends you random posts by users you follow, unbiased by post age.
1require "sidekiq"
2require "minisky"
3require "sequel"
4require_relative "../shared/redis"
5
6module PostRouletteFeed
7 class FollowGraphSeeder
8 include Sidekiq::Worker
9
10 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)
19
20 dids = []
21 cursor = nil
22
23 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
56end