sources: rename Sources::Strategies to Source::Extractor.
Rename Sources::Strategies to Source::Extractor. A Source::Extractor represents a thing that extracts information from a given URL.
This commit is contained in:
145
app/logical/source/extractor/tumblr.rb
Normal file
145
app/logical/source/extractor/tumblr.rb
Normal file
@@ -0,0 +1,145 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# @see Source::URL::Tumblr
|
||||
class Source::Extractor
|
||||
class Tumblr < Source::Extractor
|
||||
def self.enabled?
|
||||
Danbooru.config.tumblr_consumer_key.present?
|
||||
end
|
||||
|
||||
def match?
|
||||
Source::URL::Tumblr === parsed_url
|
||||
end
|
||||
|
||||
def image_urls
|
||||
return [find_largest(parsed_url)].compact if parsed_url.asset_url?
|
||||
|
||||
assets = []
|
||||
|
||||
case post[:type]
|
||||
when "photo"
|
||||
assets += post[:photos].map do |photo|
|
||||
sizes = [photo[:original_size]] + photo[:alt_sizes]
|
||||
biggest = sizes.max_by { |x| x[:width] * x[:height] }
|
||||
biggest[:url]
|
||||
end
|
||||
|
||||
when "video"
|
||||
assets += [post[:video_url]]
|
||||
end
|
||||
|
||||
assets += inline_images
|
||||
assets.map { |url| find_largest(url) }
|
||||
end
|
||||
|
||||
def page_url
|
||||
parsed_url.page_url || parsed_referer&.page_url || post_url_from_image_html&.page_url
|
||||
end
|
||||
|
||||
def profile_url
|
||||
parsed_url.profile_url || parsed_referer&.profile_url || post_url_from_image_html&.profile_url
|
||||
end
|
||||
|
||||
def artist_commentary_title
|
||||
case post[:type]
|
||||
when "text", "link"
|
||||
post[:title]
|
||||
|
||||
when "answer"
|
||||
"#{post[:asking_name]} asked: #{post[:question]}"
|
||||
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def artist_commentary_desc
|
||||
case post[:type]
|
||||
when "text"
|
||||
post[:body]
|
||||
|
||||
when "link"
|
||||
post[:description]
|
||||
|
||||
when "photo", "video"
|
||||
post[:caption]
|
||||
|
||||
when "answer"
|
||||
post[:answer]
|
||||
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
post[:tags].to_a.map do |tag|
|
||||
[tag, "https://tumblr.com/tagged/#{CGI.escape(tag)}"]
|
||||
end.uniq
|
||||
end
|
||||
|
||||
def normalize_tag(tag)
|
||||
tag = tag.tr("-", "_")
|
||||
super(tag)
|
||||
end
|
||||
|
||||
def dtext_artist_commentary_desc
|
||||
DText.from_html(artist_commentary_desc).strip
|
||||
end
|
||||
|
||||
def find_largest(image_url)
|
||||
parsed_image = Source::URL.parse(image_url)
|
||||
if parsed_image.full_image_url.present?
|
||||
image_url_html(parsed_image.full_image_url)&.at("img[src*='/#{parsed_image.directory}/']")&.[](:src)
|
||||
elsif parsed_image.variants.present?
|
||||
# Look for the biggest available version on media.tumblr.com. A bigger
|
||||
# version may or may not exist.
|
||||
parsed_image.variants.find { |variant| http_exists?(variant) }
|
||||
else
|
||||
parsed_image.original_url
|
||||
end
|
||||
end
|
||||
|
||||
def post_url_from_image_html
|
||||
extracted = image_url_html(parsed_url)&.at("[href*='/post/']")&.[](:href)
|
||||
Source::URL.parse(extracted)
|
||||
end
|
||||
|
||||
def image_url_html(image_url)
|
||||
resp = http.cache(1.minute).headers(accept: "text/html").get(image_url)
|
||||
return nil if resp.code != 200
|
||||
resp.parse
|
||||
end
|
||||
|
||||
def inline_images
|
||||
html = Nokogiri::HTML5.fragment(artist_commentary_desc)
|
||||
html.css("img").map { |node| node["src"] }
|
||||
end
|
||||
|
||||
def artist_name
|
||||
parsed_url.blog_name || parsed_referer&.blog_name || post_url_from_image_html&.blog_name
|
||||
end
|
||||
|
||||
def work_id
|
||||
parsed_url.work_id || parsed_referer&.work_id || post_url_from_image_html&.work_id
|
||||
end
|
||||
|
||||
def api_response
|
||||
return {} unless self.class.enabled?
|
||||
return {} unless artist_name.present? && work_id.present?
|
||||
|
||||
response = http.cache(1.minute).get(
|
||||
"https://api.tumblr.com/v2/blog/#{artist_name}/posts",
|
||||
params: { id: work_id, api_key: Danbooru.config.tumblr_consumer_key }
|
||||
)
|
||||
|
||||
return {} if response.code != 200
|
||||
response.parse.with_indifferent_access
|
||||
end
|
||||
memoize :api_response
|
||||
|
||||
def post
|
||||
api_response.dig(:response, :posts)&.first || {}
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user