migrate inkbunny jobs to unified domain models
This commit is contained in:
@@ -6,28 +6,30 @@
|
||||
# LatestPostsJob, which needs to process a single page of submissions.
|
||||
class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
extend T::Sig
|
||||
include HasColorLogger
|
||||
|
||||
SUBMISSIONS_PER_PAGE = 100
|
||||
MAX_LOOP_COUNT = 50
|
||||
|
||||
sig { returns(T::Array[Domain::Inkbunny::Post]) }
|
||||
sig { returns(T::Array[Domain::Post::InkbunnyPost]) }
|
||||
attr_reader :changed_posts
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
@shallow_posts_by_ib_post_id =
|
||||
T.let({}, T::Hash[Integer, Domain::Inkbunny::Post])
|
||||
@users_by_ib_user_id = T.let({}, T::Hash[Integer, Domain::Inkbunny::User])
|
||||
@changed_posts = T.let([], T::Array[Domain::Inkbunny::Post])
|
||||
T.let({}, T::Hash[Integer, Domain::Post::InkbunnyPost])
|
||||
@users_by_ib_user_id =
|
||||
T.let({}, T::Hash[Integer, Domain::User::InkbunnyUser])
|
||||
@changed_posts = T.let([], T::Array[Domain::Post::InkbunnyPost])
|
||||
@total_new_posts = T.let(0, Integer)
|
||||
end
|
||||
|
||||
sig { returns(T::Array[Domain::Inkbunny::Post]) }
|
||||
sig { returns(T::Array[Domain::Post::InkbunnyPost]) }
|
||||
def all_posts
|
||||
@shallow_posts_by_ib_post_id.values
|
||||
end
|
||||
|
||||
sig { returns(T::Array[Domain::Inkbunny::User]) }
|
||||
sig { returns(T::Array[Domain::User::InkbunnyUser]) }
|
||||
def all_users
|
||||
@users_by_ib_user_id.values
|
||||
end
|
||||
@@ -149,8 +151,8 @@ class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
return false if post = @shallow_posts_by_ib_post_id[ib_post_id]
|
||||
|
||||
post =
|
||||
Domain::Inkbunny::Post.includes(:creator).find_or_initialize_by(
|
||||
ib_post_id: ib_post_id,
|
||||
Domain::Post::InkbunnyPost.includes(:creator).find_or_initialize_by(
|
||||
ib_id: ib_post_id,
|
||||
)
|
||||
@shallow_posts_by_ib_post_id[ib_post_id] = post
|
||||
is_new_post = post.new_record?
|
||||
@@ -161,12 +163,12 @@ class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
caused_by_entry: caused_by_entry,
|
||||
)
|
||||
|
||||
if post.creator && (post.creator&.ib_user_id != creator.ib_user_id)
|
||||
raise "post.creator.ib_user_id (#{post.creator&.ib_user_id}) != creator.ib_user_id (#{creator.ib_user_id})"
|
||||
if post.creator && (post.creator&.ib_id != creator.ib_id)
|
||||
raise "post.creator.ib_id (#{post.creator&.ib_id}) != creator.ib_id (#{creator.ib_id})"
|
||||
end
|
||||
|
||||
post.creator = creator
|
||||
post.shallow_updated_at = Time.zone.now
|
||||
post.shallow_updated_at = Time.current
|
||||
post.title = submission_json["title"]
|
||||
post.posted_at =
|
||||
Time.parse(submission_json["create_datetime"]).in_time_zone("UTC")
|
||||
@@ -180,13 +182,18 @@ class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
end
|
||||
|
||||
post.num_files = submission_json["pagecount"]&.to_i
|
||||
post.rating = submission_json["rating_id"]&.to_i
|
||||
post.submission_type = submission_json["submission_type_id"]&.to_i
|
||||
if rating_id = submission_json["rating_id"]&.to_i
|
||||
post.rating = Domain::Post::InkbunnyPost::RATING_TYPE_MAP[rating_id]
|
||||
end
|
||||
if submission_type_id = submission_json["submission_type_id"]&.to_i
|
||||
post.submission_type =
|
||||
Domain::Post::InkbunnyPost::SUBMISSION_TYPE_MAP[submission_type_id]
|
||||
end
|
||||
post.ib_detail_raw["submission_json"] = submission_json
|
||||
|
||||
post_changed =
|
||||
post.changed? || post.files.count != post.num_files ||
|
||||
creator.avatar_url_str.blank?
|
||||
creator.avatar.blank?
|
||||
|
||||
if post_changed
|
||||
post.shallow_update_log_entry = caused_by_entry
|
||||
@@ -207,7 +214,7 @@ class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
params(
|
||||
submission_json: T::Hash[String, T.untyped],
|
||||
caused_by_entry: T.nilable(HttpLogEntry),
|
||||
).returns(Domain::Inkbunny::User)
|
||||
).returns(Domain::User::InkbunnyUser)
|
||||
end
|
||||
def upsert_user_from_submission_json!(submission_json, caused_by_entry: nil)
|
||||
ib_user_id = submission_json["user_id"]&.to_i
|
||||
@@ -215,10 +222,13 @@ class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
return user
|
||||
end
|
||||
raise "ib_user_id is blank" if ib_user_id.blank?
|
||||
user = Domain::Inkbunny::User.find_or_initialize_by(ib_user_id: ib_user_id)
|
||||
user = Domain::User::InkbunnyUser.find_or_initialize_by(ib_id: ib_user_id)
|
||||
@users_by_ib_user_id[ib_user_id] = user
|
||||
user.name = submission_json["username"]
|
||||
if user.changed?
|
||||
logger.info(
|
||||
"[ApiSearchPageProcessor][user changed][ib_id: #{user.ib_id_change&.join(" -> ")}][name: #{user.name_change&.join(" -> ")}]",
|
||||
)
|
||||
user.shallow_update_log_entry = caused_by_entry
|
||||
user.save!
|
||||
end
|
||||
|
||||
@@ -10,12 +10,12 @@ class Domain::Inkbunny::Job::Base < Scraper::JobBase
|
||||
:get_inkbunny_http_client
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Domain::Inkbunny::User)) }
|
||||
sig { returns(T.nilable(Domain::User::InkbunnyUser)) }
|
||||
def user_from_args
|
||||
T.cast(arguments[0][:user], T.nilable(Domain::Inkbunny::User))
|
||||
T.cast(arguments[0][:user], T.nilable(Domain::User::InkbunnyUser))
|
||||
end
|
||||
|
||||
sig { returns(Domain::Inkbunny::User) }
|
||||
sig { returns(Domain::User::InkbunnyUser) }
|
||||
def user_from_args!
|
||||
user_from_args || raise("user must exist")
|
||||
end
|
||||
|
||||
@@ -62,7 +62,7 @@ module Domain::Inkbunny::Job
|
||||
defer_job(
|
||||
Domain::Inkbunny::Job::UpdatePostsJob,
|
||||
{
|
||||
ib_post_ids: posts_to_update.map(&:ib_post_id),
|
||||
ib_post_ids: posts_to_update.map(&:ib_id),
|
||||
caused_by_entry: first_log_entry,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -63,7 +63,7 @@ module Domain::Inkbunny::Job
|
||||
if posts_to_update.any?
|
||||
defer_job(
|
||||
Domain::Inkbunny::Job::UpdatePostsJob,
|
||||
{ ib_post_ids: posts_to_update.map(&:ib_post_id) },
|
||||
{ ib_post_ids: posts_to_update.map(&:ib_id) },
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,61 +3,45 @@ module Domain::Inkbunny::Job
|
||||
class UserAvatarJob < Base
|
||||
queue_as :static_file
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
def initialize(*args)
|
||||
super(*T.unsafe(args))
|
||||
end
|
||||
|
||||
sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform(args)
|
||||
user = user_from_args!
|
||||
avatar = T.must(user.avatar)
|
||||
|
||||
logger.prefix =
|
||||
proc { "[user #{user.name.to_s.bold} / #{user.ib_user_id.to_s.bold}]" }
|
||||
proc { "[user #{user.name.to_s.bold} / #{user.ib_id.to_s.bold}]" }
|
||||
|
||||
avatar_url_str = user.avatar_url_str
|
||||
if avatar_url_str.blank?
|
||||
logger.warn("user has no avatar_url_str")
|
||||
url_str = avatar.url_str
|
||||
if url_str.blank?
|
||||
logger.warn("avatar has no url_str")
|
||||
return
|
||||
end
|
||||
|
||||
response = http_client.get(avatar_url_str)
|
||||
response = http_client.get(url_str)
|
||||
self.first_log_entry ||= response.log_entry
|
||||
|
||||
user.avatar_state_detail ||= {}
|
||||
user.avatar_state_detail["log_entries"] ||= [
|
||||
user.avatar_file_log_entry_id,
|
||||
].compact
|
||||
user.avatar_state_detail["log_entries"] << response.log_entry.id
|
||||
user.avatar_log_entry = response.log_entry
|
||||
avatar.last_log_entry = response.log_entry
|
||||
|
||||
case response.status_code
|
||||
when 200
|
||||
user.avatar_state = :ok
|
||||
user.avatar_state_detail.delete("download_error")
|
||||
user.avatar_downloaded_at = response.log_entry.created_at
|
||||
user.avatar_file_sha256 = response.log_entry.response_sha256
|
||||
avatar.state = "ok"
|
||||
avatar.error_message = nil
|
||||
avatar.downloaded_at = response.log_entry.created_at
|
||||
avatar.log_entry = response.log_entry
|
||||
logger.info("downloaded avatar")
|
||||
when 404
|
||||
user.avatar_state = :not_found
|
||||
avatar.state = "file_404"
|
||||
avatar.error_message = "http #{response.status_code}"
|
||||
logger.info("avatar 404")
|
||||
else
|
||||
user.avatar_state = :error
|
||||
user.avatar_state_detail[
|
||||
"download_error"
|
||||
] = "http status #{response.status_code}"
|
||||
if user.avatar_file_sha256.blank?
|
||||
user.avatar_downloaded_at = response.log_entry.created_at
|
||||
logger.info("avatar error, and no previous file")
|
||||
else
|
||||
logger.info("avatar error, keeping previous file")
|
||||
end
|
||||
avatar.state = "http_error"
|
||||
avatar.error_message = "http #{response.status_code}"
|
||||
fatal_error(
|
||||
"http #{response.status_code}, log entry #{response.log_entry.id}",
|
||||
)
|
||||
end
|
||||
ensure
|
||||
user.save! if user
|
||||
avatar.save! if avatar
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# typed: true
|
||||
# typed: strict
|
||||
module Domain::Inkbunny::Job
|
||||
class UserGalleryJob < Base
|
||||
sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform(args)
|
||||
user = user_from_args!
|
||||
logger.prefix = "[#{user.name&.bold} / #{user.ib_user_id.to_s.bold}]"
|
||||
logger.prefix = "[#{user.name&.bold} / #{user.ib_id.to_s.bold}]"
|
||||
|
||||
if user.scanned_gallery_at&.after?(1.week.ago)
|
||||
logger.warn(
|
||||
@@ -24,7 +25,7 @@ module Domain::Inkbunny::Job
|
||||
|
||||
url =
|
||||
ApiSearchPageProcessor.build_api_search_url(
|
||||
ib_user_id: user.ib_user_id,
|
||||
ib_user_id: user.ib_id,
|
||||
rid: rid,
|
||||
page: page,
|
||||
)
|
||||
@@ -50,6 +51,7 @@ module Domain::Inkbunny::Job
|
||||
].join(" "),
|
||||
)
|
||||
|
||||
user.reload
|
||||
if user.scanned_gallery_at.present? && num_new_posts == 0
|
||||
logger.info("[no new posts, stopping]")
|
||||
break
|
||||
@@ -65,7 +67,7 @@ module Domain::Inkbunny::Job
|
||||
if processor.changed_posts.any?
|
||||
defer_job(
|
||||
Domain::Inkbunny::Job::UpdatePostsJob,
|
||||
{ ib_post_ids: processor.changed_posts.map(&:ib_post_id) },
|
||||
{ ib_post_ids: processor.changed_posts.map(&:ib_id) },
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
class Domain::Post::InkbunnyPost < Domain::Post
|
||||
SUBMISSION_TYPE_MAP =
|
||||
T.let(
|
||||
{
|
||||
0 => "unknown",
|
||||
1 => "picture_pinup",
|
||||
2 => "sketch",
|
||||
3 => "picture_series",
|
||||
4 => "comic",
|
||||
5 => "portfolio",
|
||||
6 => "flash_animation",
|
||||
7 => "flash_interactive",
|
||||
8 => "video_feature",
|
||||
9 => "video_animation",
|
||||
10 => "music_single",
|
||||
11 => "music_album",
|
||||
12 => "writing_document",
|
||||
13 => "character_sheet",
|
||||
14 => "photography",
|
||||
}.freeze,
|
||||
T::Hash[Integer, String],
|
||||
)
|
||||
|
||||
RATING_TYPE_MAP =
|
||||
T.let(
|
||||
{ 0 => "general", 1 => "mature", 2 => "adult" }.freeze,
|
||||
T::Hash[Integer, String],
|
||||
)
|
||||
|
||||
attr_json :ib_id, :integer
|
||||
attr_json :state, :string
|
||||
attr_json :rating, :string
|
||||
@@ -14,6 +43,9 @@ class Domain::Post::InkbunnyPost < Domain::Post
|
||||
attr_json :last_file_updated_at, :datetime
|
||||
attr_json :deep_update_log_entry_id, :integer
|
||||
attr_json :shallow_update_log_entry_id, :integer
|
||||
attr_json :shallow_updated_at, :datetime
|
||||
attr_json :deep_updated_at, :datetime
|
||||
attr_json :ib_detail_raw, ActiveModel::Type::Value.new
|
||||
|
||||
has_multiple_files! Domain::PostFile::InkbunnyPostFile
|
||||
has_single_creator! Domain::User::InkbunnyUser
|
||||
@@ -30,28 +62,17 @@ class Domain::Post::InkbunnyPost < Domain::Post
|
||||
|
||||
validates :ib_id, presence: true
|
||||
validates :state, presence: true, inclusion: { in: %w[ok error] }
|
||||
validates :rating, presence: true, inclusion: { in: %w[general mature adult] }
|
||||
validates :rating, inclusion: { in: RATING_TYPE_MAP.values }, if: :rating
|
||||
validates :submission_type,
|
||||
presence: true,
|
||||
inclusion: {
|
||||
in: %w[
|
||||
unknown
|
||||
picture_pinup
|
||||
sketch
|
||||
picture_series
|
||||
comic
|
||||
portfolio
|
||||
flash_animation
|
||||
flash_interactive
|
||||
video_feature
|
||||
video_animation
|
||||
music_single
|
||||
music_album
|
||||
writing_document
|
||||
character_sheet
|
||||
photography
|
||||
],
|
||||
}
|
||||
in: SUBMISSION_TYPE_MAP.values,
|
||||
},
|
||||
if: :submission_type
|
||||
|
||||
after_initialize do
|
||||
self.state ||= "ok"
|
||||
self.ib_detail_raw ||= {}
|
||||
end
|
||||
|
||||
sig { override.returns([String, Symbol]) }
|
||||
def self.param_prefix_and_attribute
|
||||
|
||||
@@ -41,7 +41,10 @@ class Domain::User < ReduxApplicationRecord
|
||||
super
|
||||
end
|
||||
|
||||
before_save { self.name_for_search = names_for_search_value }
|
||||
before_save do
|
||||
self.name_for_search = names_for_search_value
|
||||
true
|
||||
end
|
||||
|
||||
sig(:final) { returns(String) }
|
||||
def names_for_search_value
|
||||
|
||||
@@ -6,6 +6,7 @@ class Domain::User::InkbunnyUser < Domain::User
|
||||
attr_json :scanned_gallery_at, :datetime
|
||||
attr_json :deep_update_log_entry_id, :integer
|
||||
attr_json :shallow_update_log_entry_id, :integer
|
||||
attr_json :ib_detail_raw, ActiveModel::Type::Value.new
|
||||
|
||||
has_many :posts,
|
||||
class_name: "::Domain::Inkbunny::Post",
|
||||
@@ -27,6 +28,11 @@ class Domain::User::InkbunnyUser < Domain::User
|
||||
validates :name, presence: true
|
||||
validates :state, presence: true, inclusion: { in: %w[ok error] }
|
||||
|
||||
after_initialize do
|
||||
self.state ||= "ok"
|
||||
self.ib_detail_raw ||= {}
|
||||
end
|
||||
|
||||
sig { override.returns([String, Symbol]) }
|
||||
def self.param_prefix_and_attribute
|
||||
["ib", :name]
|
||||
@@ -57,4 +63,13 @@ class Domain::User::InkbunnyUser < Domain::User
|
||||
def names_for_search
|
||||
[name].compact
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_gallery_scan?
|
||||
if at = self.scanned_gallery_at
|
||||
at < 1.month.ago
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::E621::Job::PostsIndexJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,13 +15,13 @@ class Domain::E621::Job::ScanPostFavsJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::E621::Job::ScanPostFavsJob).void)
|
||||
).returns(T.any(Domain::E621::Job::ScanPostFavsJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/e621/job/scan_post_job.rbi
generated
2
sorbet/rbi/dsl/domain/e621/job/scan_post_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::E621::Job::ScanPostJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,13 +15,13 @@ class Domain::E621::Job::ScanUserFavsJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::E621::Job::ScanUserFavsJob).void)
|
||||
).returns(T.any(Domain::E621::Job::ScanUserFavsJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,13 +15,13 @@ class Domain::E621::Job::ScanUsersJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::E621::Job::ScanUsersJob).void)
|
||||
).returns(T.any(Domain::E621::Job::ScanUsersJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::E621::Job::StaticFileJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/fa/job/browse_page_job.rbi
generated
2
sorbet/rbi/dsl/domain/fa/job/browse_page_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::Fa::Job::BrowsePageJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/fa/job/favs_job.rbi
generated
2
sorbet/rbi/dsl/domain/fa/job/favs_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::Fa::Job::FavsJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/fa/job/scan_file_job.rbi
generated
2
sorbet/rbi/dsl/domain/fa/job/scan_file_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::Fa::Job::ScanFileJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/fa/job/scan_post_job.rbi
generated
2
sorbet/rbi/dsl/domain/fa/job/scan_post_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::Fa::Job::ScanPostJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
4
sorbet/rbi/dsl/domain/fa/job/user_avatar_job.rbi
generated
4
sorbet/rbi/dsl/domain/fa/job/user_avatar_job.rbi
generated
@@ -15,13 +15,13 @@ class Domain::Fa::Job::UserAvatarJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::Fa::Job::UserAvatarJob).void)
|
||||
).returns(T.any(Domain::Fa::Job::UserAvatarJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Fa::Job::UserFollowsJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Fa::Job::UserGalleryJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Fa::Job::UserIncrementalJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/dsl/domain/fa/job/user_page_job.rbi
generated
2
sorbet/rbi/dsl/domain/fa/job/user_page_job.rbi
generated
@@ -21,7 +21,7 @@ class Domain::Fa::Job::UserPageJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
16
sorbet/rbi/dsl/domain/inkbunny/job/api_search_page_processor.rbi
generated
Normal file
16
sorbet/rbi/dsl/domain/inkbunny/job/api_search_page_processor.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Domain::Inkbunny::Job::ApiSearchPageProcessor`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Domain::Inkbunny::Job::ApiSearchPageProcessor`.
|
||||
|
||||
|
||||
class Domain::Inkbunny::Job::ApiSearchPageProcessor
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
4
sorbet/rbi/dsl/domain/inkbunny/job/file_job.rbi
generated
4
sorbet/rbi/dsl/domain/inkbunny/job/file_job.rbi
generated
@@ -15,13 +15,13 @@ class Domain::Inkbunny::Job::FileJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::Inkbunny::Job::FileJob).void)
|
||||
).returns(T.any(Domain::Inkbunny::Job::FileJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Inkbunny::Job::LatestPostsJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Inkbunny::Job::UpdatePoolJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Domain::Inkbunny::Job::UpdatePostsJob
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,13 +15,13 @@ class Domain::Inkbunny::Job::UserAvatarJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::Inkbunny::Job::UserAvatarJob).void)
|
||||
).returns(T.any(Domain::Inkbunny::Job::UserAvatarJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
191
sorbet/rbi/dsl/domain/post/inkbunny_post.rbi
generated
191
sorbet/rbi/dsl/domain/post/inkbunny_post.rbi
generated
@@ -895,6 +895,106 @@ class Domain::Post::InkbunnyPost
|
||||
sig { void }
|
||||
def deep_update_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def deep_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def deep_updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def deep_updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def deep_updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def deep_updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def deep_updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def deep_updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def deep_updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def deep_updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def deep_updated_at_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw; end
|
||||
|
||||
sig { params(value: T.untyped).returns(T.untyped) }
|
||||
def ib_detail_raw=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def ib_detail_raw?; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def ib_detail_raw_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_change; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def ib_detail_raw_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_previous_change; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def ib_detail_raw_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_previously_was; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_was; end
|
||||
|
||||
sig { void }
|
||||
def ib_detail_raw_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def ib_id; end
|
||||
|
||||
@@ -1506,6 +1606,12 @@ class Domain::Post::InkbunnyPost
|
||||
sig { void }
|
||||
def restore_deep_update_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_deep_updated_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_ib_detail_raw!; end
|
||||
|
||||
sig { void }
|
||||
def restore_ib_id!; end
|
||||
|
||||
@@ -1548,6 +1654,9 @@ class Domain::Post::InkbunnyPost
|
||||
sig { void }
|
||||
def restore_shallow_update_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_shallow_updated_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_state!; end
|
||||
|
||||
@@ -1578,6 +1687,18 @@ class Domain::Post::InkbunnyPost
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_deep_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_deep_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_deep_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_ib_detail_raw; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_ib_detail_raw?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_ib_id; end
|
||||
|
||||
@@ -1662,6 +1783,12 @@ class Domain::Post::InkbunnyPost
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_shallow_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_shallow_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_shallow_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_state; end
|
||||
|
||||
@@ -1743,6 +1870,61 @@ class Domain::Post::InkbunnyPost
|
||||
sig { void }
|
||||
def shallow_update_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def shallow_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def shallow_updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def shallow_updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def shallow_updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def shallow_updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def shallow_updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def shallow_updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def shallow_updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def shallow_updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def shallow_updated_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def state; end
|
||||
|
||||
@@ -1984,6 +2166,12 @@ class Domain::Post::InkbunnyPost
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_deep_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_deep_updated_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_ib_detail_raw?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_ib_id?; end
|
||||
|
||||
@@ -2026,6 +2214,9 @@ class Domain::Post::InkbunnyPost
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_shallow_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_shallow_updated_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_state?; end
|
||||
|
||||
|
||||
57
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
57
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
@@ -895,6 +895,51 @@ class Domain::User::InkbunnyUser
|
||||
sig { void }
|
||||
def deep_update_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw; end
|
||||
|
||||
sig { params(value: T.untyped).returns(T.untyped) }
|
||||
def ib_detail_raw=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def ib_detail_raw?; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def ib_detail_raw_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_change; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def ib_detail_raw_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def ib_detail_raw_previous_change; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def ib_detail_raw_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_previously_was; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def ib_detail_raw_was; end
|
||||
|
||||
sig { void }
|
||||
def ib_detail_raw_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def ib_id; end
|
||||
|
||||
@@ -1226,6 +1271,9 @@ class Domain::User::InkbunnyUser
|
||||
sig { void }
|
||||
def restore_deep_update_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_ib_detail_raw!; end
|
||||
|
||||
sig { void }
|
||||
def restore_ib_id!; end
|
||||
|
||||
@@ -1274,6 +1322,12 @@ class Domain::User::InkbunnyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_deep_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_ib_detail_raw; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_ib_detail_raw?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_ib_id; end
|
||||
|
||||
@@ -1597,6 +1651,9 @@ class Domain::User::InkbunnyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_deep_update_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_ib_detail_raw?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_ib_id?; end
|
||||
|
||||
|
||||
2
sorbet/rbi/dsl/scraper/job_base.rbi
generated
2
sorbet/rbi/dsl/scraper/job_base.rbi
generated
@@ -21,7 +21,7 @@ class Scraper::JobBase
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).void }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
8
spec/factories/domain/post/inkbunny_post.rb
Normal file
8
spec/factories/domain/post/inkbunny_post.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_post_inkbunny_post, class: "Domain::Post::InkbunnyPost" do
|
||||
sequence(:ib_id) { |n| 1 + n }
|
||||
sequence(:title) { |n| "the_post_#{n}" }
|
||||
association :creator, factory: :domain_user_inkbunny_user
|
||||
end
|
||||
end
|
||||
7
spec/factories/domain/user/inkbunny_user.rb
Normal file
7
spec/factories/domain/user/inkbunny_user.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_user_inkbunny_user, class: "Domain::User::InkbunnyUser" do
|
||||
sequence(:ib_id) { |n| 1 + n }
|
||||
sequence(:name) { |n| "the_user_#{n}" }
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_user_avatar, class: "Domain::UserAvatar" do
|
||||
user { create(:domain_user_fa_user) }
|
||||
association :user, factory: :domain_user_fa_user
|
||||
state { "ok" }
|
||||
url_str { "https://a.furaffinity.net/0/meesh.gif" }
|
||||
log_entry { create(:http_log_entry) }
|
||||
|
||||
@@ -26,38 +26,38 @@ describe Domain::Inkbunny::Job::LatestPostsJob do
|
||||
|
||||
it "creates posts" do
|
||||
expect { perform_now({}) }.to(
|
||||
change(Domain::Inkbunny::Post, :count)
|
||||
change(Domain::Post::InkbunnyPost, :count)
|
||||
.by(3)
|
||||
.and(change(Domain::Inkbunny::User, :count).by(3))
|
||||
.and(change(Domain::User::InkbunnyUser, :count).by(3))
|
||||
.and(change(Domain::Inkbunny::File, :count).by(0)),
|
||||
)
|
||||
|
||||
user_thendyart = Domain::Inkbunny::User.find_by!(ib_user_id: 941_565)
|
||||
user_thendyart = Domain::User::InkbunnyUser.find_by!(ib_id: 941_565)
|
||||
expect(user_thendyart.name).to eq("ThendyArt")
|
||||
|
||||
user_seff = Domain::Inkbunny::User.find_by!(ib_user_id: 229_331)
|
||||
user_seff = Domain::User::InkbunnyUser.find_by!(ib_id: 229_331)
|
||||
expect(user_seff.name).to eq("Seff")
|
||||
expect(user_seff.avatar_url_str).to be_nil
|
||||
expect(user_seff.avatar).to be_nil
|
||||
|
||||
post_3104202 = Domain::Inkbunny::Post.find_by!(ib_post_id: 3_104_202)
|
||||
post_3104202 = Domain::Post::InkbunnyPost.find_by!(ib_id: 3_104_202)
|
||||
expect(post_3104202.title).to eq("Phantom Touch - Page 25")
|
||||
expect(post_3104202.posted_at).to eq(
|
||||
expect(post_3104202.posted_at).to be_within(1.second).of(
|
||||
Time.parse("2023-08-27 21:31:40.365597+02"),
|
||||
)
|
||||
expect(post_3104202.creator).to eq(user_thendyart)
|
||||
expect(post_3104202.last_file_updated_at).to eq(
|
||||
expect(post_3104202.last_file_updated_at).to be_within(1.second).of(
|
||||
Time.parse("2023-08-27 21:30:06.222262+02"),
|
||||
)
|
||||
expect(post_3104202.num_files).to eq(1)
|
||||
expect(post_3104202.rating).to eq("adult")
|
||||
expect(post_3104202.submission_type).to eq("comic")
|
||||
expect(post_3104202.shallow_updated_at).to be_within(1.second).of(
|
||||
Time.now,
|
||||
Time.current,
|
||||
)
|
||||
expect(post_3104202.shallow_update_log_entry).to eq(log_entries[0])
|
||||
expect(post_3104202.deep_updated_at).to be_nil
|
||||
|
||||
user_soulcentinel = Domain::Inkbunny::User.find_by!(ib_user_id: 349_747)
|
||||
user_soulcentinel = Domain::User::InkbunnyUser.find_by!(ib_id: 349_747)
|
||||
expect(user_soulcentinel.scanned_gallery_at).to be_nil
|
||||
|
||||
expect(
|
||||
@@ -112,13 +112,13 @@ describe Domain::Inkbunny::Job::LatestPostsJob do
|
||||
|
||||
it "updates posts and files" do
|
||||
expect { perform_now({}) }.to(
|
||||
change(Domain::Inkbunny::Post, :count).by(1).and(
|
||||
change(Domain::Inkbunny::User, :count).by(1),
|
||||
change(Domain::Post::InkbunnyPost, :count).by(1).and(
|
||||
change(Domain::User::InkbunnyUser, :count).by(1),
|
||||
),
|
||||
)
|
||||
post_1047334 = Domain::Inkbunny::Post.find_by!(ib_post_id: 1_047_334)
|
||||
post_1047334 = Domain::Post::InkbunnyPost.find_by!(ib_id: 1_047_334)
|
||||
expect(post_1047334.title).to eq("Yellow Snake")
|
||||
expect(post_1047334.last_file_updated_at).to eq(
|
||||
expect(post_1047334.last_file_updated_at).to be_within(1.second).of(
|
||||
Time.parse("2016-03-13 22:18:52.32319+01"),
|
||||
)
|
||||
|
||||
@@ -129,15 +129,15 @@ describe Domain::Inkbunny::Job::LatestPostsJob do
|
||||
|
||||
# second perform should update the post
|
||||
expect { perform_now({}) }.to(
|
||||
change(Domain::Inkbunny::Post, :count)
|
||||
change(Domain::Post::InkbunnyPost, :count)
|
||||
.by(0)
|
||||
.and(change(Domain::Inkbunny::User, :count).by(0))
|
||||
.and(change(Domain::User::InkbunnyUser, :count).by(0))
|
||||
.and(change(Domain::Inkbunny::File, :count).by(0)),
|
||||
)
|
||||
|
||||
post_1047334.reload
|
||||
expect(post_1047334.title).to eq("How to Photograph Snakes")
|
||||
expect(post_1047334.last_file_updated_at).to eq(
|
||||
expect(post_1047334.last_file_updated_at).to be_within(1.second).of(
|
||||
Time.parse("2023-09-14 19:07:45.735562+02"),
|
||||
)
|
||||
|
||||
|
||||
@@ -48,16 +48,16 @@ RSpec.describe Domain::Inkbunny::Job::UpdatePoolJob do
|
||||
)
|
||||
|
||||
expect { perform_now({ pool: pool }) }.to change {
|
||||
Domain::Inkbunny::Post.count
|
||||
Domain::Post::InkbunnyPost.count
|
||||
}.by(4)
|
||||
|
||||
# Verify posts were created correctly
|
||||
post_3334290 = Domain::Inkbunny::Post.find_by!(ib_post_id: 3_334_290)
|
||||
post_3334290 = Domain::Post::InkbunnyPost.find_by!(ib_id: 3_334_290)
|
||||
expect(post_3334290.title).to eq("Phantom Touch: Follow-Up")
|
||||
expect(post_3334290.posted_at).to eq(
|
||||
expect(post_3334290.posted_at).to be_within(1.second).of(
|
||||
Time.parse("2024-05-28 00:57:36.597545+00"),
|
||||
)
|
||||
expect(post_3334290.last_file_updated_at).to eq(
|
||||
expect(post_3334290.last_file_updated_at).to be_within(1.second).of(
|
||||
Time.parse("2024-05-28 00:55:24.811748+00"),
|
||||
)
|
||||
expect(post_3334290.num_files).to eq(1)
|
||||
@@ -70,7 +70,7 @@ RSpec.describe Domain::Inkbunny::Job::UpdatePoolJob do
|
||||
expect(post_3334290.deep_updated_at).to be_nil
|
||||
|
||||
# Verify user was created
|
||||
user_thendyart = Domain::Inkbunny::User.find_by!(ib_user_id: 941_565)
|
||||
user_thendyart = Domain::User::InkbunnyUser.find_by!(ib_id: 941_565)
|
||||
expect(user_thendyart.name).to eq("ThendyArt")
|
||||
|
||||
# Verify UpdatePostsJob was enqueued for posts without deep_updated_at
|
||||
@@ -94,7 +94,7 @@ RSpec.describe Domain::Inkbunny::Job::UpdatePoolJob do
|
||||
pool.save!
|
||||
|
||||
expect { perform_now({ pool: pool }) }.not_to change {
|
||||
Domain::Inkbunny::Post.count
|
||||
Domain::Post::InkbunnyPost.count
|
||||
}
|
||||
|
||||
expect(pool.deep_update_log_entry).to eq(log_entry)
|
||||
|
||||
@@ -6,18 +6,19 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
before { Scraper::ClientFactory.http_client_mock = http_client_mock }
|
||||
|
||||
let(:avatar_url_str) { "https://example.com/avatar.jpg" }
|
||||
let(:avatar_state) { nil }
|
||||
let(:existing_avatar_sha256) { nil }
|
||||
let(:avatar_state) { "pending" }
|
||||
let(:existing_downloaded_at) { nil }
|
||||
let(:existing_log_entry_id) { nil }
|
||||
let!(:user) do
|
||||
let(:user) { create(:domain_user_inkbunny_user) }
|
||||
let!(:avatar) do
|
||||
create(
|
||||
:domain_inkbunny_user,
|
||||
avatar_url_str: avatar_url_str,
|
||||
avatar_state: avatar_state,
|
||||
avatar_file_sha256: existing_avatar_sha256,
|
||||
avatar_downloaded_at: existing_downloaded_at,
|
||||
avatar_file_log_entry_id: existing_log_entry_id,
|
||||
:domain_user_avatar,
|
||||
user: user,
|
||||
url_str: avatar_url_str,
|
||||
state: avatar_state,
|
||||
downloaded_at: existing_downloaded_at,
|
||||
last_log_entry_id: existing_log_entry_id,
|
||||
log_entry_id: existing_log_entry_id,
|
||||
)
|
||||
end
|
||||
|
||||
@@ -30,10 +31,9 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
|
||||
it "logs a warning and returns" do
|
||||
perform_job
|
||||
user.reload
|
||||
expect(user.avatar_state).to be_nil
|
||||
expect(user.avatar).to be_nil
|
||||
expect(user.avatar_log_entry).to be_nil
|
||||
avatar.reload
|
||||
expect(avatar.state).to eq("pending")
|
||||
expect(avatar.log_entry).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -57,14 +57,11 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
perform_job
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("ok")
|
||||
expect(user.avatar_file_sha256).to eq(log_entries[0].response_sha256)
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(log_entries[0].response_sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
expect(avatar.state).to eq("ok")
|
||||
expect(avatar.downloaded_at).to be_within(1.second).of(
|
||||
log_entries[0].created_at,
|
||||
)
|
||||
expect(avatar.log_entry).to eq(log_entries[0])
|
||||
end
|
||||
|
||||
context "when previous file exists" do
|
||||
@@ -73,7 +70,6 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
let(:existing_blob_entry) do
|
||||
create(:blob_entry, content: "previous", content_type: "image/jpeg")
|
||||
end
|
||||
let(:existing_avatar_sha256) { existing_blob_entry.sha256 }
|
||||
let(:avatar_state) { :ok }
|
||||
let(:existing_downloaded_at) { 1.day.ago }
|
||||
|
||||
@@ -81,17 +77,11 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
perform_job
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("ok")
|
||||
expect(user.avatar_file_sha256).to eq(log_entries[0].response_sha256)
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(log_entries[0].response_sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq(
|
||||
[existing_log_entry.id, log_entries[0].id],
|
||||
)
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
expect(avatar.state).to eq("ok")
|
||||
expect(avatar.downloaded_at).to be_within(1.second).of(
|
||||
log_entries[0].created_at,
|
||||
)
|
||||
expect(avatar.log_entry).to eq(log_entries[0])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -116,12 +106,10 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
perform_job
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("not_found")
|
||||
expect(user.avatar_file_sha256).to be_nil
|
||||
expect(user.avatar).to be_nil
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq([log_entries[0].id])
|
||||
expect(user.avatar_downloaded_at).to be_nil
|
||||
expect(avatar.state).to eq("file_404")
|
||||
expect(avatar.downloaded_at).to be_nil
|
||||
expect(avatar.last_log_entry).to eq(log_entries[0])
|
||||
expect(avatar.log_entry).to be_nil
|
||||
end
|
||||
|
||||
context "when previous file exists" do
|
||||
@@ -130,7 +118,6 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
let(:existing_blob_entry) do
|
||||
create(:blob_entry, content: "previous", content_type: "image/jpeg")
|
||||
end
|
||||
let(:existing_avatar_sha256) { existing_blob_entry.sha256 }
|
||||
let(:avatar_state) { :ok }
|
||||
let(:existing_downloaded_at) { 1.day.ago }
|
||||
|
||||
@@ -138,22 +125,17 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
perform_job
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("not_found")
|
||||
expect(user.avatar_file_sha256).to eq(existing_blob_entry.sha256)
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(existing_blob_entry.sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq(
|
||||
[existing_log_entry.id, log_entries[0].id],
|
||||
)
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
expect(avatar.state).to eq("file_404")
|
||||
expect(avatar.downloaded_at).to be_within(1.second).of(
|
||||
existing_downloaded_at,
|
||||
)
|
||||
expect(avatar.last_log_entry).to eq(log_entries[0])
|
||||
expect(avatar.log_entry).to eq(existing_log_entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when avatar download fails with error" do
|
||||
context "when avatar download fails and then succeeds" do
|
||||
let! :log_entries do
|
||||
HttpClientMockHelpers.init_http_client_mock(
|
||||
http_client_mock,
|
||||
@@ -176,29 +158,25 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
)
|
||||
end
|
||||
|
||||
it "sets error state and raises fatal error" do
|
||||
it "sets error state and then ok state" do
|
||||
perform_now({ user: user }, should_raise: Scraper::JobBase::JobError)
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("error")
|
||||
expect(user.avatar_state_detail["download_error"]).to include("500")
|
||||
expect(user.avatar).to be_nil
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq([log_entries[0].id])
|
||||
avatar.reload
|
||||
|
||||
expect(avatar.state).to eq("http_error")
|
||||
expect(avatar.last_log_entry).to eq(log_entries[0])
|
||||
expect(avatar.log_entry).to be_nil
|
||||
expect(avatar.error_message).to include("500")
|
||||
|
||||
perform_now({ user: user })
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("ok")
|
||||
expect(user.avatar_state_detail["download_error"]).to be_nil
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(log_entries[1].response_sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[1])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq(
|
||||
log_entries.map(&:id),
|
||||
)
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
log_entries[1].created_at,
|
||||
)
|
||||
avatar.reload
|
||||
|
||||
expect(avatar.state).to eq("ok")
|
||||
expect(avatar.error_message).to be_nil
|
||||
expect(avatar).to be_present
|
||||
expect(avatar.last_log_entry).to eq(log_entries[1])
|
||||
expect(avatar.log_entry).to eq(log_entries[1])
|
||||
end
|
||||
|
||||
context "when previous file exists" do
|
||||
@@ -207,7 +185,6 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
let(:existing_blob_entry) do
|
||||
create(:blob_entry, content: "previous", content_type: "image/jpeg")
|
||||
end
|
||||
let(:existing_avatar_sha256) { existing_blob_entry.sha256 }
|
||||
let(:avatar_state) { :ok }
|
||||
let(:existing_downloaded_at) { 1.day.ago }
|
||||
|
||||
@@ -215,31 +192,25 @@ describe Domain::Inkbunny::Job::UserAvatarJob do
|
||||
perform_now({ user: user }, should_raise: Scraper::JobBase::JobError)
|
||||
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("error")
|
||||
expect(user.avatar_file_sha256).to eq(existing_blob_entry.sha256)
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(existing_blob_entry.sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[0])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq(
|
||||
[existing_log_entry.id, log_entries[0].id],
|
||||
)
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
avatar.reload
|
||||
|
||||
expect(avatar.state).to eq("http_error")
|
||||
expect(avatar.last_log_entry).to eq(log_entries[0])
|
||||
expect(avatar.log_entry).to eq(existing_log_entry)
|
||||
expect(avatar.error_message).to include("500")
|
||||
expect(avatar.downloaded_at).to be_within(1.second).of(
|
||||
existing_downloaded_at,
|
||||
)
|
||||
|
||||
perform_now({ user: user })
|
||||
user.reload
|
||||
expect(user.avatar_state).to eq("ok")
|
||||
expect(user.avatar_state_detail["download_error"]).to be_nil
|
||||
expect(user.avatar).to be_present
|
||||
expect(user.avatar.sha256).to eq(log_entries[1].response_sha256)
|
||||
expect(user.avatar_log_entry).to eq(log_entries[1])
|
||||
expect(user.avatar_state_detail["log_entries"]).to eq(
|
||||
[existing_log_entry.id] + log_entries.map(&:id),
|
||||
)
|
||||
expect(user.avatar_downloaded_at).to be_within(1.second).of(
|
||||
log_entries[1].created_at,
|
||||
)
|
||||
avatar.reload
|
||||
|
||||
expect(avatar.state).to eq("ok")
|
||||
expect(avatar.error_message).to be_nil
|
||||
expect(avatar).to be_present
|
||||
expect(avatar.last_log_entry).to eq(log_entries[1])
|
||||
expect(avatar.log_entry).to eq(log_entries[1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
# User ID is for `zaush`, set the wrong name to test that the name is updated
|
||||
let!(:user) do
|
||||
create(:domain_inkbunny_user, name: "the_user", ib_user_id: 26_540)
|
||||
create(:domain_user_inkbunny_user, name: "the_user", ib_id: 26_540)
|
||||
end
|
||||
let(:args) { { user: user, caused_by_entry: nil } }
|
||||
let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
|
||||
@@ -37,7 +38,7 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
)
|
||||
|
||||
expect { perform_now(args) }.to(
|
||||
change(Domain::Inkbunny::Post, :count)
|
||||
change(Domain::Post::InkbunnyPost, :count)
|
||||
.by(0)
|
||||
.and(change(Domain::Inkbunny::File, :count).by(0))
|
||||
.and(change(Domain::Inkbunny::User, :count).by(0)),
|
||||
@@ -79,10 +80,10 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
|
||||
it "fetches all pages and enqueues update jobs" do
|
||||
expect { perform_now(args) }.to(
|
||||
change(Domain::Inkbunny::Post, :count)
|
||||
change(Domain::Post::InkbunnyPost, :count)
|
||||
.by(4)
|
||||
.and(change(Domain::Inkbunny::File, :count).by(0))
|
||||
.and(change(Domain::Inkbunny::User, :count).by(0)),
|
||||
.and(change(Domain::PostFile::InkbunnyPostFile, :count).by(0))
|
||||
.and(change(Domain::User::InkbunnyUser, :count).by(0)),
|
||||
)
|
||||
|
||||
user.reload
|
||||
@@ -91,7 +92,7 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
expect(user.posts.count).to eq(4)
|
||||
expect(user.shallow_update_log_entry).to eq(log_entries[0])
|
||||
|
||||
post_3507105 = user.posts.find_by(ib_post_id: 350_7105)
|
||||
post_3507105 = user.posts.find_by(ib_id: 350_7105)
|
||||
expect(post_3507105).to be_present
|
||||
expect(post_3507105.num_files).to eq(5)
|
||||
expect(post_3507105.files.count).to eq(0)
|
||||
@@ -121,13 +122,13 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
end
|
||||
|
||||
let(:user) do
|
||||
create(:domain_inkbunny_user, name: "the_user", ib_user_id: 16_532)
|
||||
create(:domain_user_inkbunny_user, name: "the_user", ib_id: 16_532)
|
||||
end
|
||||
let(:args) { { user: user, caused_by_entry: nil } }
|
||||
|
||||
it "correctly handles posts with a null last_file_update_datetime" do
|
||||
expect { perform_now(args) }.to(
|
||||
change(Domain::Inkbunny::Post, :count).by(1),
|
||||
change(Domain::Post::InkbunnyPost, :count).by(1),
|
||||
)
|
||||
|
||||
user.reload
|
||||
@@ -136,7 +137,7 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
expect(user.posts.count).to eq(1)
|
||||
expect(user.shallow_update_log_entry).to eq(log_entries[0])
|
||||
|
||||
post_2855990 = user.posts.find_by(ib_post_id: 2_855_990)
|
||||
post_2855990 = user.posts.find_by(ib_id: 2_855_990)
|
||||
expect(post_2855990).to be_present
|
||||
expect(post_2855990.num_files).to eq(0)
|
||||
expect(post_2855990.files.count).to eq(0)
|
||||
|
||||
Reference in New Issue
Block a user