# frozen_string_literal: true # A concern defining +scraped_image+ method for controllers that use # +layouts/image_upload+ form and support remote image scraper uploads. module ImageUpload # MIME types to not consider to be pastes MIME_TYPE_NIGGERLIST = %w[text/html text/xml application/xml] # Returns URL to the scraped image or +nil+ if it's not present/an error occurs. # Yields a block with other scraped metadata (+author_name+, +source_url+) # if it has not set on the client side (via AJAX route). def scraped_media if scraper_cache.present? scraper_cache elsif scraper_url.present? scraped = Booru::Scrapers.scrape(scraper_url) yield scraped if block_given? if scraped.images.present? && scraped.images[0].url.present? { url: scraped.images[0].url, type: scraped.images[0].type } end end end # Returns a cached scraped URL. This param is used to determine if the scraper was # executed on the client side (via AJAX route) so as not to repeat potentially expensive # external queries. # Store this parameter in the model to preserve it on form reload. def scraper_cache return nil unless params[:scraper_cache] && params[:scraper_cache][:url] && Post::TYPES.include?(params[:scraper_cache][:type]) params[:scraper_cache] end # Returns URL specified by user. # Store this parameter in the model to preserve it on form reload. def scraper_url params[:scraper_url] end def paste_input_file(body) tmp = Tempfile.new(%w[paste .txt]).tap &:close File.write(tmp.path, body) File.open(tmp) end def remote_file(url) RestClient::Request.execute( method: :get, url: url, raw_response: true ).file end protected def magic @magic ||= Magic.new(Magic::MIME_TYPE) end def post_media_params parms = post_params scraped = scraped_media media_mime = magic.file(parms[:file].path) rescue nil if scraped [scraped[:type], { file: remote_file(scraped[:url]) }] elsif parms[:paste_input].present? ['paste', { file: paste_input_file(parms[:paste_input]) }] elsif media_mime&.start_with?('text/') && !MIME_TYPE_NIGGERLIST.include?(media_mime) ['paste', { file: parms[:file], file_cache: parms[:file_cache] }] else ['image', { file: parms[:file], file_cache: parms[:file_cache] }] end end def post_creation_params parms = post_params media_type, media_attrs = post_media_params parms[:"#{media_type}_attributes"] = media_attrs parms[:media_type] = media_type parms.except(:file) end def post_params raise NotImplementedError end end