Files
danbooru/app/logical/nico_seiga_api_client.rb
evazion 05d7355ebb danbooru::http: support automatically following redirects.
Replace http.rb's builtin redirect following option with our own
redirect follower. This fixes an issue with http.rb losing cookies after
following a redirect.
2020-06-21 05:22:57 -05:00

110 lines
2.9 KiB
Ruby

class NicoSeigaApiClient
extend Memoist
XML_API = "https://seiga.nicovideo.jp/api"
attr_reader :http
# XXX temp disable following redirects.
def initialize(work_id:, type:)
@work_id = work_id
@work_type = type
@http = Danbooru::Http.new
@http.http.default_options.features.reject! { |name, _| name == :redirector }
end
def image_ids
if @work_type == "illust"
[api_response["id"]]
elsif @work_type == "manga"
manga_api_response.map do |x|
case x["meta"]["source_url"]
when %r{/thumb/(\d+)\w}i then Regexp.last_match(1)
when %r{nicoseiga\.cdn\.nimg\.jp/drm/image/\w+/(\d+)\w}i then Regexp.last_match(1)
end
end
end
end
def title
api_response["title"]
end
def description
api_response["description"]
end
def tags
api_response.dig("tag_list", "tag").to_a.map { |t| t["name"] }.compact
end
def user_id
api_response["user_id"]
end
def user_name
if @work_type == "illust"
api_response["nickname"]
elsif @work_type == "manga"
user_api_response(user_id)["nickname"]
end
end
def api_response
if @work_type == "illust"
resp = get("https://sp.seiga.nicovideo.jp/ajax/seiga/im#{@work_id}")
return {} if resp.blank? || resp.code.to_i == 404
api_response = JSON.parse(resp)["target_image"]
elsif @work_type == "manga"
resp = http.cache(1.minute).get("#{XML_API}/theme/info?id=#{@work_id}")
return {} if resp.blank? || resp.code.to_i == 404
api_response = Hash.from_xml(resp.to_s)["response"]["theme"]
end
api_response || {}
rescue JSON::ParserError
{}
end
def manga_api_response
resp = get("https://ssl.seiga.nicovideo.jp/api/v1/app/manga/episodes/#{@work_id}/frames")
return {} if resp.blank? || resp.code.to_i == 404
JSON.parse(resp)["data"]["result"]
rescue JSON::ParserError
{}
end
def user_api_response(user_id)
resp = http.cache(1.minute).get("#{XML_API}/user/info?id=#{user_id}")
return {} if resp.blank? || resp.code.to_i == 404
Hash.from_xml(resp.to_s)["response"]["user"]
end
def get(url)
cookie_header = Cache.get("nicoseiga-cookie-header") || regenerate_cookie_header
resp = http.headers({Cookie: cookie_header}).cache(1.minute).get(url)
if resp.headers["Location"] =~ %r{seiga\.nicovideo\.jp/login/}i
cookie_header = regenerate_cookie_header
resp = http.headers({Cookie: cookie_header}).cache(1.minute).get(url)
end
resp
end
def regenerate_cookie_header
form = {
mail_tel: Danbooru.config.nico_seiga_login,
password: Danbooru.config.nico_seiga_password
}
resp = http.post("https://account.nicovideo.jp/api/v1/login", form: form)
cookies = resp.cookies.map { |c| c.name + "=" + c.value }
cookies << "accept_fetish_warning=2"
Cache.put("nicoseiga-cookie-header", cookies.join(";"), 1.week)
end
memoize :api_response, :manga_api_response, :user_api_response
end