diff --git a/app/helpers/icon_helper.rb b/app/helpers/icon_helper.rb index 8559eb949..03bb2b891 100644 --- a/app/helpers/icon_helper.rb +++ b/app/helpers/icon_helper.rb @@ -247,6 +247,8 @@ module IconHelper image_icon_tag("pixiv-fanbox-logo.png", **options) when "Pixiv Sketch" image_icon_tag("pixiv-sketch-logo.png", **options) + when "Plurk" + image_icon_tag("plurk-logo.png", **options) when "Privatter" image_icon_tag("privatter-logo.png", **options) when "Sakura.ne.jp" diff --git a/app/logical/sources/strategies.rb b/app/logical/sources/strategies.rb index b0f5dea41..a312ad5d5 100644 --- a/app/logical/sources/strategies.rb +++ b/app/logical/sources/strategies.rb @@ -19,6 +19,7 @@ module Sources Strategies::Skeb, Strategies::Lofter, Strategies::Foundation, + Strategies::Plurk, ] end diff --git a/app/logical/sources/strategies/plurk.rb b/app/logical/sources/strategies/plurk.rb new file mode 100644 index 000000000..8401d8b63 --- /dev/null +++ b/app/logical/sources/strategies/plurk.rb @@ -0,0 +1,97 @@ +# Image URLs +# +# * https://images.plurk.com/5wj6WD0r6y4rLN0DL3sqag.jpg +# +# Page URLs +# +# * https://www.plurk.com/p/om6zv4 +# +# Profile URLs +# +# * https://www.plurk.com/redeyehare + +module Sources + module Strategies + class Plurk < Base + BASE_URL = %r{\Ahttps?://(?:www\.)?plurk\.com}i + PAGE_URL = %r{#{BASE_URL}(?:/m)?/p/(?\w+)}i + PROFILE_URL = %r{#{BASE_URL}/\w+}i + IMAGE_URL = %r{https?://images\.plurk\.com/\w+\.\w+}i + + def domains + ["plurk.com"] + end + + def site_name + "Plurk" + end + + def image_urls + return [url] if url =~ IMAGE_URL + images = page&.search(".bigplurk .content a img, .response.highlight_owner .content a img").to_a.map { |img| img["alt"] } + # the above returns both the "main" images, and any other art the artist might have posted in the replies + + if images.empty? + # in case of adult posts, we fall back to the internal api, which doesn't show replies + images = images_from_internal_api + end + + images + end + + def page_url + return nil if illust_id.blank? + + "https://plurk.com/p/#{illust_id}" + end + + def illust_id + urls.map { |u| u[PAGE_URL, :illust_id] }.compact.first + end + + def page + return nil if page_url.blank? + + response = http.cache(1.minute).get(page_url) + return nil unless response.status == 200 + + response.parse + end + + def images_from_internal_api + internal_api = page&.search("body script")&.select {|s| s.text =~ /plurk =/ }.to_a.compact.first&.text + return [] unless internal_api.present? + internal_api.scan(/(#{IMAGE_URL})/).flatten.compact.uniq.filter { |img| img !~ %r{/mx_\w+}i } + end + + def tag_name + page&.at(".bigplurk .user a")&.[](:href)&.gsub(%r{^/}, "") + end + + def artist_name + page&.at(".bigplurk .user a")&.text + end + + def profile_url + return nil if artist_name.blank? + "https://www.plurk.com/#{tag_name}" + end + + def artist_commentary_desc + page&.search(".bigplurk .content .text_holder, .response.highlight_owner .content .text_holder")&.to_html + end + + def dtext_artist_commentary_desc + DText.from_html(artist_commentary_desc) do |element| + if element.name == "a" + element.content = "" + end + end.gsub(/\A[[:space:]]+|[[:space:]]+\z/, "") + end + + def normalize_for_source + page_url + end + end + end +end diff --git a/app/models/artist_url.rb b/app/models/artist_url.rb index ed884b47f..6caf2faab 100644 --- a/app/models/artist_url.rb +++ b/app/models/artist_url.rb @@ -108,7 +108,7 @@ class ArtistUrl < ApplicationRecord def priority sites = %w[ Pixiv Twitter - ArtStation BCY Deviant\ Art Hentai\ Foundry Foundation Nico\ Seiga Nijie pawoo.net Pixiv\ Fanbox Pixiv\ Sketch Tinami Tumblr + ArtStation baraag.net BCY Deviant\ Art Hentai\ Foundry Foundation Nico\ Seiga Nijie pawoo.net Pixiv\ Fanbox Pixiv\ Sketch Plurk Tinami Tumblr Ask.fm Booth.pm Facebook Fantia FC2 Gumroad Instagram Ko-fi Livedoor Lofter Mihuashi Mixi.jp Patreon Piapro.jp Picarto Privatter Sakura.ne.jp Stickam Skeb Twitch Weibo Youtube Amazon Circle.ms DLSite Doujinshi.org Erogamescape Mangaupdates Melonbooks Toranoana Wikipedia ] diff --git a/public/images/plurk-logo.png b/public/images/plurk-logo.png new file mode 100644 index 000000000..29c6d50df Binary files /dev/null and b/public/images/plurk-logo.png differ diff --git a/test/unit/sources/plurk_test.rb b/test/unit/sources/plurk_test.rb new file mode 100644 index 000000000..dd02b04e2 --- /dev/null +++ b/test/unit/sources/plurk_test.rb @@ -0,0 +1,67 @@ +require "test_helper" + +module Sources + class PlurkTest < ActiveSupport::TestCase + context "The source for a Plurk picture" do + setup do + @post_url = "https://www.plurk.com/p/om6zv4" + @adult_post_url = "https://www.plurk.com/p/omc64y" + @image_url = "https://images.plurk.com/5wj6WD0r6y4rLN0DL3sqag.jpg" + @profile_url = "https://www.plurk.com/redeyehare" + @post1 = Sources::Strategies.find(@post_url) + @post2 = Sources::Strategies.find(@image_url) + @post3 = Sources::Strategies.find(@profile_url) + @post4 = Sources::Strategies.find(@adult_post_url) + end + + should "not raise errors" do + assert_nothing_raised { @post1.to_h } + assert_nothing_raised { @post2.to_h } + assert_nothing_raised { @post3.to_h } + assert_nothing_raised { @post4.to_h } + end + + should "get the artist name" do + assert_equal("紅眼兔", @post1.artist_name) + assert_equal("redeyehare", @post1.tag_name) + assert_equal("BOW99", @post4.tag_name) + end + + should "get profile url" do + assert_equal(@profile_url, @post1.profile_url) + end + + should "get the image url" do + assert_equal(@image_url, @post1.image_url) + assert_equal(@image_url, @post2.image_url) + end + + should "get the image urls for an adult post" do + images = ["https://images.plurk.com/yfnumBJqqoQt50Em6xKwf.png", + "https://images.plurk.com/5NaqqO3Yi6bQW1wKXq1Dc2.png", + "https://images.plurk.com/3HzNcbMhCozHPk5YY8j9fI.png", + "https://images.plurk.com/2e0duwn8BpSW9MGuUvbrim.png", + "https://images.plurk.com/1OuiMDp82hYPEUn64CWFFB.png", + "https://images.plurk.com/3F3KzZOabeMYkgTeseEZ0r.png", + "https://images.plurk.com/7onKKTAIXkY4pASszrBys8.png", + "https://images.plurk.com/6aotmjLGbtMLiI3slN7ODv.png", + "https://images.plurk.com/6pzn7jE2nkj9EV7H25L0x1.png", + "https://images.plurk.com/yA8egjDuhy0eNG9yxRj1d.png",] + assert_equal(images, @post4.image_urls) + end + + should "download an image" do + assert_downloaded(627_697, @post1.image_url) + assert_downloaded(627_697, @post2.image_url) + assert_downloaded(520_122, @post4.image_url) + end + + should "find the correct artist" do + @artist = FactoryBot.create(:artist, name: "redeyehare", url_string: @profile_url) + assert_equal([@artist], @post1.artists) + @adult_artist = FactoryBot.create(:artist, name: "bow", url_string: "https://www.plurk.com/BOW99") + assert_equal([@adult_artist], @post4.artists) + end + end + end +end