Files
danbooru/app/models/artist_url.rb
2022-03-30 22:04:24 -05:00

156 lines
4.1 KiB
Ruby

# frozen_string_literal: true
class ArtistURL < ApplicationRecord
normalize :url, :normalize_url
validates :url, presence: true, uniqueness: { scope: :artist_id }
validate :validate_url_format
validate :validate_url_is_not_duplicate
belongs_to :artist, :touch => true
scope :url_matches, ->(url) { url_attribute_matches(:url, url) }
scope :normalized_url_matches, ->(url) { url_attribute_matches(:normalized_url, url) }
scope :active, -> { where(is_active: true) }
def self.parse_prefix(url)
prefix, url = url.match(/\A(-)?(.*)/)[1, 2]
is_active = prefix.nil?
[is_active, url]
end
def self.normalize_normalized_url(url)
return nil if url.nil?
url = Source::URL.parse(url)&.profile_url || url
url = url.sub(%r{^https://}, "http://")
url = url.gsub(%r{/+\Z}, "")
url + "/"
end
def self.search(params = {})
q = search_attributes(params, :id, :created_at, :updated_at, :url, :normalized_url, :is_active, :artist)
q = q.url_matches(params[:url_matches])
q = q.normalized_url_matches(params[:normalized_url_matches])
case params[:order]
when /\A(id|artist_id|url|normalized_url|is_active|created_at|updated_at)(?:_(asc|desc))?\z/i
dir = $2 || :desc
q = q.order($1 => dir).order(id: :desc)
else
q = q.apply_default_order(params)
end
q
end
def self.url_attribute_matches(attr, url)
if url.blank?
all
elsif url =~ %r{\A/(.*)/\z}
where_regex(attr, $1)
elsif url.include?("*")
where_ilike(attr, url)
else
profile_url = Source::Extractor.find(url).profile_url || url
where(attr => normalize_normalized_url(profile_url))
end
end
def domain
parsed_url&.domain.to_s
end
def site_name
parsed_url&.site_name.to_s
end
# A secondary URL is an artist URL that we don't normally want to display,
# usually because it's redundant with the primary profile URL.
def secondary_url?
case url
when %r{pixiv\.net/stacc}i
true
when %r{pixiv\.net/fanbox}i
true
when %r{twitter\.com/intent}i
true
when %r{lohas\.nicoseiga\.jp}i
true
when %r{(?:www|com|dic)\.nicovideo\.jp}i
true
when %r{pawoo\.net/web/accounts}i
true
when %r{www\.artstation\.com}i
true
when %r{blogimg\.jp}i, %r{image\.blog\.livedoor\.jp}i
true
else
false
end
end
# The sort order of sites in artist URL lists.
def priority
sites = %w[
Pixiv Twitter
ArtStation Baraag BCY Deviant\ Art Hentai\ Foundry Fantia Foundation Lofter Nico\ Seiga Nijie Pawoo Fanbox Pixiv\ Sketch Plurk Tinami Tumblr Weibo
Ask.fm Booth 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
]
sites.index(site_name) || 1000
end
def self.normalize_url(url)
Source::URL.parse(url)&.profile_url || Danbooru::URL.parse(url)&.to_normalized_s || url
end
def url=(url)
super(url)
@parsed_url = Source::URL.parse(url)
self.normalized_url = self.class.normalize_normalized_url(self.url)
end
def parsed_url
@parsed_url ||= Source::URL.parse(url)
end
def to_s
if is_active?
url
else
"-#{url}"
end
end
def validate_scheme(uri)
errors.add(:url, "'#{uri}' must begin with http:// or https:// ") unless uri.scheme.in?(%w[http https])
end
def validate_hostname(uri)
errors.add(:url, "'#{uri}' has a hostname '#{uri.host}' that does not contain a dot") unless uri.host&.include?(".")
end
def validate_url_format
uri = Addressable::URI.parse(url)
validate_scheme(uri)
validate_hostname(uri)
rescue Addressable::URI::InvalidURIError => e
errors.add(:url, "'#{uri}' is malformed: #{e}")
end
def validate_url_is_not_duplicate
artists = ArtistFinder.find_artists(url).without(artist)
artists.each do |a|
warnings.add(:base, "Duplicate of [[#{a.name}]]")
end
end
def self.available_includes
[:artist]
end
end