94 lines
2.9 KiB
Ruby
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
|