Added show archive/un-archive

This commit is contained in:
G. Gibson 2026-09-01 15:34:13 -07:00
commit 5017224aa4
2 changed files with 24 additions and 101 deletions

View file

@ -409,104 +409,8 @@ def add_show(feed_url):
log.info("Added show: %s (%s)", name, slug) log.info("Added show: %s (%s)", name, slug)
fetch_show_episodes(slug, name, feed_url) fetch_show_episodes(slug, name, feed_url)
def remove_show_data(slug): def set_archive(slug, value):
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):
db = open_subs_db() db = open_subs_db()
row = db.execute("SELECT name FROM shows WHERE slug = ?", (slug,)).fetchone() row = db.execute("SELECT name FROM shows WHERE slug = ?", (slug,)).fetchone()
if row is None: if row is None:
log_error(f"No show found with slug '{slug}'.") log_error(f"No
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()

View file

@ -477,11 +477,24 @@ module RadioAutomation
fetch_show_episodes(slug, name, feed_url) fetch_show_episodes(slug, name, feed_url)
end 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) def self.remove_show_data(slug)
pod_dir = File.join(PODCASTS_DIR, slug) pod_dir = File.join(PODCASTS_DIR, slug)
FileUtils.rm_rf(pod_dir) if Dir.exist?(pod_dir) FileUtils.rm_rf(pod_dir) if Dir.exist?(pod_dir)
pls = File.join(PLAYLISTS_DIR, "#{slug}.pls") txt = File.join(PLAYLISTS_DIR, "#{slug}.txt")
File.delete(pls) if File.exist?(pls) File.delete(txt) if File.exist?(txt)
end end
def self.delete_show(slug) 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("--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("--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("--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 } opts.on("--import-opml FILE", "Import shows from an OPML file") { |v| options[:import] = v }
end.parse! end.parse!
@ -567,7 +582,11 @@ module RadioAutomation
config = load_config 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]) list_shows(detail: options[:detail])
elsif options[:add] elsif options[:add]
add_show(options[:add]) add_show(options[:add])