57 lines
2.2 KiB
Ruby
57 lines
2.2 KiB
Ruby
require "rss"
|
|
require "rss/itunes"
|
|
|
|
module Podcasts
|
|
class Feed
|
|
def initialize(podcast)
|
|
@podcast = podcast
|
|
end
|
|
|
|
# @note While the limit might look generous, the callers are passing the value (which they
|
|
# themselves receive elsewhere). In one case, the :limit is 5
|
|
#
|
|
# @see Podcasts::EnqueueGetEpisodesWorker
|
|
def get_episodes(limit: 100, force_update: false)
|
|
# increased the redirect limit from 5 (default) to 7 to be able to handle such urls
|
|
rss = HTTParty.get(podcast.feed_url, limit: 7).body.to_s
|
|
feed = RSS::Parser.parse(rss, false)
|
|
|
|
set_unreachable(status: :unparsable, force_update: force_update) && return unless feed
|
|
|
|
get_episode = Podcasts::GetEpisode.new(podcast)
|
|
|
|
# Sort by published date in descending order
|
|
feed.items.sort_by { |i| -i.pubDate.to_i }.first(limit).each do |item|
|
|
get_episode.call(item: item, force_update: force_update)
|
|
end
|
|
podcast.update_columns(reachable: true, status_notice: "")
|
|
feed.items.size
|
|
rescue Net::OpenTimeout, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError, HTTParty::RedirectionTooDeep
|
|
set_unreachable(status: :unreachable, force_update: force_update)
|
|
rescue OpenSSL::SSL::SSLError
|
|
set_unreachable(status: :ssl_failed, force_update: force_update)
|
|
rescue RSS::NotWellFormedError
|
|
set_unreachable(status: :unparsable, force_update: force_update)
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :podcast
|
|
|
|
def set_unreachable(status: :unreachable, force_update: false)
|
|
# don't recheck if the podcast was already unreachable or force update is required
|
|
need_refetching = podcast.reachable || force_update
|
|
podcast.update_columns(reachable: false, status_notice: I18n.t(status, scope: "views.podcasts.statuses"))
|
|
refetch_items if need_refetching
|
|
true
|
|
end
|
|
|
|
# When setting podcast feed as unreachable, we need to re-check the episodes URLs.
|
|
# If the episodes URLs are still reachable, the podcast will remain on the site.
|
|
# If they are not, the podcast will be hidden.
|
|
def refetch_items
|
|
job_params = podcast.podcast_episodes.pluck(:id, :media_url)
|
|
PodcastEpisodes::UpdateMediaUrlWorker.perform_bulk(job_params)
|
|
end
|
|
end
|
|
end
|