Module: PinterestURLNormalizer

Defined in:
lib/pinterest_url_normalizer.rb,
lib/pinterest_url_normalizer/cli.rb,
lib/pinterest_url_normalizer/version.rb

Overview

Parses, classifies, and normalizes supported Pinterest URLs without making network requests.

Full Pinterest URLs are normalized to www.pinterest.com. Short pin.it links retain their host because resolving them requires a network request.

SavePinner: https://savepinner.com/pinterest-downloader/

Defined Under Namespace

Modules: CLI Classes: Error, ParsedURL

Constant Summary collapse

CANONICAL_HOST =
"www.pinterest.com"
SHORT_HOST =
"pin.it"
MAX_URL_LENGTH =
2048
COUNTRY_HOSTS =
%w[
  pinterest.at pinterest.be pinterest.ca pinterest.ch pinterest.cl
  pinterest.co pinterest.co.kr pinterest.co.nz pinterest.co.uk
  pinterest.com.au pinterest.com.br pinterest.com.mx pinterest.com.pe
  pinterest.com.tr pinterest.cz pinterest.de pinterest.dk pinterest.es
  pinterest.fi pinterest.fr pinterest.gr pinterest.hu pinterest.id
  pinterest.ie pinterest.it pinterest.jp pinterest.nl pinterest.no
  pinterest.ph pinterest.pl pinterest.pt pinterest.ro pinterest.se
  pinterest.sk
].freeze
REGIONAL_SUBDOMAINS =
%w[
  at au be br ca ch cl co cz de dk es fi fr gr hu id ie it jp kr mx nl
  no nz pe ph pl pt ro se sk tr uk
].freeze
RESERVED_FIRST_SEGMENTS =
%w[
  business categories explore help ideas login logout oauth pin pin-builder
  resource search settings signup today topics
].freeze
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.normalize(input) ⇒ Object

Returns the canonical URL for a supported Pinterest URL.



92
93
94
# File 'lib/pinterest_url_normalizer.rb', line 92

def normalize(input)
  parse(input).normalized_url
end

.parse(input) ⇒ Object

Parses a supported Pinterest URL and returns its canonical fields.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pinterest_url_normalizer.rb', line 67

def parse(input)
  original = input.to_s.strip
  raise_invalid("URL is empty or too long") if original.empty? || original.bytesize > MAX_URL_LENGTH

  uri = URI.parse(original)
  raise_invalid("URL could not be parsed") unless uri.host
  raise_invalid("only HTTPS URLs are supported") unless uri.scheme == "https"
  raise_invalid("credentials are not supported") if uri.userinfo
  raise_invalid("non-standard ports are not supported") unless uri.port == 443
  raise_invalid("encoded paths are not supported") if uri.path.include?("%")

  host = uri.host.downcase
  segments = uri.path.split("/").reject(&:empty?)
  return parse_short(original, segments) if host == SHORT_HOST

  raise_invalid("host is not an allowed Pinterest domain") unless pinterest_host?(host)

  parse_pin(original, segments) ||
    parse_ideas(original, segments) ||
    parse_profile_or_board(original, segments)
rescue URI::InvalidURIError, URI::InvalidComponentError, ArgumentError
  raise_invalid("URL could not be parsed")
end

.pinterest_host?(host) ⇒ Boolean

Reports whether host is an exact supported Pinterest host.

Returns:

  • (Boolean)


105
106
107
108
109
110
111
112
113
# File 'lib/pinterest_url_normalizer.rb', line 105

def pinterest_host?(host)
  host = host.to_s.downcase
  return true if %w[pinterest.com www.pinterest.com m.pinterest.com].include?(host)
  return true if COUNTRY_HOSTS.include?(host)
  return true if host.start_with?("www.") && COUNTRY_HOSTS.include?(host.delete_prefix("www."))

  region = host.delete_suffix(".pinterest.com")
  region != host && REGIONAL_SUBDOMAINS.include?(region)
end

.pinterest_url?(input) ⇒ Boolean

Reports whether input is a supported Pinterest URL.

Returns:

  • (Boolean)


97
98
99
100
101
102
# File 'lib/pinterest_url_normalizer.rb', line 97

def pinterest_url?(input)
  parse(input)
  true
rescue Error
  false
end