Files
redux-scraper/app/models/domain/post/e621_post.rb
2025-08-20 22:10:57 +00:00

186 lines
4.7 KiB
Ruby

# typed: strict
class Domain::Post::E621Post < Domain::Post
aux_table :e621
has_single_file!
has_faving_users! Domain::User::E621User, Domain::UserPostFav::E621UserPostFav
belongs_to_groups! :pools,
Domain::PostGroup::E621Pool,
Domain::PostGroupJoin::E621PoolJoin
belongs_to :parent_post,
class_name: "Domain::Post::E621Post",
foreign_key: :parent_post_e621_id,
primary_key: :e621_id,
optional: true
belongs_to :uploader_user,
class_name: "::Domain::User::E621User",
inverse_of: :uploaded_posts,
optional: true
belongs_to :last_index_page, class_name: "HttpLogEntry", optional: true
belongs_to :scan_log_entry, class_name: "HttpLogEntry", optional: true
belongs_to :caused_by_entry, class_name: "HttpLogEntry", optional: true
validates :state, inclusion: { in: %w[ok removed scan_error file_error] }
validates :rating,
inclusion: {
in: %w[s q e],
},
if: ->(p) { p.rating.present? }
validates :e621_id, presence: true
after_initialize do
self.state ||= "ok"
self.flags_array ||= []
self.pools_array ||= []
self.sources_array ||= []
self.artists_array ||= []
end
sig { params(log_entry: HttpLogEntry).void }
def set_index_page_entry(log_entry)
self.last_index_page = log_entry
self.index_page_ids ||= []
self.index_page_ids << log_entry.id
end
sig { override.returns(Integer) }
def num_post_files_for_view
1
end
sig { override.returns([String, Symbol]) }
def self.param_prefix_and_attribute
["e621", :e621_id]
end
sig { override.returns(Symbol) }
def self.post_order_attribute
:e621_id
end
sig { override.returns(String) }
def self.view_prefix
"e621"
end
sig { override.returns(Domain::DomainType) }
def self.domain_type
Domain::DomainType::E621
end
sig { override.returns(T.nilable(String)) }
def title
self
.sources_array
.lazy
.filter_map do |source|
model =
T.cast(
T.unsafe(ApplicationController.helpers).link_for_source(source),
T.nilable(Domain::PostsHelper::LinkForSource),
)&.model
return model.title if model && model.is_a?(Domain::Post)
end
.first || "E621 Post #{self.e621_id}"
end
sig { override.returns(T.nilable(String)) }
def primary_creator_name_fallback_for_view
guess_creator_from_sources&.name_for_view ||
self.class.first_valid_artist_tag_in(self.tags_array&.dig("artist")) ||
self.class.first_valid_artist_tag_in(self.artists_array)
end
sig { override.returns(T.nilable(Domain::User)) }
def primary_fallback_creator_for_view
guess_creator_from_sources
end
sig { override.returns(T.nilable(String)) }
def description_html_for_view
self.description
end
INVALID_ARTIST_TAGS = %w[unknown unknown_artist sound_warning].freeze
sig { params(list: T.nilable(T::Array[String])).returns(T.nilable(String)) }
def self.first_valid_artist_tag_in(list)
list &&
list
.lazy
.filter_map { |tag| INVALID_ARTIST_TAGS.include?(tag) ? nil : tag }
.first
end
sig { override.returns(T.nilable(T.any(String, Integer))) }
def domain_id_for_view
self.e621_id
end
sig { override.returns(T.nilable(HttpLogEntry)) }
def scanned_post_log_entry_for_view
self.scan_log_entry || self.last_index_page || self.caused_by_entry
end
sig { override.returns(String) }
def description_html_base_domain
"e621.net"
end
sig { override.returns(T.nilable(Addressable::URI)) }
def external_url_for_view
if self.e621_id.present?
Addressable::URI.parse("https://e621.net/posts/#{self.e621_id}")
end
end
sig { override.returns(T.nilable(Domain::PostFile)) }
def primary_file_for_view
self.file
end
sig { returns(String) }
def rating_for_view
case self.rating
when nil
"None"
when "s"
"Safe"
when "q"
"Questionable"
when "e"
"Explicit"
else
"Unknown (#{self.rating})"
end
end
private
sig { returns(T.nilable(Domain::User)) }
def guess_creator_from_sources
self
.sources_array
.lazy
.filter_map do |source|
model =
T.cast(
T.unsafe(ApplicationController.helpers).link_for_source(source),
T.nilable(Domain::PostsHelper::LinkForSource),
)&.model
if model && model.is_a?(Domain::Post) && model.class.has_creators?
T.unsafe(model).creator
elsif model && model.is_a?(Domain::User)
model
else
nil
end
end
.first
end
end