nicoseiga: fix inability to login to nicoseiga.

NicoSeiga changed it so that on every login, you must enter a 2FA code
sent by email. This broke the NicoSeiga strategy. The fix is to just use
a static session cookie instead (and hope it doesn't expire, and isn't
tied to an IP).

The `nico_seiga_login` and `nico_seiga_password` config settings have
been removed from config/danbooru_default_config.rb and replaced by
`nico_seiga_user_session`. If you run your own Danbooru instance, you
will have to update your config file manually.
This commit is contained in:
evazion
2022-02-22 12:23:01 -06:00
parent c5777f360e
commit 7b009cc893
4 changed files with 20 additions and 24 deletions

View File

@@ -47,8 +47,7 @@ jobs:
DANBOORU_PIXIV_PHPSESSID: ${{ secrets.DANBOORU_PIXIV_PHPSESSID }} DANBOORU_PIXIV_PHPSESSID: ${{ secrets.DANBOORU_PIXIV_PHPSESSID }}
DANBOORU_NIJIE_LOGIN: ${{ secrets.DANBOORU_NIJIE_LOGIN }} DANBOORU_NIJIE_LOGIN: ${{ secrets.DANBOORU_NIJIE_LOGIN }}
DANBOORU_NIJIE_PASSWORD: ${{ secrets.DANBOORU_NIJIE_PASSWORD }} DANBOORU_NIJIE_PASSWORD: ${{ secrets.DANBOORU_NIJIE_PASSWORD }}
DANBOORU_NICO_SEIGA_LOGIN: ${{ secrets.DANBOORU_NICO_SEIGA_LOGIN }} DANBOORU_NICO_SEIGA_USER_SESSION: ${{ secrets.DANBOORU_NICO_SEIGA_USER_SESSION }}
DANBOORU_NICO_SEIGA_PASSWORD: ${{ secrets.DANBOORU_NICO_SEIGA_PASSWORD }}
DANBOORU_TUMBLR_CONSUMER_KEY: ${{ secrets.DANBOORU_TUMBLR_CONSUMER_KEY }} DANBOORU_TUMBLR_CONSUMER_KEY: ${{ secrets.DANBOORU_TUMBLR_CONSUMER_KEY }}
DANBOORU_DEVIANTART_CLIENT_ID: ${{ secrets.DANBOORU_DEVIANTART_CLIENT_ID }} DANBOORU_DEVIANTART_CLIENT_ID: ${{ secrets.DANBOORU_DEVIANTART_CLIENT_ID }}
DANBOORU_DEVIANTART_CLIENT_SECRET: ${{ secrets.DANBOORU_DEVIANTART_CLIENT_SECRET }} DANBOORU_DEVIANTART_CLIENT_SECRET: ${{ secrets.DANBOORU_DEVIANTART_CLIENT_SECRET }}

View File

@@ -5,11 +5,12 @@ class NicoSeigaApiClient
extend Memoist extend Memoist
XML_API = "https://seiga.nicovideo.jp/api" XML_API = "https://seiga.nicovideo.jp/api"
attr_reader :http attr_reader :http, :user_session
def initialize(work_id:, type:, http: Danbooru::Http.new) def initialize(work_id:, type:, user_session: Danbooru.config.nico_seiga_user_session, http: Danbooru::Http.new)
@work_id = work_id @work_id = work_id
@work_type = type @work_type = type
@user_session = user_session
@http = http @http = http
end end
@@ -60,7 +61,7 @@ class NicoSeigaApiClient
api_response = JSON.parse(resp)["target_image"] api_response = JSON.parse(resp)["target_image"]
when "manga" when "manga"
resp = http.cache(1.minute).get("#{XML_API}/theme/info?id=#{@work_id}") resp = get("#{XML_API}/theme/info?id=#{@work_id}")
return {} if resp.blank? || resp.code.to_i == 404 return {} if resp.blank? || resp.code.to_i == 404
api_response = Hash.from_xml(resp.to_s)["response"]["theme"] api_response = Hash.from_xml(resp.to_s)["response"]["theme"]
end end
@@ -79,26 +80,24 @@ class NicoSeigaApiClient
end end
def user_api_response(user_id) def user_api_response(user_id)
resp = http.cache(1.minute).get("#{XML_API}/user/info?id=#{user_id}") resp = get("#{XML_API}/user/info?id=#{user_id}")
return {} if resp.blank? || resp.code.to_i == 404 return {} if resp.blank? || resp.code.to_i == 404
Hash.from_xml(resp.to_s)["response"]["user"] Hash.from_xml(resp.to_s)["response"]["user"]
end end
def login def cookies
form = { {
mail_tel: Danbooru.config.nico_seiga_login, skip_fetish_warning: "1",
password: Danbooru.config.nico_seiga_password user_session: user_session,
} }
# XXX should fail gracefully instead of raising exception
resp = http.cache(1.hour).post("https://account.nicovideo.jp/login/redirector?site=seiga", form: form)
raise "NicoSeiga login failed (status=#{resp.status})" if resp.status != 200
http
end end
def get(url) def get(url)
login.cache(1.minute).get(url) http.cookies(cookies).cache(1.minute).get(url)
end
def head(url)
http.cookies(cookies).cache(1.minute).head(url)
end end
memoize :api_response, :manga_api_response, :user_api_response memoize :api_response, :manga_api_response, :user_api_response

View File

@@ -53,7 +53,7 @@ module Sources
PROFILE_PAGE = %r{\Ahttps?://seiga\.nicovideo\.jp/user/illust/(?<artist_id>\d+)}i PROFILE_PAGE = %r{\Ahttps?://seiga\.nicovideo\.jp/user/illust/(?<artist_id>\d+)}i
def self.enabled? def self.enabled?
Danbooru.config.nico_seiga_login.present? && Danbooru.config.nico_seiga_password.present? Danbooru.config.nico_seiga_user_session.present?
end end
def domains def domains
@@ -79,7 +79,7 @@ module Sources
def image_url_for(url) def image_url_for(url)
return url if api_client.blank? return url if api_client.blank?
resp = api_client.login.head(url) resp = api_client.head(url)
if resp.uri.to_s =~ %r{https?://.+/(\w+/\d+/\d+)\z}i if resp.uri.to_s =~ %r{https?://.+/(\w+/\d+/\d+)\z}i
"https://lohas.nicoseiga.jp/priv/#{$1}" "https://lohas.nicoseiga.jp/priv/#{$1}"
else else

View File

@@ -265,11 +265,9 @@ module Danbooru
nil nil
end end
def nico_seiga_login # Your NicoSeiga "user_session" cookie. Login to NicoSeiga then use the
nil # devtools to find the "user_session" cookie.
end def nico_seiga_user_session
def nico_seiga_password
nil nil
end end