From 0b5ed163feff937b978a81d4ee9b38e6e7c0b22a Mon Sep 17 00:00:00 2001 From: evazion Date: Tue, 21 Nov 2017 10:14:32 -0600 Subject: [PATCH] Fix #3395: fix pixiv API exception when uploading bad pixiv id images. Fixes an exception when attempting to upload a Pixiv image from a deleted work. The download strategy tries to fetch the source data in the course of rewriting the URL, which fails if the work has been deleted from Pixiv. Raise a BadIDError and leave the URL as-is (don't rewrite it). --- .../downloads/rewrite_strategies/pixiv.rb | 2 ++ app/logical/pixiv_api_client.rb | 18 +++++---------- test/unit/downloads/pixiv_test.rb | 23 +++++++++++++++++-- test/unit/sources/pixiv_test.rb | 8 +++++++ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/app/logical/downloads/rewrite_strategies/pixiv.rb b/app/logical/downloads/rewrite_strategies/pixiv.rb index 3d8316d1f..863258195 100644 --- a/app/logical/downloads/rewrite_strategies/pixiv.rb +++ b/app/logical/downloads/rewrite_strategies/pixiv.rb @@ -27,6 +27,8 @@ module Downloads data[:ugoira_content_type] = source.ugoira_content_type end + return [url, headers, data] + rescue PixivApiClient::BadIDError return [url, headers, data] end diff --git a/app/logical/pixiv_api_client.rb b/app/logical/pixiv_api_client.rb index 59830d78d..7c9e50a73 100644 --- a/app/logical/pixiv_api_client.rb +++ b/app/logical/pixiv_api_client.rb @@ -19,6 +19,7 @@ class PixivApiClient ] class Error < Exception ; end + class BadIDError < Error ; end class WorksResponse attr_reader :json, :pages, :name, :moniker, :user_id, :page_count, :tags @@ -142,24 +143,17 @@ class PixivApiClient url = "https://public-api.secure.pixiv.net/v#{API_VERSION}/works/#{illust_id.to_i}.json" resp = HTTParty.get(url, Danbooru.config.httparty_options.deep_merge(query: params, headers: headers)) body = resp.body.force_encoding("utf-8") + json = JSON.parse(body) if resp.success? - json = parse_api_json(body) WorksResponse.new(json["response"][0]) + elsif json["status"] == "failure" && json.dig("errors", "system", "message") =~ /対象のイラストは見つかりませんでした。/ + raise BadIDError.new("Pixiv ##{illust_id} not found: work was deleted, made private, or ID is invalid.") else raise Error.new("Pixiv API call failed (status=#{resp.code} body=#{body})") end - end - -private - def parse_api_json(body) - json = JSON.parse(body) - - if json["status"] != "success" - raise Error.new("Pixiv API call failed (status=#{json['status']} body=#{body})") - end - - json + rescue JSON::ParserError + raise Error.new("Pixiv API call failed (status=#{resp.code} body=#{body})") end def access_token diff --git a/test/unit/downloads/pixiv_test.rb b/test/unit/downloads/pixiv_test.rb index cd485578b..1dbb5c532 100644 --- a/test/unit/downloads/pixiv_test.rb +++ b/test/unit/downloads/pixiv_test.rb @@ -43,8 +43,6 @@ module Downloads end end - - # Test a new illustration (one uploaded after 2014-09-30). New illustrations # must use /img-original/ for full size URLs. Old /imgXX/img/username/ style URLs # don't work for images uploaded after this date. @@ -112,6 +110,27 @@ module Downloads end end + context "downloading a bad id image" do + setup do + @bad_id_full = "https://i.pximg.net/img-original/img/2017/11/22/01/06/44/65991677_p0.png" + @bad_id_sample = "https://i.pximg.net/c/600x600/img-master/img/2017/11/22/01/06/44/65991677_p0_master1200.jpg" + end + + should "not raise an error when rewriting the url" do + assert_nothing_raised { assert_not_rewritten(@bad_id_full) } + end + + should_eventually "rewrite bad id samples to full size" do + assert_rewritten(@bad_id_full, @bad_id_sample) + end + + # XXX This may fail someday. Pixiv doesn't delete bad id images right + # away, but they may be deleted eventually. + should "download the image" do + assert_downloaded(21440, @bad_id_full) + end + end + context "downloading a ugoira" do setup do @medium_page = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364" diff --git a/test/unit/sources/pixiv_test.rb b/test/unit/sources/pixiv_test.rb index 34feca41b..58eb39aef 100644 --- a/test/unit/sources/pixiv_test.rb +++ b/test/unit/sources/pixiv_test.rb @@ -127,6 +127,14 @@ module Sources end end + context "fetching source data for a deleted work" do + should "raise a bad id error" do + assert_raise(::PixivApiClient::BadIDError) do + get_source("https://i.pximg.net/img-original/img/2017/11/22/01/06/44/65991677_p0.png") + end + end + end + context "fetching the commentary" do should "work when the description is blank" do get_source("https://www.pixiv.net/member_illust.php?mode=medium&illust_id=65981746")