diff --git a/app/logical/pixiv_api_client.rb b/app/logical/pixiv_api_client.rb new file mode 100644 index 000000000..6500a18e2 --- /dev/null +++ b/app/logical/pixiv_api_client.rb @@ -0,0 +1,67 @@ +class PixivApiClient + CLIENT_ID = "bYGKuGVw91e0NMfPGp44euvGt59s" + CLIENT_SECRET = "HP3RmkgAmEGro0gn1x9ioawQE8WMfvLXDz3ZqxpK" + + def works(illust_id) + headers = { + "Referer" => "http://www.pixiv.net", + "User-Agent" => "#{Danbooru.config.safe_app_name}/#{Danbooru.config.version}", + "Content-Type" => "application/x-www-form-urlencoded", + "Authorization" => "Bearer #{access_token}" + } + params = { + "image_sizes" => "large", + "include_stats" => "true" + } + url = URI.parse("https://public-api.secure.pixiv.net/v1/works/#{illust_id.to_i}.json") + url.query = URI.encode_www_form(params) + json = nil + + Net::HTTP.start(url.host, url.port, :use_ssl => true) do |http| + resp = http.request_get(url.request_uri, headers) + if resp.is_a?(Net::HTTPSuccess) + json = JSON.parse(resp.body) + end + end + + map(json) + end + +private + + def map(raw_json) + { + :moniker => raw_json["response"][0]["user"]["account"], + :file_ext => File.extname(raw_json["response"][0]["image_urls"]["large"]), + :page_count => raw_json["response"][0]["page_count"] + } + end + + def access_token + Cache.get("pixiv-papi-access-token", 3000) do + access_token = nil + headers = { + "Referer" => "http://www.pixiv.net" + } + params = { + "username" => Danbooru.config.pixiv_login, + "password" => Danbooru.config.pixiv_password, + "grant_type" => "password", + "client_id" => CLIENT_ID, + "client_secret" => CLIENT_SECRET + } + url = URI.parse("https://oauth.secure.pixiv.net/auth/token") + + Net::HTTP.start(url.host, url.port, :use_ssl => true) do |http| + resp = http.request_post(url.request_uri, URI.encode_www_form(params), headers) + + if resp.is_a?(Net::HTTPSuccess) + json = JSON.parse(resp.body) + access_token = json["response"]["access_token"] + end + end + + access_token + end + end +end \ No newline at end of file diff --git a/app/logical/sources/strategies/pixiv.rb b/app/logical/sources/strategies/pixiv.rb index 92d97ad01..8847f6397 100644 --- a/app/logical/sources/strategies/pixiv.rb +++ b/app/logical/sources/strategies/pixiv.rb @@ -48,8 +48,8 @@ module Sources moniker = get_moniker_from_url else illust_id = illust_id_from_url(url) - get_metadata_from_spapi!(illust_id) do |metadata| - moniker = metadata[24] + get_metadata_from_papi!(illust_id) do |metadata| + moniker = metadata[:moniker] end end @@ -81,7 +81,7 @@ module Sources end def rewrite_thumbnails(thumbnail_url, is_manga=nil) - # thumbnail_url = rewrite_new_medium_images(thumbnail_url) + thumbnail_url = rewrite_new_medium_images(thumbnail_url) thumbnail_url = rewrite_medium_ugoiras(thumbnail_url) thumbnail_url = rewrite_old_small_and_medium_images(thumbnail_url, is_manga) return thumbnail_url @@ -130,8 +130,8 @@ module Sources # => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1. illust_id = illust_id_from_url(@url) - get_metadata_from_spapi!(illust_id) do |metadata| - file_ext = metadata[2] + get_metadata_from_papi!(illust_id) do |metadata| + file_ext = metadata[:file_ext] thumbnail_url += file_ext # => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1.png end @@ -164,8 +164,8 @@ module Sources if thumbnail_url =~ %r!/img/#{MONIKER}/\d+_[ms]\.#{EXT}!i if is_manga.nil? illust_id = illust_id_from_url(@url) - get_metadata_from_spapi!(illust_id) do |metadata| - page_count = metadata[19].to_i || 1 + get_metadata_from_papi!(illust_id) do |metadata| + page_count = metadata[:page_count] || 1 is_manga = page_count > 1 end end @@ -314,53 +314,21 @@ module Sources "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=#{illust_id}" end + def get_metadata_from_papi!(illust_id) + client = PixivApiClient.new + yield client.works(illust_id) + end + # Refer to http://danbooru.donmai.us/wiki_pages/58938 for documentation on the Pixiv API. def get_metadata_from_spapi!(illust_id) - yield [] - return - spapi_url = "http://spapi.pixiv.net/iphone/illust.php?illust_id=#{illust_id}&PHPSESSID=#{PixivWebAgent.phpsessid(agent)}" agent.get(spapi_url) do |response| metadata = CSV.parse(response.content.force_encoding("UTF-8")).first - - validate_spapi_metadata!(metadata) yield metadata end end - def validate_spapi_metadata!(metadata) - if metadata.nil? - raise Sources::Error.new("Pixiv API returned empty response.") - elsif metadata.size != 31 - raise Sources::Error.new("Pixiv API returned unexpected number of fields.") - end - - illust_id = metadata[0] - file_ext = metadata[2] - page_count = metadata[19] - moniker = metadata[24] - mobile_profile_image = metadata[30] - - if file_ext !~ /#{EXT}/i - raise Sources::Error.new("Pixiv API returned unexpected file extension '#{file_ext}' for pixiv ##{illust_id}.") - elsif moniker !~ /#{MONIKER}/i - raise Sources::Error.new("Pixiv API returned invalid artist moniker '#{moniker}' for pixiv ##{illust_id}.") - elsif page_count.to_s !~ /[0-9]*/i - raise Sources::Error.new("Pixiv API returned invalid page count '#{page_count}' for pixiv ##{illust_id}.") - end - - if mobile_profile_image - # http://i1.pixiv.net/img01/profile/ccz67420/mobile/5042957_80.jpg - profile_regex = %r!i[12]\.pixiv\.net/img\d+/profile/#{MONIKER}/mobile/\d+_\d+\.jpg!i - mobile_moniker = mobile_profile_image.match(profile_regex)[1] - - if mobile_moniker != moniker - raise Sources::Error.new("Pixiv API returned inconsistent artist moniker '#{moniker}' for pixiv ##{illust_id}.") - end - end - end - def illust_id_from_url(url) # http://img18.pixiv.net/img/evazion/14901720.png #