151 lines
3.8 KiB
Ruby
151 lines
3.8 KiB
Ruby
# typed: strict
|
|
class Domain::Post::BlueskyPost < Domain::Post
|
|
aux_table :bluesky, allow_redefining: :title
|
|
|
|
belongs_to :first_seen_entry, class_name: "::HttpLogEntry", optional: true
|
|
|
|
belongs_to :quoted_post,
|
|
class_name: "Domain::Post::BlueskyPost",
|
|
optional: true,
|
|
foreign_key: :quote_uri,
|
|
primary_key: :at_uri,
|
|
inverse_of: :quoting_posts
|
|
|
|
has_many :quoting_posts,
|
|
class_name: "Domain::Post::BlueskyPost",
|
|
foreign_key: :quote_uri,
|
|
primary_key: :at_uri,
|
|
inverse_of: :quoted_post
|
|
|
|
belongs_to :replying_to_post,
|
|
class_name: "Domain::Post::BlueskyPost",
|
|
optional: true,
|
|
foreign_key: :reply_to_uri,
|
|
primary_key: :at_uri,
|
|
inverse_of: :replying_posts
|
|
|
|
has_many :replying_posts,
|
|
class_name: "Domain::Post::BlueskyPost",
|
|
foreign_key: :reply_to_uri,
|
|
primary_key: :at_uri,
|
|
inverse_of: :replying_to_post
|
|
|
|
has_multiple_files! Domain::PostFile::BlueskyPostFile
|
|
has_single_creator! Domain::User::BlueskyUser
|
|
has_faving_users! Domain::User::BlueskyUser
|
|
|
|
after_initialize { self.state ||= "ok" if new_record? }
|
|
|
|
enum :state, { ok: "ok", removed: "removed" }, prefix: "state"
|
|
|
|
validates :state, presence: true
|
|
validates :at_uri, presence: true, uniqueness: true
|
|
validates :rkey, presence: true
|
|
|
|
before_validation { self.rkey = at_uri&.split("/")&.last }
|
|
validate :rkey_matches_at_uri
|
|
|
|
sig { void }
|
|
def rkey_matches_at_uri
|
|
return true if rkey.blank? && at_uri.blank?
|
|
return true if rkey == at_uri&.split("/")&.last
|
|
errors.add(:rkey, "does not match AT URI")
|
|
end
|
|
|
|
sig { override.returns([String, Symbol]) }
|
|
def self.param_prefix_and_attribute
|
|
["bsky", :rkey]
|
|
end
|
|
|
|
sig { override.returns(Integer) }
|
|
def num_post_files_for_view
|
|
self.files.group(:file_order).count.size
|
|
end
|
|
|
|
sig { override.returns(String) }
|
|
def self.view_prefix
|
|
"bsky"
|
|
end
|
|
|
|
sig { override.returns(Symbol) }
|
|
def self.post_order_attribute
|
|
:posted_at
|
|
end
|
|
|
|
sig { override.returns(Domain::DomainType) }
|
|
def self.domain_type
|
|
Domain::DomainType::Bluesky
|
|
end
|
|
|
|
sig { override.returns(T.nilable(Domain::User)) }
|
|
def primary_creator_for_view
|
|
self.creator
|
|
end
|
|
|
|
sig { override.returns(T.nilable(T.any(String, Integer))) }
|
|
def domain_id_for_view
|
|
self.rkey
|
|
end
|
|
|
|
sig { override.returns(T.nilable(String)) }
|
|
def primary_creator_name_fallback_for_view
|
|
self.creator&.handle
|
|
end
|
|
|
|
sig { override.returns(T.nilable(Addressable::URI)) }
|
|
def external_url_for_view
|
|
handle = self.creator&.handle
|
|
if rkey.present? && handle.present?
|
|
Addressable::URI.parse("https://bsky.app/profile/#{handle}/post/#{rkey}")
|
|
end
|
|
end
|
|
|
|
sig { override.returns(T.nilable(Domain::PostFile)) }
|
|
def primary_file_for_view
|
|
self.files.first
|
|
end
|
|
|
|
sig { override.returns(T.nilable(HttpLogEntry)) }
|
|
def scanned_post_log_entry_for_view
|
|
self.first_seen_entry
|
|
end
|
|
|
|
sig { override.returns(T::Boolean) }
|
|
def pending_scan?
|
|
false
|
|
end
|
|
|
|
sig { override.returns(T.nilable(String)) }
|
|
def description_html_for_view
|
|
text
|
|
end
|
|
|
|
sig { override.returns(String) }
|
|
def description_html_base_domain
|
|
"bsky.app"
|
|
end
|
|
|
|
sig { override.returns(T.nilable(String)) }
|
|
def description_for_view
|
|
self.text
|
|
end
|
|
|
|
sig { override.returns(T.nilable(Integer)) }
|
|
def num_favorites_for_view
|
|
like_count
|
|
end
|
|
|
|
sig { override.returns(T.nilable(String)) }
|
|
def title
|
|
# Use first 50 characters of text as title, or a fallback
|
|
current_text = text
|
|
current_text.present? ? current_text.truncate(50) : "Bluesky Post"
|
|
end
|
|
|
|
sig { override.returns(T.nilable(T::Array[TagForView])) }
|
|
def tags_for_view
|
|
return nil unless hashtags.present?
|
|
hashtags.map { |tag| TagForView.new(category: :general, value: tag) }
|
|
end
|
|
end
|