Add anifty.jp support
This commit is contained in:
@@ -216,6 +216,8 @@ module IconHelper
|
|||||||
image_icon_tag("amazon-logo.png", **options)
|
image_icon_tag("amazon-logo.png", **options)
|
||||||
when "Ameblo"
|
when "Ameblo"
|
||||||
image_icon_tag("ameblo-logo.png", **options)
|
image_icon_tag("ameblo-logo.png", **options)
|
||||||
|
when "Anifty"
|
||||||
|
image_icon_tag("anifty-logo.png", **options)
|
||||||
when "ArtStation"
|
when "ArtStation"
|
||||||
image_icon_tag("artstation-logo.png", **options)
|
image_icon_tag("artstation-logo.png", **options)
|
||||||
when "Ask.fm"
|
when "Ask.fm"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ module ArtistFinder
|
|||||||
"ameblo.jp", # https://ameblo.jp/g8set55679
|
"ameblo.jp", # https://ameblo.jp/g8set55679
|
||||||
"ameba.jp", # https://profile.ameba.jp/ameba/kbnr32rbfs
|
"ameba.jp", # https://profile.ameba.jp/ameba/kbnr32rbfs
|
||||||
"anidb.net", # https://anidb.net/creator/65313
|
"anidb.net", # https://anidb.net/creator/65313
|
||||||
|
"anifty.jp", # https://anifty.jp/@unagi189
|
||||||
|
%r{anifty.jp/(?:ja|zh|en)}, # https://anifty.jp/ja/@unagi189
|
||||||
"animenewsnetwork.com", # http://www.animenewsnetwork.com/encyclopedia/people.php?id=46869
|
"animenewsnetwork.com", # http://www.animenewsnetwork.com/encyclopedia/people.php?id=46869
|
||||||
"artstation.com/artist", # http://www.artstation.com/artist/serafleur/
|
"artstation.com/artist", # http://www.artstation.com/artist/serafleur/
|
||||||
"www.artstation.com", # http://www.artstation.com/serafleur/
|
"www.artstation.com", # http://www.artstation.com/serafleur/
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ module Source
|
|||||||
Source::Extractor::Tinami,
|
Source::Extractor::Tinami,
|
||||||
Source::Extractor::Fantia,
|
Source::Extractor::Fantia,
|
||||||
Source::Extractor::Booth,
|
Source::Extractor::Booth,
|
||||||
|
Source::Extractor::Anifty,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Should return true if the extractor is configured correctly. Return false
|
# Should return true if the extractor is configured correctly. Return false
|
||||||
|
|||||||
110
app/logical/source/extractor/anifty.rb
Normal file
110
app/logical/source/extractor/anifty.rb
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# @see Source::URL::Anifty
|
||||||
|
class Source::Extractor
|
||||||
|
class Anifty < Source::Extractor
|
||||||
|
def match?
|
||||||
|
Source::URL::Anifty === parsed_url
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_urls
|
||||||
|
if parsed_url.image_url?
|
||||||
|
[parsed_url.full_image_url].compact
|
||||||
|
else
|
||||||
|
[api_response["imageURL"]].compact
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile_url
|
||||||
|
if artist_name.present?
|
||||||
|
"https://anifty.jp/@#{username}"
|
||||||
|
else
|
||||||
|
parsed_url.profile_url || parsed_referer&.profile_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def username
|
||||||
|
api_response.dig("creator", "userName") || artist_api_response["userName"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def artist_name
|
||||||
|
api_response.dig("creator", "displayName") || artist_api_response.dig("createdTokens", 0, "creatorProfile", "displayNameEN")
|
||||||
|
end
|
||||||
|
|
||||||
|
def other_names
|
||||||
|
other_names = [username]
|
||||||
|
if api_response.present?
|
||||||
|
other_names << api_response.dig("creator", "displayNameJA")
|
||||||
|
elsif artist_api_response
|
||||||
|
other_names << artist_api_response.dig("createdTokens", 0, "creatorProfile", "displayNameJP")
|
||||||
|
end
|
||||||
|
other_names.compact.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
def artist_commentary_title
|
||||||
|
api_response["title"] || api_response["titleJA"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def artist_commentary_desc
|
||||||
|
api_response["description"] || api_response["descriptionJA"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def tags
|
||||||
|
# anifty marketplace uses XHR requests to filter by tags, so there's no url to get
|
||||||
|
api_response["tags"].to_a.map do |tag|
|
||||||
|
[tag["name"], "https://anifty.jp/marketplace"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_url
|
||||||
|
if page_url_from_parsed_urls.present?
|
||||||
|
page_url_from_parsed_urls
|
||||||
|
elsif work_id.present?
|
||||||
|
"https://anifty.jp/creations/#{work_id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_url_from_parsed_urls
|
||||||
|
parsed_url.page_url || parsed_referer&.page_url
|
||||||
|
end
|
||||||
|
|
||||||
|
def work_id
|
||||||
|
parsed_url.work_id || parsed_referer&.work_id || work_id_from_artist_api
|
||||||
|
end
|
||||||
|
|
||||||
|
def work_id_from_artist_api
|
||||||
|
# Try to get the work ID from the artist's list of tokens
|
||||||
|
return nil unless parsed_url.file.present? && parsed_url.work_type == "creation"
|
||||||
|
artist_api_response["createdTokens"].to_a.map do |token|
|
||||||
|
if Source::URL.parse(token["imageURL"])&.file == parsed_url.file
|
||||||
|
return token["creationID"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def artist_hash
|
||||||
|
parsed_url.artist_hash || parsed_referer&.artist_hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_response
|
||||||
|
return {} if work_id.blank?
|
||||||
|
|
||||||
|
resp = http.cache(1.minute).get("https://asia-northeast1-anifty-59655.cloudfunctions.net/api/v2/creations/#{work_id}")
|
||||||
|
return {} if resp.code != 200
|
||||||
|
|
||||||
|
resp.parse.with_indifferent_access
|
||||||
|
end
|
||||||
|
memoize :api_response
|
||||||
|
|
||||||
|
def artist_api_response
|
||||||
|
return {} if artist_hash.blank?
|
||||||
|
|
||||||
|
resp = http.cache(1.minute).get("https://asia-northeast1-anifty-59655.cloudfunctions.net/api/users/#{artist_hash}")
|
||||||
|
return {} if resp.code != 200
|
||||||
|
|
||||||
|
resp.parse.with_indifferent_access
|
||||||
|
end
|
||||||
|
memoize :artist_api_response
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -47,6 +47,7 @@ module Source
|
|||||||
Source::URL::Tumblr,
|
Source::URL::Tumblr,
|
||||||
Source::URL::TwitPic,
|
Source::URL::TwitPic,
|
||||||
Source::URL::Weibo,
|
Source::URL::Weibo,
|
||||||
|
Source::URL::Anifty,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Parse a URL into a subclass of Source::URL, or raise an exception if the URL is not a valid HTTP or HTTPS URL.
|
# Parse a URL into a subclass of Source::URL, or raise an exception if the URL is not a valid HTTP or HTTPS URL.
|
||||||
|
|||||||
62
app/logical/source/url/anifty.rb
Normal file
62
app/logical/source/url/anifty.rb
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Source::URL::Anifty < Source::URL
|
||||||
|
attr_reader :username, :artist_hash, :work_id, :file, :work_type
|
||||||
|
|
||||||
|
def self.match?(url)
|
||||||
|
url.domain == "anifty.jp" || url.host == "anifty.imgix.net" || (url.host == "storage.googleapis.com" && url.path.include?("/anifty-media/"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def site_name
|
||||||
|
"Anifty"
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse
|
||||||
|
case [host, *path_segments]
|
||||||
|
|
||||||
|
# https://anifty.imgix.net/creation/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/20d5ce5b5163a71258e1d0ee152a0347bf40c7da.png?w=660&h=660&fit=crop&crop=focalpoint&fp-x=0.76&fp-y=0.5&fp-z=1&auto=compress
|
||||||
|
# https://anifty.imgix.net/creation/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/48b1409838cf7271413480b8533372844b9f2437.png?w=3840&q=undefined&auto=compress
|
||||||
|
in "anifty.imgix.net", work_type, /0x\w+/ => artist_hash, file
|
||||||
|
@artist_hash = artist_hash
|
||||||
|
@file = file
|
||||||
|
@work_type = work_type
|
||||||
|
|
||||||
|
# https://storage.googleapis.com/anifty-media/creation/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/20d5ce5b5163a71258e1d0ee152a0347bf40c7da.png
|
||||||
|
# https://storage.googleapis.com/anifty-media/profile/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/a6d2c366a3e876ddbf04fc269b63124be18af424.png
|
||||||
|
in "storage.googleapis.com", "anifty-media", work_type, /0x\w+/ => artist_hash, file
|
||||||
|
@artist_hash = artist_hash
|
||||||
|
@file = file
|
||||||
|
@work_type = work_type
|
||||||
|
|
||||||
|
# https://anifty.jp/creations/373
|
||||||
|
# https://anifty.jp/ja/creations/373
|
||||||
|
# https://anifty.jp/zh/creations/373
|
||||||
|
# https://anifty.jp/zh-Hant/creations/373
|
||||||
|
in ("anifty.jp" | "www.anifty.jp"), *, "creations", /\d+/ => work_id
|
||||||
|
@work_id = work_id
|
||||||
|
|
||||||
|
# https://anifty.jp/@hightree
|
||||||
|
# https://anifty.jp/ja/@hightree
|
||||||
|
in ("anifty.jp" | "www.anifty.jp"), *, /@(\w+)/
|
||||||
|
@username = $1
|
||||||
|
|
||||||
|
else
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_url?
|
||||||
|
file.present? && artist_hash.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_image_url
|
||||||
|
"https://storage.googleapis.com/anifty-media/#{work_type}/#{artist_hash}/#{file}" if image_url?
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_url
|
||||||
|
"https://anifty.jp/creations/#{work_id}" if work_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile_url
|
||||||
|
"https://anifty.jp/@#{username}" if username.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -95,7 +95,7 @@ class ArtistURL < ApplicationRecord
|
|||||||
def priority
|
def priority
|
||||||
sites = %w[
|
sites = %w[
|
||||||
Pixiv Twitter
|
Pixiv Twitter
|
||||||
ArtStation Baraag BCY Booth Deviant\ Art Hentai\ Foundry Fantia Foundation Lofter Nico\ Seiga Nijie Pawoo Fanbox Pixiv\ Sketch Plurk Tinami Tumblr Weibo
|
Anifty ArtStation Baraag BCY Booth Deviant\ Art Hentai\ Foundry Fantia Foundation Lofter Nico\ Seiga Nijie Pawoo Fanbox Pixiv\ Sketch Plurk Tinami Tumblr Weibo
|
||||||
Ask.fm Facebook FC2 Gumroad Instagram Ko-fi Livedoor Mihuashi Mixi.jp Patreon Piapro.jp Picarto Privatter Sakura.ne.jp Stickam Skeb Twitch Youtube
|
Ask.fm Facebook FC2 Gumroad Instagram Ko-fi Livedoor Mihuashi Mixi.jp Patreon Piapro.jp Picarto Privatter Sakura.ne.jp Stickam Skeb Twitch Youtube
|
||||||
Amazon Circle.ms DLSite Doujinshi.org Erogamescape Mangaupdates Melonbooks Toranoana Wikipedia
|
Amazon Circle.ms DLSite Doujinshi.org Erogamescape Mangaupdates Melonbooks Toranoana Wikipedia
|
||||||
]
|
]
|
||||||
|
|||||||
BIN
public/images/anifty-logo.png
Normal file
BIN
public/images/anifty-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
43
test/unit/sources/anifty_test.rb
Normal file
43
test/unit/sources/anifty_test.rb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
module Sources
|
||||||
|
class AniftyTest < ActiveSupport::TestCase
|
||||||
|
strategy_should_work(
|
||||||
|
"https://anifty.jp/ja/creations/1500",
|
||||||
|
image_urls: ["https://storage.googleapis.com/anifty-media/creation/0x0913be22dd08f7e092e00d4f8c2f61778dc6df94/a5bb2c63b8a602aba6cfd93d2147bef23b6b9bc2.jpg"],
|
||||||
|
profile_url: "https://anifty.jp/@inamihatoko",
|
||||||
|
page_url: "https://anifty.jp/creations/1500",
|
||||||
|
artist_name: "inami hatoko",
|
||||||
|
other_names: ["inamihatoko", "井波ハトコ"],
|
||||||
|
tags: ["background", "girl"],
|
||||||
|
artist_commentary_title: "Escape",
|
||||||
|
artist_commentary_desc: "Let's get out of there."
|
||||||
|
)
|
||||||
|
|
||||||
|
strategy_should_work(
|
||||||
|
"https://anifty.imgix.net/creation/0x9942a21fdc78fe2c3973d219a1d705a4efd056b4/22f4c9694dd2f1f32b610d1d75a18621c5c2d6d8.jpg?w=3840&q=undefined&auto=compress",
|
||||||
|
image_urls: ["https://storage.googleapis.com/anifty-media/creation/0x9942a21fdc78fe2c3973d219a1d705a4efd056b4/22f4c9694dd2f1f32b610d1d75a18621c5c2d6d8.jpg"],
|
||||||
|
profile_url: "https://anifty.jp/@unagi189",
|
||||||
|
page_url: "https://anifty.jp/creations/1585",
|
||||||
|
artist_name: "yunagi",
|
||||||
|
other_names: ["unagi189", "夕凪"],
|
||||||
|
tags: ["background", "girl", "uniform"],
|
||||||
|
artist_commentary_title: "Sound!",
|
||||||
|
artist_commentary_desc: "This work was created in 2017 and partially modified for exhibition.I created this work with the image of after-school for the girls in the brass band."
|
||||||
|
)
|
||||||
|
|
||||||
|
strategy_should_work(
|
||||||
|
"https://storage.googleapis.com/anifty-media/profile/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/a6d2c366a3e876ddbf04fc269b63124be18af424.png",
|
||||||
|
image_urls: ["https://storage.googleapis.com/anifty-media/profile/0x961d09077b4a9f7a27f6b7ee78cb4c26f0e72c18/a6d2c366a3e876ddbf04fc269b63124be18af424.png"],
|
||||||
|
profile_url: "https://anifty.jp/@hightree",
|
||||||
|
page_url: nil,
|
||||||
|
artist_name: "Knoy Konome",
|
||||||
|
other_names: ["hightree", "木芽のい"],
|
||||||
|
tags: [],
|
||||||
|
artist_commentary_title: nil,
|
||||||
|
artist_commentary_desc: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
strategy_should_work("https://anifty.jp/zh/creations/373123123", deleted: true, profile_url: nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user