docbrown/app/labor/podcast_feed.rb

94 lines
2.9 KiB
Ruby

require "rss"
require "rss/itunes"
class PodcastFeed
def get_all_episodes
Podcast.find_each do |podcast|
get_episodes(podcast)
end
end
def get_episodes(podcast, num = 1000)
rss = HTTParty.get(podcast.feed_url).body
feed = RSS::Parser.parse(rss, false)
feed.items.first(num).each do |item|
ep = existing_episode(item, podcast).first
if ep
update_existing_episode(ep, item, podcast)
else
create_new_episode(item, podcast)
end
end
feed.items.size
rescue StandardError => e
Rails.logger.error(e)
end
private
# returns empty array if an episode doesn't exist
def existing_episode(item, podcast)
# presence returns nil if the query is an empty array, otherwise returns the array
podcasts = PodcastEpisode.where(media_url: item.enclosure.url).presence ||
PodcastEpisode.where(title: item.title).presence ||
PodcastEpisode.where(guid: item.guid.to_s).presence ||
(podcast.unique_website_url? && PodcastEpisode.where(website_url: item.link).presence)
podcasts.to_a
end
def create_new_episode(item, podcast)
ep = PodcastEpisode.new
ep.title = item.title
ep.podcast_id = podcast.id
ep.slug = item.title.parameterize
ep.subtitle = item.itunes_subtitle
ep.summary = item.itunes_summary
ep.website_url = item.link
ep.guid = item.guid
get_media_url(ep, item, podcast)
begin
ep.published_at = item.pubDate.to_date
rescue StandardError => e
Rails.logger.error("not a valid date: #{e}")
end
ep.body = item.content_encoded || item.itunes_summary || item.description
ep.save!
end
def update_existing_episode(episode, item, _podcast)
if episode.published_at.nil?
begin
episode.published_at = item.pubDate.to_date
episode.save
rescue StandardError => e
Rails.logger.error("not a valid date: #{e}")
end
end
update_media_url(episode, item)
end
def get_media_url(episode, item, podcast)
episode.media_url = if Rails.env.test? ||
HTTParty.head(item.enclosure.url.gsub(/http:/, "https:")).code == 200
item.enclosure.url.gsub(/http:/, "https:")
else
item.enclosure.url
end
rescue StandardError
# podcast episode must have a media_url
episode.media_url = item.enclosure.url
podcast.update(status_notice: "This podcast may not be playable in the browser") if podcast.status_notice.empty?
end
def update_media_url(episode, item)
if episode.media_url.include?("https")
nil
elsif !episode.media_url.include?("https") &&
item.enclosure.url.include?("https")
episode.update!(media_url: item.enclosure.url)
end
rescue StandardError
message = "something went wrong with #{podcast.title}, #{episode.title} -- #{episode.media_url}"
Rails.logger.error(message)
end
end