Files
redux-scraper/app/helpers/fa_uri_helper.rb
2025-07-25 00:25:12 +00:00

60 lines
1.7 KiB
Ruby

# typed: strict
module FaUriHelper
extend T::Sig
FA_CDN_HOSTS = %w[d.facdn.net d.furaffinity.net].freeze
class FaMediaUrlInfo < T::ImmutableStruct
extend T::Sig
include T::Struct::ActsAsComparable
const :url_name, String
const :original_file_posted, Integer
const :latest_file_posted, Integer
const :filename, String
const :filename_with_ts, String
sig { returns(Time) }
def original_file_posted_at
Time.at(original_file_posted)
end
sig { returns(Time) }
def latest_file_posted_at
Time.at(latest_file_posted)
end
end
sig { params(url_str: String).returns(T.nilable(FaMediaUrlInfo)) }
def self.parse_fa_media_url(url_str)
uri = Addressable::URI.parse(url_str)
return nil unless is_fa_cdn_host?(uri.host)
# paths are in the form of `art/<user.url_name>/<latest_file_ts>/<og_file_ts>.<rest_of_filename>`
# latest_file_ts is the timestamp of the most up to date file that has been uploaded for the post
# og_file_ts is the timestamp of when the post was originally made
path = uri.path
match =
path.match(
%r{/art/(?<url_name>[^/]+)/(stories/)?(?<latest_ts>\d+)/(?<original_ts>\d+)\.(?<filename>.*)},
)
return nil unless match
url_name = match[:url_name]
latest_ts = match[:latest_ts].to_i
original_ts = match[:original_ts].to_i
filename = match[:filename]
FaMediaUrlInfo.new(
url_name:,
original_file_posted: original_ts,
latest_file_posted: latest_ts,
filename:,
filename_with_ts: path.split("/").last,
)
end
sig { params(host: String).returns(T::Boolean) }
def self.is_fa_cdn_host?(host)
FA_CDN_HOSTS.include?(host)
end
end