Files
danbooru/app/logical/upload_service/preprocessor.rb
evazion f38c38f26e search: split tag_match into user_tag_match / system_tag_match.
When doing a tag search, we have to be careful about which user we're
running the search as because the results depend on the current user.
Specifically, things like private favorites, private favorite groups,
post votes, saved searches, and flagger names depend on the user's
permissions, and whether non-safe or deleted posts are filtered out
depend on whether the user has safe mode on or the hide deleted posts
setting enabled.

* Refactor internal searches to explicitly state whether they're
  running as the system user (DanbooruBot) or as the current user.
* Explicitly pass in the current user to PostQueryBuilder instead of
  implicitly relying on the CurrentUser global.
* Get rid of CurrentUser.admin_mode? (used to ignore the hide deleted
  post setting) and CurrentUser.without_safe_mode (used to ignore safe
  mode).
* Change the /counts/posts.json endpoint to ignore safe mode and the
  hide deleted posts settings when counting posts.
* Fix searches not correctly overriding the hide deleted posts setting
  when multiple status: metatags were used (e.g. `status:banned status:active`)
* Fix fast_count not respecting the hide deleted posts setting when the
  status:banned metatag was used.
2020-05-07 03:29:44 -05:00

125 lines
3.2 KiB
Ruby

class UploadService
class Preprocessor
extend Memoist
attr_reader :params, :original_post_id
def initialize(params)
@original_post_id = params.delete(:original_post_id) || -1
@params = params
end
def source
params[:source]
end
def md5
params[:md5_confirmation]
end
def referer_url
params[:referer_url]
end
def strategy
Sources::Strategies.find(source, referer_url)
end
memoize :strategy
# When searching posts we have to use the canonical source
def canonical_source
strategy.canonical_url
end
memoize :canonical_source
def in_progress?
if md5.present?
return Upload.where(status: "preprocessing", md5: md5).exists?
end
if Utils.is_downloadable?(source)
return Upload.where(status: "preprocessing", source: source).exists?
end
false
end
def predecessor
if md5.present?
return Upload.where(status: ["preprocessed", "preprocessing"], md5: md5).first
end
if Utils.is_downloadable?(source)
return Upload.where(status: ["preprocessed", "preprocessing"], source: source).first
end
end
def completed?
predecessor.present?
end
def delayed_start(uploader_id)
CurrentUser.as(uploader_id) do
start!
end
rescue ActiveRecord::RecordNotUnique
return
end
def start!
if Utils.is_downloadable?(source)
if Post.system_tag_match("source:#{canonical_source}").where.not(id: original_post_id).exists?
raise ActiveRecord::RecordNotUnique.new("A post with source #{canonical_source} already exists")
end
if Upload.where(source: source, status: "completed").exists?
raise ActiveRecord::RecordNotUnique.new("A completed upload with source #{source} already exists")
end
if Upload.where(source: source).where("status like ?", "error%").exists?
raise ActiveRecord::RecordNotUnique.new("An errored upload with source #{source} already exists")
end
end
params[:rating] ||= "q"
params[:tag_string] ||= "tagme"
upload = Upload.create!(params)
begin
upload.update(status: "preprocessing")
file = Utils.get_file_for_upload(upload, file: params[:file]&.tempfile)
Utils.process_file(upload, file, original_post_id: original_post_id)
upload.rating = params[:rating]
upload.tag_string = params[:tag_string]
upload.status = "preprocessed"
upload.save!
rescue Exception => x
upload.update(file_ext: nil, status: "error: #{x.class} - #{x.message}", backtrace: x.backtrace.join("\n"))
end
return upload
end
def finish!(upload = nil)
pred = upload || self.predecessor
# regardless of who initialized the upload, credit should
# goto whoever submitted the form
pred.initialize_attributes
pred.attributes = self.params
# if a file was uploaded after the preprocessing occurred,
# then process the file and overwrite whatever the preprocessor
# did
Utils.process_file(pred, pred.file.tempfile) if pred.file.present?
pred.status = "completed"
pred.save
return pred
end
end
end