From dc97f4483b56a515af6f0de5b77518831052f293 Mon Sep 17 00:00:00 2001 From: nonamethanks Date: Thu, 4 Mar 2021 21:48:47 +0100 Subject: [PATCH] Add skeb support --- app/logical/sources/strategies.rb | 3 +- app/logical/sources/strategies/base.rb | 2 - app/logical/sources/strategies/skeb.rb | 107 +++++++++++++++++++++++++ test/unit/sources/skeb_test.rb | 75 +++++++++++++++++ 4 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 app/logical/sources/strategies/skeb.rb create mode 100644 test/unit/sources/skeb_test.rb diff --git a/app/logical/sources/strategies.rb b/app/logical/sources/strategies.rb index 895a9a6bd..a3686a37f 100644 --- a/app/logical/sources/strategies.rb +++ b/app/logical/sources/strategies.rb @@ -15,7 +15,8 @@ module Sources Strategies::Moebooru, Strategies::HentaiFoundry, Strategies::Weibo, - Strategies::Newgrounds + Strategies::Newgrounds, + Strategies::Skeb ] end diff --git a/app/logical/sources/strategies/base.rb b/app/logical/sources/strategies/base.rb index 52a190bd5..11c6cfe96 100644 --- a/app/logical/sources/strategies/base.rb +++ b/app/logical/sources/strategies/base.rb @@ -90,8 +90,6 @@ module Sources "Patreon" when /privatter\.net\z/i "Privatter" - when /skeb\.jp\z/i - "Skeb" when /tinami\.com\z/i "Tinami" when /toranoana\.(jp|shop)\z/i diff --git a/app/logical/sources/strategies/skeb.rb b/app/logical/sources/strategies/skeb.rb new file mode 100644 index 000000000..90fdc9859 --- /dev/null +++ b/app/logical/sources/strategies/skeb.rb @@ -0,0 +1,107 @@ +# Image URLS +## Non-watermarked: +# * https://skeb.imgix.net/requests/199886_0?bg=%23fff&auto=format&w=800&s=5a6a908ab964fcdfc4713fad179fe715 +## Watermarked: +# * https://skeb.imgix.net/requests/73290_0?bg=%23fff&auto=format&txtfont=bold&txtshad=70&txtclr=BFFFFFFF&txtalign=middle%2Ccenter&txtsize=150&txt=SAMPLE&w=800&s=4843435cff85d623b1f657209d131526 +## Full Size (found in commissioner_upload): +# * https://skeb.imgix.net/requests/53269_1?bg=%23fff&fm=png&dl=53269.png&w=1.0&h=1.0&s=44588ea9c41881049e392adb1df21cce +# +# The signature is required and tied to the parameters. Doesn't seem like it's possible to reverse engineer it to remove the watermark, unfortunately. +# +# Page URLS +# * https://skeb.jp/@OrvMZ/works/3 (non-watermarked) +# * https://skeb.jp/@OrvMZ/works/1 (separated request and client's message after delivery. We can't get the latter) +# * https://skeb.jp/@asanagi/works/16 (age-restricted, watermarked) +# * https://skeb.jp/@asanagi/works/6 (private, returns 404) +# +# Profile URLS +# Since skeb forces login through twitter, usernames are the same as twitter +# * https://skeb.jp/@asanagi + +module Sources + module Strategies + class Skeb < Base + PROFILE_URL = %r{https?://(?:www\.)?skeb\.jp/@(?\w+)}i + + PAGE_URL = %r{#{PROFILE_URL}/works/(?\d+)}i + + IMAGE_URL = %r{https?://(?:www\.)?skeb\.imgix\.net/requests/[\d_]+\?.*}i + + def domains + ["skeb.jp"] + end + + def match? + return false if parsed_url.nil? + parsed_url.domain.in?(domains) || parsed_url.host == "skeb.imgix.net" + end + + def site_name + "Skeb" + end + + def image_urls + if url =~ IMAGE_URL + [url] + elsif page.present? + [page.text[/window\.__NUXT__=.*,preview_url:"(.*?)",/, 1].gsub("\\u002F", "/")] + else + [] + end + end + + def page_url + urls.map { |u| u if u =~ PAGE_URL }.compact.first + end + + def normalize_for_source + page_url + end + + def page + return if page_url.blank? + response = http.cache(1.minute).get(page_url) + return nil unless response.status == 200 + # The status check is required for private commissions, which return 404 + + response.parse + end + + def profile_url + return nil if artist_name.blank? + "https://skeb.jp/@#{artist_name}" + end + + def artist_name + url[PROFILE_URL, :artist_name] + end + + def display_name + page&.at("title")&.text&.match(/.*by (.*?) \| skeb/i).to_a[1] + end + + def other_names + [display_name].compact.uniq + end + + def artist_commentary_desc + # skeb "titles" are not needed: it's just the first few characters of the description + return if page.blank? + page.at("[property='og:description']")["content"] + end + + def client_response + return if page.blank? + page.text[/window\.__NUXT__=.*,thanks:"(.*?)",/, 1]&.gsub(/\\n/, "\n") + end + + def dtext_artist_commentary_desc + if client_response.present? && artist_commentary_desc.present? + "h5. Original Request:\n#{artist_commentary_desc}\n\nh5. Client Response:\n#{client_response}" + else + artist_commentary_desc + end + end + end + end +end diff --git a/test/unit/sources/skeb_test.rb b/test/unit/sources/skeb_test.rb new file mode 100644 index 000000000..35539abfd --- /dev/null +++ b/test/unit/sources/skeb_test.rb @@ -0,0 +1,75 @@ +require 'test_helper' + +module Sources + class SkebTest < ActiveSupport::TestCase + context "The source for a skeb picture" do + setup do + @site = Sources::Strategies.find("https://skeb.jp/@kai_chiisame/works/6") + end + + should "get the artist name" do + assert_equal("kai_chiisame", @site.artist_name) + end + + should "get the artist commentary" do + commentary = <<~COMM.chomp + 初めまして、先日アピールを頂きましたのでリクエストさせて頂きます。 + + 〇キャラ +  東方の東風谷早苗さん + + 〇内容 +  ・水着や薄着などの若干セクシーめ・肌色多めな方向性で、細部は絵師さんにお任せ +  ・念のためNSFW指定にしましたがエロでなくていいです + + ご検討お願いします。 + COMM + + assert_equal(commentary, @site.artist_commentary_desc) + end + + should "get profile url" do + assert_equal("https://skeb.jp/@kai_chiisame", @site.profile_url) + end + + should "get the image url" do + assert_equal("https://skeb.imgix.net/requests/229088_2?bg=%23fff&auto=format&w=800&s=9cac8b76c0838f2df4f19ebc41c1ae0a", @site.image_url) + end + + should "get the canonical url" do + assert_equal("https://skeb.jp/@kai_chiisame/works/6", @site.canonical_url) + end + + should "find the correct artist" do + artist = FactoryBot.create(:artist, name: "kai_chiisame", url_string: @site.url) + assert_equal([artist], @site.artists) + end + + should "not fail" do + assert_nothing_raised { @site.to_h } + end + end + + context "A private or non-existent skeb url" do + setup do + @site = Sources::Strategies.find("https://skeb.jp/@kai_chiisame/works/2") + end + + should "not raise anything" do + assert_nothing_raised { @site.to_h } + end + + should "still find the right artist" do + artist = FactoryBot.create(:artist, name: "kai_chiisame", url_string: @site.url) + assert_equal([artist], @site.artists) + end + end + + context "normalizing for source" do + should "avoid normalizing unnormalizable urls" do + bad_source = "https://skeb.imgix.net/requests/229088_2?bg=%23fff&auto=format&w=800&s=9cac8b76c0838f2df4f19ebc41c1ae0a" + assert_equal(bad_source, Sources::Strategies.normalize_source(bad_source)) + end + end + end +end