Introduce EpisodeTask to replace index/episode pairs
Encapsulates slug and path derivation. Eliminates free path
helper functions and (i, ep) threading throughout the Rakefile.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/Rakefile b/Rakefile
index 5c55328..e30d099 100644
--- a/Rakefile
+++ b/Rakefile
@@ -4,6 +4,7 @@ require "pathname"
require "uri"
require_relative "lib/config"
+require_relative "lib/episode_task"
require_relative "lib/feed"
require_relative "lib/download"
@@ -12,24 +13,6 @@ load File.expand_path("lib/tasks/transcribers.rake", __dir__)
CONFIG = CookingIssues::Config.from_env(Transcribers)
CONFIG.transcriber.register
-# --- Path helpers ---
-
-def episode_slug(index, ep)
- format("%03d-%s", index + 1, ep.slug)
-end
-
-def audio_path(index, ep)
- (CONFIG.audio_dir / "#{episode_slug(index, ep)}.mp3").to_s
-end
-
-def transcript_path(index, ep)
- (CONFIG.transcriber_cache_dir / "#{episode_slug(index, ep)}.json").to_s
-end
-
-def text_path(index, ep)
- (CONFIG.text_dir / "#{episode_slug(index, ep)}.txt").to_s
-end
-
# --- Feed downloads ---
[CONFIG.cache_dir, CONFIG.audio_dir, CONFIG.transcriber_cache_dir, CONFIG.text_dir].each do |dir|
@@ -53,27 +36,27 @@ end
Rake::Task[CONFIG.hrn_feed_path.to_s].invoke
Rake::Task[CONFIG.patreon_feed_path.to_s].invoke
-EPISODES = CookingIssues::Feed.parse(CONFIG.hrn_feed_path) +
+episodes = CookingIssues::Feed.parse(CONFIG.hrn_feed_path) +
CookingIssues::Feed.parse(CONFIG.patreon_feed_path)
-# --- Per-episode file tasks ---
+EPISODE_TASKS = episodes.map.with_index do |ep, i|
+ CookingIssues::EpisodeTask.new(index: i, episode: ep, config: CONFIG)
+end
-EPISODES.each_with_index do |ep, i|
- audio = audio_path(i, ep)
- transcript = transcript_path(i, ep)
- txt = text_path(i, ep)
+# --- Per-episode file tasks ---
- file audio => CONFIG.audio_dir.to_s do
- puts "Downloading #{episode_slug(i, ep)}..."
- CookingIssues::Download.fetch(ep.audio_url, audio)
+EPISODE_TASKS.each do |et|
+ file et.audio_path => CONFIG.audio_dir.to_s do
+ puts "Downloading #{et.slug}..."
+ CookingIssues::Download.fetch(et.episode.audio_url, et.audio_path)
end
- file transcript => [audio, CONFIG.transcriber_cache_dir.to_s, *CONFIG.transcriber.prereqs] do
- CONFIG.transcriber.call(audio, transcript)
+ file et.transcript_path => [et.audio_path, CONFIG.transcriber_cache_dir.to_s, *CONFIG.transcriber.prereqs] do
+ CONFIG.transcriber.call(et.audio_path, et.transcript_path)
end
- file txt => [transcript, CONFIG.text_dir.to_s] do
- CONFIG.transcriber.render(transcript, txt)
+ file et.text_path => [et.transcript_path, CONFIG.text_dir.to_s] do
+ CONFIG.transcriber.render(et.transcript_path, et.text_path)
end
end
@@ -83,16 +66,14 @@ task default: :sync
desc "Download, transcribe, and render all episodes"
task :sync do
- EPISODES.each_with_index do |ep, i|
- Rake::Task[text_path(i, ep)].invoke
- end
+ EPISODE_TASKS.each { |et| Rake::Task[et.text_path].invoke }
end
desc "List all episodes from the feed"
task :episodes do
- EPISODES.each_with_index do |ep, i|
- status = Pathname(text_path(i, ep)).exist? ? "✓" : " "
- puts "[#{status}] #{episode_slug(i, ep)} #{ep.title}"
+ EPISODE_TASKS.each do |et|
+ status = Pathname(et.text_path).exist? ? "✓" : " "
+ puts "[#{status}] #{et.slug} #{et.episode.title}"
end
end
@@ -100,26 +81,23 @@ 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]
- i = args[:number].to_i - 1
- ep = EPISODES.fetch(i) { abort "Episode #{args[:number]} not found in feed." }
+ et = EPISODE_TASKS.fetch(args[:number].to_i - 1) { abort "Episode #{args[:number]} not found in feed." }
- Rake::Task[text_path(i, ep)].invoke
+ Rake::Task[et.text_path].invoke
end
desc "Re-transcribe an episode (e.g., rake retranscribe[42])"
task :retranscribe, [:number] do |_t, args|
abort "Usage: rake retranscribe[NUMBER]" unless args[:number]
- i = args[:number].to_i - 1
- ep = EPISODES.fetch(i) { abort "Episode #{args[:number]} not found in feed." }
+ et = EPISODE_TASKS.fetch(args[:number].to_i - 1) { abort "Episode #{args[:number]} not found in feed." }
- 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(i, ep)].reenable
- Rake::Task[transcript_path(i, ep)].reenable
- Rake::Task[text_path(i, ep)].invoke
+ [et.transcript_path, et.text_path].each do |path|
+ p = Pathname(path)
+ p.delete if p.exist?
+ Rake::Task[path].reenable
+ end
+ Rake::Task[et.text_path].invoke
end
load File.expand_path("lib/tasks/site.rake", __dir__)
diff --git a/lib/episode_task.rb b/lib/episode_task.rb
new file mode 100644
index 0000000..a547c2c
--- /dev/null
+++ b/lib/episode_task.rb
@@ -0,0 +1,9 @@
+module CookingIssues
+ EpisodeTask = Data.define(:index, :episode, :config) do
+ def number = index + 1
+ def slug = format("%03d-%s", number, episode.slug)
+ def audio_path = (config.audio_dir / "#{slug}.mp3").to_s
+ def transcript_path = (config.transcriber_cache_dir / "#{slug}.json").to_s
+ def text_path = (config.text_dir / "#{slug}.txt").to_s
+ end
+end
diff --git a/lib/tasks/site.rake b/lib/tasks/site.rake
index 2d845ad..c31a381 100644
--- a/lib/tasks/site.rake
+++ b/lib/tasks/site.rake
@@ -5,18 +5,16 @@ SITE_DIR = Pathname("site")
desc "Generate an HTML page of transcripts"
task :site do
- transcripts = []
- EPISODES.each_with_index do |ep, i|
- txt = Pathname(text_path(i, ep))
- next unless txt.exist?
-
- transcripts << {
- number: i + 1,
- title: ep.title,
- slug: episode_slug(i, ep),
- text: txt.read
- }
- end
+ transcripts = EPISODE_TASKS
+ .select { |et| Pathname(et.text_path).exist? }
+ .map do |et|
+ {
+ number: et.number,
+ title: et.episode.title,
+ slug: et.slug,
+ text: File.read(et.text_path)
+ }
+ end
template = File.read(File.expand_path("../../site.html.erb", __FILE__))
html = ERB.new(template).result(binding)