From 5017224aa4969117fdb4496ef089435692be92c8 Mon Sep 17 00:00:00 2001 From: "G. Gibson" Date: Tue, 1 Sep 2026 15:34:13 -0700 Subject: [PATCH] Added show archive/un-archive --- fetch_podcasts.py | 100 +--------------------------------------------- fetch_podcasts.rb | 25 ++++++++++-- 2 files changed, 24 insertions(+), 101 deletions(-) diff --git a/fetch_podcasts.py b/fetch_podcasts.py index 8f472da..44df923 100755 --- a/fetch_podcasts.py +++ b/fetch_podcasts.py @@ -409,104 +409,8 @@ def add_show(feed_url): log.info("Added show: %s (%s)", name, slug) fetch_show_episodes(slug, name, feed_url) -def remove_show_data(slug): - pod_dir = PODCASTS_DIR / slug - if pod_dir.exists(): - shutil.rmtree(pod_dir) - pls = PLAYLISTS_DIR / f"{slug}.txt" - if pls.exists(): - pls.unlink() - -def delete_show(slug): +def set_archive(slug, value): db = open_subs_db() row = db.execute("SELECT name FROM shows WHERE slug = ?", (slug,)).fetchone() if row is None: - log_error(f"No show found with slug '{slug}'.") - return - remove_show_data(slug) - db.execute("DELETE FROM shows WHERE slug = ?", (slug,)) - db.commit() - db.close() - played_db = open_played_db() - played_db.execute("DELETE FROM episodes WHERE show_slug = ?", (slug,)) - played_db.commit() - played_db.close() - log.info("Deleted show: %s (%s)", row["name"], slug) - -def import_opml(path): - try: - with open(path) as f: - content = f.read() - except OSError as e: - log_error(f"Cannot read OPML file: {e}") - return - shows = parse_opml(content) - db = open_subs_db() - added = 0 - skipped_video = 0 - for show in shows: - slug = slugify(show["name"]) - existing = db.execute("SELECT slug FROM shows WHERE slug = ?", (slug,)).fetchone() - if existing is not None: - continue - parsed = fetch_feed(show["feed_url"]) - if parsed is None: - log.warning("OPML import: skipping '%s', could not fetch feed.", show["name"]) - continue - if not is_audio_feed(parsed): - log.info("OPML import: skipping '%s' (%s): video podcast.", show["name"], slug) - skipped_video += 1 - continue - guid = show["guid"] or gen_uuid() - db.execute( - "INSERT INTO shows (slug, guid, name, feed_url, source, opml_import, archived) VALUES (?, ?, ?, ?, 'opml', 1, 1)", - (slug, guid, show["name"], show["feed_url"]), - ) - added += 1 - db.commit() - db.close() - log.info("OPML import: %d added, %d video shows filtered out.", added, skipped_video) - -def run_fetch(config): - g = config["gpodder"] - if g.get("enable") is True: - remote = gpodder_sync(config) - if not remote: - log.warning("No subscriptions retrieved from gPodder; using local registry only.") - else: - added = register_remote_shows(remote) - pruned = prune_stale_shows(remote) - log.info("Sync: %d added, %d pruned.", added, pruned) - fetch_all_episodes() - -def main(): - parser = argparse.ArgumentParser(description="Podcast fetcher for radio automation") - parser.add_argument("--list-shows", action="store_true", help="List registered shows") - parser.add_argument("--detail", action="store_true", help="With --list-shows, show feed URLs") - parser.add_argument("--add-show", metavar="FEED_URL", help="Add a show from a feed URL") - parser.add_argument("--delete-show", metavar="SLUG", help="Delete a show and its data") - parser.add_argument("--import-opml", metavar="FILE", help="Import shows from an OPML file") - args = parser.parse_args() - - init_paths() - STATE_DIR.mkdir(parents=True, exist_ok=True) - LOGS_DIR.mkdir(parents=True, exist_ok=True) - PODCASTS_DIR.mkdir(parents=True, exist_ok=True) - PLAYLISTS_DIR.mkdir(parents=True, exist_ok=True) - _setup_logging() - - config = load_config() - - if args.list_shows: - list_shows(detail=args.detail) - elif args.add_show: - add_show(args.add_show) - elif args.delete_show: - delete_show(args.delete_show) - elif args.import_opml: - import_opml(args.import_opml) - else: - run_fetch(config) - -if __name__ == "__main__": - main() + log_error(f"No diff --git a/fetch_podcasts.rb b/fetch_podcasts.rb index ad23081..b8631f1 100755 --- a/fetch_podcasts.rb +++ b/fetch_podcasts.rb @@ -477,11 +477,24 @@ module RadioAutomation fetch_show_episodes(slug, name, feed_url) end + def self.set_archive(slug, value) + db = open_subs_db + rows = jdb_query(db, "SELECT name FROM shows WHERE slug = ?", [slug]) + if rows.empty? + log_error("No show found with slug '#{slug}'.") + return + end + jdb_exec(db, "UPDATE shows SET archived = ? WHERE slug = ?", [value, slug]) + db.close + state = value == 1 ? "archived" : "non-archived (live)" + log_info("Show '#{rows.first['name']}' (#{slug}) is now #{state}.") + end + def self.remove_show_data(slug) pod_dir = File.join(PODCASTS_DIR, slug) FileUtils.rm_rf(pod_dir) if Dir.exist?(pod_dir) - pls = File.join(PLAYLISTS_DIR, "#{slug}.pls") - File.delete(pls) if File.exist?(pls) + txt = File.join(PLAYLISTS_DIR, "#{slug}.txt") + File.delete(txt) if File.exist?(txt) end def self.delete_show(slug) @@ -556,6 +569,8 @@ module RadioAutomation opts.on("--detail", "With --list-shows, show feed URLs") { options[:detail] = true } opts.on("--add-show FEED_URL", "Add a show from a feed URL") { |v| options[:add] = v } opts.on("--delete-show SLUG", "Delete a show and its data") { |v| options[:delete] = v } + opts.on("--archive SLUG", "Mark a show as archived (download episodes)") { |v| options[:archive] = v } + opts.on("--unarchive SLUG", "Mark a show as non-archived (stream live)") { |v| options[:unarchive] = v } opts.on("--import-opml FILE", "Import shows from an OPML file") { |v| options[:import] = v } end.parse! @@ -567,7 +582,11 @@ module RadioAutomation config = load_config - if options[:list] + if options[:archive] + set_archive(options[:archive], 1) + elsif options[:unarchive] + set_archive(options[:unarchive], 0) + elsif options[:list] list_shows(detail: options[:detail]) elsif options[:add] add_show(options[:add])