Don't forget to lycansubscribe

extracted import code into models

+2
app/at_uri.rb
··· 7 7 attr_reader :repo, :collection, :rkey 8 8 9 9 def initialize(uri) 10 + uri = uri.to_s 10 11 raise InvalidURIError, "Invalid AT URI: #{uri}" if uri.include?(' ') || !uri.start_with?('at://') 11 12 12 13 parts = uri.split('/') ··· 38 39 end 39 40 40 41 def AT_URI(uri) 42 + return uri if uri.is_a?(AT_URI) 41 43 AT_URI.new(uri) 42 44 end
-18
app/importers/base_importer.rb
··· 43 43 def import_items 44 44 raise NotImplementedError 45 45 end 46 - 47 - def create_item_for_post(uri) 48 - post_uri = AT_URI(uri) 49 - return unless post_uri.is_post? 50 - 51 - post = Post.find_by_at_uri(post_uri) 52 - 53 - if post 54 - yield({ post: post }) 55 - else 56 - item_stub = yield({ post_uri: post_uri }) 57 - 58 - if @item_queue 59 - @item_queue.push(item_stub) 60 - @report&.update(queue: { length: @item_queue.length }) 61 - end 62 - end 63 - end 64 46 end
+4 -9
app/importers/likes_importer.rb
··· 1 1 require 'time' 2 - 3 - require_relative '../at_uri' 4 2 require_relative 'base_importer' 5 3 6 4 class LikesImporter < BaseImporter ··· 20 18 21 19 records.each do |record| 22 20 begin 23 - like_rkey = AT_URI(record['uri']).rkey 24 - next if @user.likes.where(rkey: like_rkey).exists? 21 + like = @user.likes.import_from_record(record['uri'], record['value']) 25 22 26 - like_time = Time.parse(record['value']['createdAt']) 27 - post_uri = record['value']['subject']['uri'] 28 - 29 - create_item_for_post(post_uri) do |args| 30 - @user.likes.create!(args.merge(rkey: like_rkey, time: like_time)) 23 + if like && like.pending? && @item_queue 24 + @item_queue.push(like) 25 + @report&.update(queue: { length: @item_queue.length }) 31 26 end 32 27 rescue StandardError => e 33 28 puts "Error in LikesImporter: #{record['uri']}: #{e}"
+12 -39
app/importers/posts_importer.rb
··· 1 1 require 'time' 2 - 3 - require_relative '../at_uri' 4 2 require_relative 'base_importer' 5 3 6 4 class PostsImporter < BaseImporter ··· 20 18 21 19 records.each do |record| 22 20 begin 23 - if record['value']['embed'] && record['value']['embed']['record'] 24 - save_quote(record) 25 - end 21 + quote = @user.quotes.import_from_record(record['uri'], record['value']) 22 + pin = @user.pins.import_from_record(record['uri'], record['value']) 26 23 27 - if record['value']['reply'] && record['value']['text'].include?('📌') 28 - save_pin(record) 24 + if @item_queue 25 + if quote && quote.pending? 26 + @item_queue.push(quote) 27 + end 28 + 29 + if pin && pin.pending? 30 + @item_queue.push(pin) 31 + end 32 + 33 + @report&.update(queue: { length: @item_queue.length }) 29 34 end 30 35 rescue StandardError => e 31 36 puts "Error in LikesImporter: #{record['uri']}: #{e}" ··· 37 42 38 43 break if !cursor 39 44 break if @time_limit && records.any? { |x| Time.parse(x['value']['createdAt']) < @time_limit } 40 - end 41 - end 42 - 43 - def save_quote(record) 44 - post_rkey = AT_URI(record['uri']).rkey 45 - return if @user.quotes.where(rkey: post_rkey).exists? 46 - 47 - post_time = Time.parse(record['value']['createdAt']) 48 - 49 - quoted_post_uri = case record['value']['embed']['$type'] 50 - when 'app.bsky.embed.record' 51 - record['value']['embed']['record']['uri'] 52 - when 'app.bsky.embed.recordWithMedia' 53 - record['value']['embed']['record']['record']['uri'] 54 - else 55 - return 56 - end 57 - 58 - create_item_for_post(quoted_post_uri) do |args| 59 - @user.quotes.create!(args.merge(rkey: post_rkey, time: post_time, quote_text: record['value']['text'])) 60 - end 61 - end 62 - 63 - def save_pin(record) 64 - post_rkey = AT_URI(record['uri']).rkey 65 - return if @user.pins.where(rkey: post_rkey).exists? 66 - 67 - post_time = Time.parse(record['value']['createdAt']) 68 - parent_post_uri = record['value']['reply']['parent']['uri'] 69 - 70 - create_item_for_post(parent_post_uri) do |args| 71 - @user.pins.create!(args.merge(rkey: post_rkey, time: post_time, pin_text: record['value']['text'])) 72 45 end 73 46 end 74 47 end
+4 -9
app/importers/reposts_importer.rb
··· 1 1 require 'time' 2 - 3 - require_relative '../at_uri' 4 2 require_relative 'base_importer' 5 3 6 4 class RepostsImporter < BaseImporter ··· 20 18 21 19 records.each do |record| 22 20 begin 23 - repost_rkey = AT_URI(record['uri']).rkey 24 - next if @user.reposts.where(rkey: repost_rkey).exists? 21 + repost = @user.reposts.import_from_record(record['uri'], record['value']) 25 22 26 - repost_time = Time.parse(record['value']['createdAt']) 27 - post_uri = record['value']['subject']['uri'] 28 - 29 - create_item_for_post(post_uri) do |args| 30 - @user.reposts.create!(args.merge(rkey: repost_rkey, time: repost_time)) 23 + if repost && repost.pending? && @item_queue 24 + @item_queue.push(repost) 25 + @report&.update(queue: { length: @item_queue.length }) 31 26 end 32 27 rescue StandardError => e 33 28 puts "Error in RepostsImporter: #{record['uri']}: #{e}"
+29
app/models/importable.rb
··· 1 + require 'active_support/concern' 2 + 3 + require_relative '../at_uri' 4 + require_relative 'post' 5 + 6 + module Importable 7 + extend ActiveSupport::Concern 8 + 9 + included do 10 + scope :pending, -> { where(post: nil) } 11 + 12 + def pending? 13 + post_uri != nil 14 + end 15 + 16 + def import_item! 17 + post_uri = AT_URI(self.post_uri) 18 + return nil if !post_uri.is_post? 19 + 20 + if post = Post.find_by_at_uri(post_uri) 21 + self.post = post 22 + self.post_uri = nil 23 + end 24 + 25 + self.save! 26 + self 27 + end 28 + end 29 + end
+12
app/models/like.rb
··· 1 1 require 'active_record' 2 + require 'time' 2 3 4 + require_relative '../at_uri' 3 5 require_relative 'post' 6 + require_relative 'importable' 4 7 require_relative 'searchable' 5 8 require_relative 'user' 6 9 7 10 class Like < ActiveRecord::Base 8 11 include Searchable 12 + include Importable 9 13 10 14 validates_presence_of :time, :rkey 11 15 validates_length_of :rkey, is: 13 ··· 14 18 15 19 belongs_to :user, foreign_key: 'actor_id' 16 20 belongs_to :post, optional: true 21 + 22 + def self.new_from_record(uri, record) 23 + self.new( 24 + rkey: AT_URI(uri).rkey, 25 + time: Time.parse(record['createdAt']), 26 + post_uri: record['subject']['uri'] 27 + ) 28 + end 17 29 end
+16
app/models/pin.rb
··· 1 1 require 'active_record' 2 + require 'time' 2 3 4 + require_relative '../at_uri' 3 5 require_relative 'post' 4 6 require_relative 'searchable' 5 7 require_relative 'user' 6 8 7 9 class Pin < ActiveRecord::Base 8 10 include Searchable 11 + include Importable 12 + 13 + PIN_SIGN = '📌' 9 14 10 15 validates_presence_of :time, :rkey 11 16 validates_length_of :rkey, is: 13 ··· 15 20 16 21 belongs_to :user, foreign_key: 'actor_id' 17 22 belongs_to :post, optional: true 23 + 24 + def self.new_from_record(uri, record) 25 + return nil unless record['reply'] && record['text'].include?(PIN_SIGN) 26 + 27 + self.new( 28 + rkey: AT_URI(uri).rkey, 29 + time: Time.parse(record['createdAt']), 30 + post_uri: record['reply']['parent']['uri'], 31 + pin_text: record['text'] 32 + ) 33 + end 18 34 end
+23
app/models/quote.rb
··· 1 1 require 'active_record' 2 + require 'time' 2 3 4 + require_relative '../at_uri' 3 5 require_relative 'post' 4 6 require_relative 'searchable' 5 7 require_relative 'user' 6 8 7 9 class Quote < ActiveRecord::Base 8 10 include Searchable 11 + include Importable 9 12 10 13 validates_presence_of :time, :rkey 11 14 validates_length_of :rkey, is: 13 ··· 15 18 16 19 belongs_to :user, foreign_key: 'actor_id' 17 20 belongs_to :post, optional: true 21 + 22 + def self.new_from_record(uri, record) 23 + return nil unless record['embed'] 24 + 25 + quoted_post_uri = case record['embed']['$type'] 26 + when 'app.bsky.embed.record' 27 + record['embed']['record']['uri'] 28 + when 'app.bsky.embed.recordWithMedia' 29 + record['embed']['record']['record']['uri'] 30 + else 31 + return nil 32 + end 33 + 34 + self.new( 35 + rkey: AT_URI(uri).rkey, 36 + time: Time.parse(record['createdAt']), 37 + post_uri: quoted_post_uri, 38 + quote_text: record['text'] 39 + ) 40 + end 18 41 end
+11
app/models/repost.rb
··· 1 1 require 'active_record' 2 + require 'time' 2 3 4 + require_relative '../at_uri' 3 5 require_relative 'post' 4 6 require_relative 'searchable' 5 7 require_relative 'user' 6 8 7 9 class Repost < ActiveRecord::Base 8 10 include Searchable 11 + include Importable 9 12 10 13 validates_presence_of :time, :rkey 11 14 validates_length_of :rkey, is: 13 ··· 14 17 15 18 belongs_to :user, foreign_key: 'actor_id' 16 19 belongs_to :post, optional: true 20 + 21 + def self.new_from_record(uri, record) 22 + self.new( 23 + rkey: AT_URI(uri).rkey, 24 + time: Time.parse(record['createdAt']), 25 + post_uri: record['subject']['uri'] 26 + ) 27 + end 17 28 end
-2
app/models/searchable.rb
··· 41 41 ) 42 42 } 43 43 44 - scope :pending, -> { where(post: nil) } 45 - 46 44 def cursor 47 45 "#{self.time.to_f}:#{self.id}" 48 46 end
+36 -4
app/models/user.rb
··· 12 12 validates_length_of :did, maximum: 260 13 13 14 14 has_many :posts 15 - has_many :likes, foreign_key: 'actor_id' 16 - has_many :reposts, foreign_key: 'actor_id' 17 - has_many :quotes, foreign_key: 'actor_id' 18 - has_many :pins, foreign_key: 'actor_id' 19 15 has_many :imports 16 + 17 + has_many :likes, foreign_key: 'actor_id' do 18 + def import_from_record(like_uri, record) 19 + like = self.new_from_record(like_uri, record) 20 + return nil if like.nil? || self.where(rkey: like.rkey).exists? 21 + 22 + like.import_item! 23 + end 24 + end 25 + 26 + has_many :reposts, foreign_key: 'actor_id' do 27 + def import_from_record(repost_uri, record) 28 + repost = self.new_from_record(repost_uri, record) 29 + return nil if repost.nil? || self.where(rkey: repost.rkey).exists? 30 + 31 + repost.import_item! 32 + end 33 + end 34 + 35 + has_many :quotes, foreign_key: 'actor_id' do 36 + def import_from_record(post_uri, record) 37 + quote = self.new_from_record(post_uri, record) 38 + return nil if quote.nil? || self.where(rkey: quote.rkey).exists? 39 + 40 + quote.import_item! 41 + end 42 + end 43 + 44 + has_many :pins, foreign_key: 'actor_id' do 45 + def import_from_record(post_uri, record) 46 + pin = self.new_from_record(post_uri, record) 47 + return nil if pin.nil? || self.where(rkey: pin.rkey).exists? 48 + 49 + pin.import_item! 50 + end 51 + end 20 52 21 53 def all_pending_items 22 54 [:likes, :reposts, :quotes, :pins].map { |x| self.send(x).pending.to_a }.reduce(&:+)