Remove number from Episode, use array index instead
Prepares for feeds without itunes:episode numbers (Patreon).
Episodes are now an array ordered by feed position, with the
index used for numbering in slugs and task lookups.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/Rakefile b/Rakefile
index a4c4675..789f9a6 100644
--- a/Rakefile
+++ b/Rakefile
@@ -33,32 +33,36 @@ Rake::Task[HRN_FEED.to_s].invoke
EPISODES = CookingIssues::Feed.parse(HRN_FEED)
-def audio_path(ep)
- (AUDIO_DIR / "#{ep.slug}.mp3").to_s
+def episode_slug(index, ep)
+ format("%03d-%s", index + 1, ep.slug)
+end
+
+def audio_path(index, ep)
+ (AUDIO_DIR / "#{episode_slug(index, ep)}.mp3").to_s
end
TRANSCRIBER_CACHE_DIR = CACHE_DIR / TRANSCRIBER.name
directory TRANSCRIBER_CACHE_DIR.to_s
-def transcript_path(ep)
- (TRANSCRIBER_CACHE_DIR / "#{ep.slug}.json").to_s
+def transcript_path(index, ep)
+ (TRANSCRIBER_CACHE_DIR / "#{episode_slug(index, ep)}.json").to_s
end
-def text_path(ep)
- (TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{ep.slug}.txt").to_s
+def text_path(index, ep)
+ (TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{episode_slug(index, ep)}.txt").to_s
end
TEXT_DIR = TRANSCRIPTS_DIR / TRANSCRIBER.name
directory TEXT_DIR.to_s
-EPISODES.values.each do |ep|
- audio = audio_path(ep)
- transcript = transcript_path(ep)
+EPISODES.each_with_index do |ep, i|
+ audio = audio_path(i, ep)
+ transcript = transcript_path(i, ep)
file audio => AUDIO_DIR.to_s do
- puts "Downloading #{ep.slug}..."
+ puts "Downloading #{episode_slug(i, ep)}..."
CookingIssues::Download.fetch(ep.audio_url, audio)
end
@@ -66,7 +70,7 @@ EPISODES.values.each do |ep|
TRANSCRIBER.call(audio, transcript)
end
- txt = text_path(ep)
+ txt = text_path(i, ep)
file txt => [transcript, TEXT_DIR.to_s] do
TRANSCRIBER.render(transcript, txt)
@@ -77,17 +81,16 @@ task default: :sync
desc "Download, transcribe, and render all episodes"
task :sync do
- # The feed is reverse-chronological; process oldest episodes first.
- EPISODES.values.sort_by(&:number).each do |ep|
- Rake::Task[text_path(ep)].invoke
+ EPISODES.each_with_index do |ep, i|
+ Rake::Task[text_path(i, ep)].invoke
end
end
desc "List all episodes from the feed"
task :episodes do
- EPISODES.values.sort_by(&:number).each do |ep|
- status = Pathname(text_path(ep)).exist? ? "✓" : " "
- puts "[#{status}] #{ep.slug} #{ep.title}"
+ EPISODES.each_with_index do |ep, i|
+ status = Pathname(text_path(i, ep)).exist? ? "✓" : " "
+ puts "[#{status}] #{episode_slug(i, ep)} #{ep.title}"
end
end
@@ -95,17 +98,17 @@ desc "Transcribe an episode by number (e.g., rake transcribe[42])"
task :transcribe, [:number] do |_t, args|
abort "Usage: rake transcribe[NUMBER]" unless args[:number]
- ep = EPISODES[args[:number].to_i]
- abort "Episode #{args[:number]} not found in feed." unless ep
+ i = args[:number].to_i - 1
+ ep = EPISODES.fetch(i) { abort "Episode #{args[:number]} not found in feed." }
- Rake::Task[text_path(ep)].invoke
+ Rake::Task[text_path(i, ep)].invoke
end
desc "Move intermediate files from transcripts/ to cache/"
task :migrate_cache do
- EPISODES.values.each do |ep|
- old_path = TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{ep.slug}.json"
- new_path = Pathname(transcript_path(ep))
+ EPISODES.each_with_index do |ep, i|
+ old_path = TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{episode_slug(i, ep)}.json"
+ new_path = Pathname(transcript_path(i, ep))
next unless old_path.exist?
new_path.dirname.mkpath
@@ -120,14 +123,14 @@ desc "Re-transcribe an episode (e.g., rake retranscribe[42])"
task :retranscribe, [:number] do |_t, args|
abort "Usage: rake retranscribe[NUMBER]" unless args[:number]
- ep = EPISODES[args[:number].to_i]
- abort "Episode #{args[:number]} not found in feed." unless ep
+ i = args[:number].to_i - 1
+ ep = EPISODES.fetch(i) { abort "Episode #{args[:number]} not found in feed." }
- json = Pathname(transcript_path(ep))
- txt = Pathname(text_path(ep))
+ json = Pathname(transcript_path(i, ep))
+ txt = Pathname(text_path(i, ep))
json.delete if json.exist?
txt.delete if txt.exist?
- Rake::Task[text_path(ep)].reenable
- Rake::Task[transcript_path(ep)].reenable
- Rake::Task[text_path(ep)].invoke
+ Rake::Task[text_path(i, ep)].reenable
+ Rake::Task[transcript_path(i, ep)].reenable
+ Rake::Task[text_path(i, ep)].invoke
end
diff --git a/lib/feed.rb b/lib/feed.rb
index 9b9574d..208880b 100644
--- a/lib/feed.rb
+++ b/lib/feed.rb
@@ -1,10 +1,9 @@
require "nokogiri"
module CookingIssues
- Episode = Data.define(:number, :title, :published_at, :audio_url) do
+ Episode = Data.define(:title, :published_at, :audio_url) do
def self.parse(item)
new(
- number: item.at_xpath("itunes:episode").text.to_i,
title: item.at_xpath("title").text,
published_at: item.at_xpath("pubDate").text,
audio_url: item.at_xpath("enclosure")["url"]
@@ -12,8 +11,7 @@ module CookingIssues
end
def slug
- safe_title = title.downcase.gsub(/[^a-z0-9]+/, "-").chomp("-")
- format("%03d-%s", number, safe_title)
+ title.downcase.gsub(/[^a-z0-9]+/, "-").chomp("-")
end
end
@@ -22,8 +20,7 @@ module CookingIssues
doc = Nokogiri::XML(File.read(path))
doc.xpath("//item")
.map { Episode.parse(it) }
- .sort_by(&:number)
- .to_h { [it.number, it] }
+ .reverse
end
end
end
diff --git a/lib/tasks/site.rake b/lib/tasks/site.rake
index 1a8492f..2d845ad 100644
--- a/lib/tasks/site.rake
+++ b/lib/tasks/site.rake
@@ -5,18 +5,20 @@ SITE_DIR = Pathname("site")
desc "Generate an HTML page of transcripts"
task :site do
- episodes = EPISODES.values.sort_by(&:number).select { |ep| Pathname(text_path(ep)).exist? }
+ transcripts = []
+ EPISODES.each_with_index do |ep, i|
+ txt = Pathname(text_path(i, ep))
+ next unless txt.exist?
- transcripts = episodes.map do |ep|
- {
- number: ep.number,
+ transcripts << {
+ number: i + 1,
title: ep.title,
- slug: ep.slug,
- text: File.read(text_path(ep))
+ slug: episode_slug(i, ep),
+ text: txt.read
}
end
- template = File.read(File.expand_path("lib/site.html.erb", __dir__))
+ template = File.read(File.expand_path("../../site.html.erb", __FILE__))
html = ERB.new(template).result(binding)
SITE_DIR.mkpath