docbrown/app/services/podcasts/feed.rb

52 lines
1.8 KiB
Ruby

require "rss"
require "rss/itunes"
module Podcasts
class Feed
def initialize(podcast)
@podcast = podcast
end
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
feed = RSS::Parser.parse(rss, false)
set_unreachable(:unparsable, force_update) && return unless feed
get_episode = Podcasts::GetEpisode.new(podcast)
feed.items.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, SocketError => _e
set_unreachable(:unreachable, force_update)
rescue OpenSSL::SSL::SSLError => _e
set_unreachable(:ssl_failed, force_update)
rescue RSS::NotWellFormedError => _e
set_unreachable(:unparsable, 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: "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
podcast.podcast_episodes.find_each do |episode|
PodcastEpisodes::UpdateMediaUrlJob.perform_later(episode.id, episode.media_url)
end
end
end
end