Apple Podcasts' top charts into the directory weekly, and its categories checked (#252)
With apple_country set, the directory fetches Apple's top 100 podcasts and the top 50 of each of
its 19 categories for that country (itunes.apple.com/{cc}/rss/toppodcasts), looks up each
show's RSS address (/lookup, 100 ids a call, three seconds apart, as Apple asks for no more than
about twenty a minute), and stores them as the snapshot apple-podcasts with no subscribers. The
refresher fetches them like any feed; the most-subscribed chart is unchanged. Apple's primary
genre goes in as the snapshot's category, used only while a feed names none.
The same weekly run reads Apple's genre tree (ws/genres?id=26) and warns when it differs from
ipx_feed's CATEGORIES; on 2026-10-15 they were the same, all 19 and their subcategories.
A syncs table keeps when it last ran: at start if a week has passed, again weekly, an hour after
a failure. keep_instances spares apple-podcasts, which no token holds, and no token may take
the name. A trace a sync, a span each answer.
CLAUDE.md: builds one cargo command at a time, the load looked at before and after, after a
build chained with a test compile took Tower past 200.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,11 @@ pub struct Config {
|
||||
/// publishes: `0.0.0.0:9188`. Empty serves none.
|
||||
#[serde(default)]
|
||||
pub metrics_bind: String,
|
||||
/// Apple Podcasts' top charts for this country (its two letters: `ca`, `us`) come into the
|
||||
/// directory each week, and Apple's categories are checked against ipx's (#252). Empty, or
|
||||
/// left out, does neither.
|
||||
#[serde(default)]
|
||||
pub apple_country: String,
|
||||
#[serde(default)]
|
||||
pub tokens: Vec<TokenCfg>,
|
||||
}
|
||||
@@ -81,6 +86,14 @@ impl Config {
|
||||
if !seen.insert(t.name.as_str()) {
|
||||
bail!("two tokens are named {:?}", t.name);
|
||||
}
|
||||
// Apple's charts are filed under it; a server of that name would replace them.
|
||||
if t.name == crate::apple::INSTANCE {
|
||||
bail!("{:?} is the name Apple Podcasts' charts are kept under; give the token another", t.name);
|
||||
}
|
||||
}
|
||||
let c = cfg.apple_country.trim();
|
||||
if !c.is_empty() && !(c.len() == 2 && c.chars().all(|c| c.is_ascii_alphabetic())) {
|
||||
bail!("apple_country is a country's two letters, such as \"ca\" or \"us\", not {c:?}");
|
||||
}
|
||||
Ok(cfg)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user