Template of a custom feed generator service for the Bluesky network in Ruby
at 0.2 2.6 kB view raw
1require 'bundler/setup' 2 3require 'blue_factory/rake' 4require 'sinatra/activerecord' 5require 'sinatra/activerecord/rake' 6 7require_relative 'app/config' 8 9def get_feed 10 if ENV['KEY'].to_s == '' 11 puts "Please specify feed key as KEY=feedname (the part of the feed's at:// URI after the last slash)" 12 exit 1 13 end 14 15 feed_key = ENV['KEY'] 16 feed = BlueFactory.get_feed(feed_key) 17 18 if feed.nil? 19 puts "No feed configured for key '#{feed_key}' - use `BlueFactory.add_feed '#{feed_key}', MyFeed.new`" 20 exit 1 21 end 22 23 feed 24end 25 26desc "Print posts in the feed, starting from the newest ones (limit = N)" 27task :print_feed do 28 feed = get_feed 29 limit = ENV['N'] ? ENV['N'].to_i : 100 30 31 posts = FeedPost.where(feed_id: feed.feed_id).joins(:post).order('feed_posts.time DESC').limit(limit).map(&:post) 32 33 Rainbow.enabled = true 34 35 # this fixes an error when piping a long output to less and then closing without reading it all 36 Signal.trap("SIGPIPE", "SYSTEM_DEFAULT") 37 38 posts.each do |s| 39 puts Rainbow(s.time).bold + ' * ' + Rainbow("https://bsky.app/profile/#{s.repo}/post/#{s.rkey}").darkgray 40 puts 41 puts feed.colored_text(s.text) 42 if s.record['embed'] 43 json = JSON.generate(s.record['embed']) 44 colored = feed.colored_text(json) 45 puts colored unless colored == json 46 end 47 puts 48 puts "---" 49 puts 50 end 51end 52 53desc "Rescan all posts and rebuild the feed from scratch (DAYS = number of days)" 54task :rebuild_feed do 55 feed = get_feed 56 57 ActiveRecord::Base.transaction do 58 if ENV['ONLY_EXISTING'] 59 posts = FeedPost.where(feed_id: feed.feed_id).joins(:post).map(&:post) 60 else 61 days = ENV['DAYS'] ? ENV['DAYS'].to_i : 7 62 posts = Post.order('time, id').where("time > DATETIME('now', '-#{days} day')") 63 end 64 65 if ENV['APPEND_ONLY'] 66 current_post_ids = FeedPost.where(feed_id: feed.feed_id).pluck('post_id') 67 else 68 puts "Cleaning up feed..." 69 FeedPost.where(feed_id: feed.feed_id).delete_all 70 current_post_ids = [] 71 end 72 73 total = posts.count 74 75 offset = 0 76 page = 100000 77 78 while offset < total 79 batch = posts.is_a?(Array) ? posts[offset...(offset+page)] : posts.limit(page).offset(offset).to_a 80 81 batch.each_with_index do |post, i| 82 print "Processing posts... [#{offset + i + 1}/#{total}]\r" 83 $stdout.flush 84 85 if !current_post_ids.include?(post.id) && feed.post_matches?(post) 86 FeedPost.create!(feed_id: feed.feed_id, post: post, time: post.time) 87 end 88 end 89 90 offset += page 91 end 92 end 93 94 puts "Processing posts... Done." + " " * 30 95end