Files
danbooru/app/logical/pixiv_api_client.rb
2017-07-12 15:52:48 -07:00

188 lines
6.9 KiB
Ruby

class PixivApiClient
API_VERSION = "1"
CLIENT_ID = "bYGKuGVw91e0NMfPGp44euvGt59s"
CLIENT_SECRET = "HP3RmkgAmEGro0gn1x9ioawQE8WMfvLXDz3ZqxpK"
# Tools to not include in the tags list. We don't tag digital media, so
# including these results in bad translated tags suggestions.
TOOLS_BLACKLIST = %w[
Photoshop Illustrator Fireworks Flash Painter PaintShopPro pixiv\ Sketch
CLIP\ STUDIO\ PAINT IllustStudio ComicStudio RETAS\ STUDIO SAI PhotoStudio
Pixia NekoPaint PictBear openCanvas ArtRage Expression Inkscape GIMP
CGillust COMICWORKS MS_Paint EDGE AzPainter AzPainter2 AzDrawing
PicturePublisher SketchBookPro Processing 4thPaint GraphicsGale mdiapp
Paintgraphic AfterEffects drawr CLIP\ PAINT\ Lab FireAlpaca Pixelmator
AzDrawing2 MediBang\ Paint Krita ibisPaint Procreate Live2D
Lightwave3D Shade Poser STRATA AnimationMaster XSI CARRARA CINEMA4D Maya
3dsMax Blender ZBrush Metasequoia Sunny3D Bryce Vue Hexagon\ King SketchUp
VistaPro Sculptris Comi\ Po! modo DAZ\ Studio 3D-Coat
]
class Error < Exception ; end
class WorksResponse
attr_reader :json, :pages, :name, :moniker, :user_id, :page_count, :tags
attr_reader :artist_commentary_title, :artist_commentary_desc
def initialize(json)
# Sample response:
# {
# "status": "success",
# "response": [
# {
# "id": 49270482,
# "title": "ツイログ",
# "caption": null,
# "tags": [
# "神崎蘭子",
# "双葉杏",
# "アイドルマスターシンデレラガールズ",
# "Star!!",
# "アイマス5000users入り"
# ],
# "tools": [
# "CLIP STUDIO PAINT"
# ],
# "image_urls": {
# "large": "http://i3.pixiv.net/img-original/img/2015/03/14/17/53/32/49270482_p0.jpg"
# },
# "width": 1200,
# "height": 951,
# "stats": {
# "scored_count": 8247,
# "score": 81697,
# "views_count": 191630,
# "favorited_count": {
# "public": 7804,
# "private": 745
# },
# "commented_count": 182
# },
# "publicity": 0,
# "age_limit": "all-age",
# "created_time": "2015-03-14 17:53:32",
# "reuploaded_time": "2015-03-14 17:53:32",
# "user": {
# "id": 341433,
# "account": "nardack",
# "name": "Nardack",
# "is_following": false,
# "is_follower": false,
# "is_friend": false,
# "is_premium": null,
# "profile_image_urls": {
# "px_50x50": "http://i1.pixiv.net/img19/profile/nardack/846482_s.jpg"
# },
# "stats": null,
# "profile": null
# },
# "is_manga": true,
# "is_liked": false,
# "favorite_id": 0,
# "page_count": 2,
# "book_style": "none",
# "type": "illustration",
# "metadata": {
# "pages": [
# {
# "image_urls": {
# "large": "http://i3.pixiv.net/img-original/img/2015/03/14/17/53/32/49270482_p0.jpg",
# "medium": "http://i3.pixiv.net/c/1200x1200/img-master/img/2015/03/14/17/53/32/49270482_p0_master1200.jpg"
# }
# },
# {
# "image_urls": {
# "large": "http://i3.pixiv.net/img-original/img/2015/03/14/17/53/32/49270482_p1.jpg",
# "medium": "http://i3.pixiv.net/c/1200x1200/img-master/img/2015/03/14/17/53/32/49270482_p1_master1200.jpg"
# }
# }
# ]
# },
# "content_type": null
# }
# ],
# "count": 1
# }
@json = json
@name = json["user"]["name"]
@user_id = json["user"]["id"]
@moniker = json["user"]["account"]
@page_count = json["page_count"].to_i
@artist_commentary_title = json["title"].to_s
@artist_commentary_desc = json["caption"].to_s
@tags = json["tags"].reject {|x| x =~ /^http:/}
@tags += json["tools"] - TOOLS_BLACKLIST
if page_count > 1
@pages = json["metadata"]["pages"].map {|x| x["image_urls"]["large"]}
else
@pages = [json["image_urls"]["large"]]
end
end
end
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/v#{API_VERSION}/works/#{illust_id.to_i}.json")
url.query = URI.encode_www_form(params)
json = nil
resp = HTTParty.get(url, Danbooru.config.httparty_options)
if resp.success?
json = parse_api_json(resp.body)
else
raise Error.new("Pixiv API call failed (status=#{resp.code} body=#{resp.body})")
end
WorksResponse.new(json["response"][0])
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
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 = "https://oauth.secure.pixiv.net/auth/token"
resp = HTTParty.post(url, Danbooru.config.httparty_options.merge(body: params, headers: headers))
if resp.success?
json = JSON.parse(resp.body)
access_token = json["response"]["access_token"]
else
raise Error.new("Pixiv API access token call failed (status=#{resp.code} body=#{resp.body})")
end
access_token
end
end
end