/app/logical/source/extractor/nijie.rb

https://github.com/r888888888/danbooru · Ruby · 174 lines · 137 code · 34 blank · 3 comment · 22 complexity · a2ab206050b8a824eae2bb78bb2c369a MD5 · raw file

  1. # frozen_string_literal: true
  2. # @see Source::URL::Nijie
  3. module Source
  4. class Extractor
  5. class Nijie < Source::Extractor
  6. def self.enabled?
  7. Danbooru.config.nijie_login.present? && Danbooru.config.nijie_password.present?
  8. end
  9. def match?
  10. Source::URL::Nijie === parsed_url
  11. end
  12. def image_urls
  13. if parsed_url.image_url?
  14. [parsed_url.full_image_url]
  15. else
  16. image_urls_from_page
  17. end
  18. end
  19. def image_urls_from_page
  20. if doujin?
  21. images = page&.search("#dojin_left .left img").to_a.pluck("src")
  22. images += page&.search("#dojin_diff img.mozamoza").to_a.pluck("data-original")
  23. else
  24. images = page&.search("div#gallery a > .mozamoza").to_a.pluck("src")
  25. end
  26. images.map { |img| Source::URL.parse("https:#{img}").full_image_url }
  27. end
  28. def page_url
  29. return nil if illust_id.blank?
  30. "https://nijie.info/view.php?id=#{illust_id}"
  31. end
  32. def profile_url
  33. return nil if artist_id.blank?
  34. "https://nijie.info/members.php?id=#{artist_id}"
  35. end
  36. def artist_name
  37. if doujin?
  38. page&.at("#dojin_left .right a[href*='members.php?id=']")&.text
  39. else
  40. page&.at("a.name")&.text
  41. end
  42. end
  43. def artist_commentary_title
  44. if doujin?
  45. page&.search("#dojin_text p.title")&.text
  46. else
  47. page&.search("h2.illust_title")&.text
  48. end
  49. end
  50. def artist_commentary_desc
  51. if doujin?
  52. page&.search("#dojin_text p:not(.title)")&.to_html
  53. else
  54. page&.search('#illust_text > p')&.to_html
  55. end
  56. end
  57. def tags
  58. links = page&.search("div#view-tag a") || []
  59. search_links = links.select do |node|
  60. node["href"] =~ /search(?:_dojin)?\.php/
  61. end
  62. search_links.map do |node|
  63. [node.inner_text, "https://nijie.info" + node.attr("href")]
  64. end
  65. end
  66. def tag_name
  67. "nijie" + artist_id.to_s
  68. end
  69. def self.to_dtext(text)
  70. text = text.to_s.gsub(/\r\n|\r/, "<br>")
  71. dtext = DText.from_html(text) do |element|
  72. if element.name == "a" && element["href"]&.start_with?("/jump.php")
  73. element["href"] = element.text
  74. end
  75. end
  76. dtext.strip
  77. end
  78. def illust_id
  79. parsed_url.work_id || parsed_referer&.work_id
  80. end
  81. def artist_id_from_url
  82. parsed_url.user_id || parsed_referer&.user_id
  83. end
  84. def artist_id_from_page
  85. page&.search("a.name")&.first&.attr("href")&.match(/members\.php\?id=(\d+)/) { $1.to_i }
  86. end
  87. def artist_id
  88. artist_id_from_url || artist_id_from_page
  89. end
  90. def doujin?
  91. page&.at("#dojin_left").present?
  92. end
  93. def page
  94. return nil if page_url.blank? || client.blank?
  95. response = client.cache(1.minute).get(page_url)
  96. if response.status != 200 || response.parse.search("#login_illust").present?
  97. clear_cached_session_cookie!
  98. else
  99. response.parse
  100. end
  101. end
  102. memoize :page
  103. def client
  104. return nil if cached_session_cookie.nil?
  105. http.cookies(R18: 1, **cached_session_cookie)
  106. end
  107. def http
  108. super.timeout(60).use(retriable: { max_retries: 20 })
  109. end
  110. # { "NIJIEIJIEID" => "5ca3f816c0c1f3e647940b08b8ab7a45", "nijie_tok" => <long-base64-string> }
  111. def cached_session_cookie
  112. Cache.get("nijie-session-cookie", 60.minutes, skip_nil: true) do
  113. session_cookie
  114. end
  115. end
  116. def clear_cached_session_cookie!
  117. flush_cache # clear memoized session cookie
  118. Cache.delete("nijie-session-cookie")
  119. end
  120. def session_cookie
  121. login_page = http.get("https://nijie.info/login.php").parse
  122. form = {
  123. email: Danbooru.config.nijie_login,
  124. password: Danbooru.config.nijie_password,
  125. url: login_page.at("input[name='url']")&.fetch("value"),
  126. save: "on",
  127. ticket: ""
  128. }
  129. response = http.post("https://nijie.info/login_int.php", form: form)
  130. if response.status == 200
  131. response.cookies.cookies.map { |cookie| [cookie.name, cookie.value] }.to_h
  132. else
  133. DanbooruLogger.info "Nijie login failed (#{url}, #{response.status})"
  134. nil
  135. end
  136. end
  137. memoize :client, :cached_session_cookie
  138. end
  139. end
  140. end