first cut implementation at using public pixiv api
This commit is contained in:
67
app/logical/pixiv_api_client.rb
Normal file
67
app/logical/pixiv_api_client.rb
Normal file
@@ -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
|
||||||
@@ -48,8 +48,8 @@ module Sources
|
|||||||
moniker = get_moniker_from_url
|
moniker = get_moniker_from_url
|
||||||
else
|
else
|
||||||
illust_id = illust_id_from_url(url)
|
illust_id = illust_id_from_url(url)
|
||||||
get_metadata_from_spapi!(illust_id) do |metadata|
|
get_metadata_from_papi!(illust_id) do |metadata|
|
||||||
moniker = metadata[24]
|
moniker = metadata[:moniker]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ module Sources
|
|||||||
end
|
end
|
||||||
|
|
||||||
def rewrite_thumbnails(thumbnail_url, is_manga=nil)
|
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_medium_ugoiras(thumbnail_url)
|
||||||
thumbnail_url = rewrite_old_small_and_medium_images(thumbnail_url, is_manga)
|
thumbnail_url = rewrite_old_small_and_medium_images(thumbnail_url, is_manga)
|
||||||
return thumbnail_url
|
return thumbnail_url
|
||||||
@@ -130,8 +130,8 @@ module Sources
|
|||||||
# => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1.
|
# => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1.
|
||||||
|
|
||||||
illust_id = illust_id_from_url(@url)
|
illust_id = illust_id_from_url(@url)
|
||||||
get_metadata_from_spapi!(illust_id) do |metadata|
|
get_metadata_from_papi!(illust_id) do |metadata|
|
||||||
file_ext = metadata[2]
|
file_ext = metadata[:file_ext]
|
||||||
thumbnail_url += file_ext
|
thumbnail_url += file_ext
|
||||||
# => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1.png
|
# => http://i1.pixiv.net/img-original/img/2014/10/02/13/51/23/46304396_p1.png
|
||||||
end
|
end
|
||||||
@@ -164,8 +164,8 @@ module Sources
|
|||||||
if thumbnail_url =~ %r!/img/#{MONIKER}/\d+_[ms]\.#{EXT}!i
|
if thumbnail_url =~ %r!/img/#{MONIKER}/\d+_[ms]\.#{EXT}!i
|
||||||
if is_manga.nil?
|
if is_manga.nil?
|
||||||
illust_id = illust_id_from_url(@url)
|
illust_id = illust_id_from_url(@url)
|
||||||
get_metadata_from_spapi!(illust_id) do |metadata|
|
get_metadata_from_papi!(illust_id) do |metadata|
|
||||||
page_count = metadata[19].to_i || 1
|
page_count = metadata[:page_count] || 1
|
||||||
is_manga = page_count > 1
|
is_manga = page_count > 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -314,53 +314,21 @@ module Sources
|
|||||||
"http://www.pixiv.net/member_illust.php?mode=medium&illust_id=#{illust_id}"
|
"http://www.pixiv.net/member_illust.php?mode=medium&illust_id=#{illust_id}"
|
||||||
end
|
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.
|
# Refer to http://danbooru.donmai.us/wiki_pages/58938 for documentation on the Pixiv API.
|
||||||
def get_metadata_from_spapi!(illust_id)
|
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)}"
|
spapi_url = "http://spapi.pixiv.net/iphone/illust.php?illust_id=#{illust_id}&PHPSESSID=#{PixivWebAgent.phpsessid(agent)}"
|
||||||
|
|
||||||
agent.get(spapi_url) do |response|
|
agent.get(spapi_url) do |response|
|
||||||
metadata = CSV.parse(response.content.force_encoding("UTF-8")).first
|
metadata = CSV.parse(response.content.force_encoding("UTF-8")).first
|
||||||
|
|
||||||
validate_spapi_metadata!(metadata)
|
|
||||||
yield metadata
|
yield metadata
|
||||||
end
|
end
|
||||||
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)
|
def illust_id_from_url(url)
|
||||||
# http://img18.pixiv.net/img/evazion/14901720.png
|
# http://img18.pixiv.net/img/evazion/14901720.png
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user