Give a feed with no category of its own one of Apple's (#117)
Most blogs and news sites name no <itunes:category>, so they sat under no chip in the Directory unless an admin set one by hand. When TYPESAFE_KEY is set, a feed's first read, or a forced refresh, asks TypeSafe's Jev to pick one of Apple's categories or subcategories from the feed's title and up to 15 item titles, for a catalogue feed with neither its own category nor an admin's. The answer is stored as the catalogue's category, so a feed is not asked twice, and an admin can change it. Only on a first read or a forced refresh to keep the calls down: feeds already subscribed are categorised by one `ipx fetch --force`. Tried on eight subscribed feeds on 2026-10-04: XDA, Daring Fireball, Ars Technica and The Verge as Tech News, The Old New Thing as Technology, John D. Cook as Mathematics, BoardGameGeek as Games, Pluralistic as News Commentary (0.55). About 2,000 input tokens a feed at $0.042 a million. The likeliest answer is kept however unsure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
22
src/main.rs
22
src/main.rs
@@ -1526,6 +1526,28 @@ async fn scan_one(
|
||||
parsed.image.as_deref(),
|
||||
parsed.category.as_deref(),
|
||||
).await?;
|
||||
// Asked on a feed's first read, nothing of it stored yet, or when someone forces a refresh:
|
||||
// each call costs, and a feed already here without a category can wait for a forced one.
|
||||
// The answer becomes the catalogue's category, so a feed is not asked twice.
|
||||
// A feed an OPML lists is not in the catalogue and has nowhere to keep one.
|
||||
if parsed.category.is_none()
|
||||
&& (force || stored.entries == 0)
|
||||
&& !parsed.entries.is_empty()
|
||||
&& ctx.cfg().feeds.get(id).is_some_and(|f| f.category.is_none())
|
||||
&& let Ok(key) = std::env::var("TYPESAFE_KEY")
|
||||
{
|
||||
match feed::classify(&ctx.client, &key, &parsed).await {
|
||||
Ok(category) => {
|
||||
let mut cfg = (*ctx.cfg()).clone();
|
||||
if let Some(f) = cfg.feeds.get_mut(id).filter(|f| f.category.is_none()) {
|
||||
tracing::info!(feed = id, category = %category, "categorised");
|
||||
f.category = Some(category);
|
||||
ctx.store_cfg(cfg).await?;
|
||||
}
|
||||
}
|
||||
Err(e) => tracing::warn!(feed = id, "could not categorise: {e:#}"),
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(parent) = &feed_cfg.group {
|
||||
let listed: Vec<(&str, &str)> = parsed
|
||||
|
||||
Reference in New Issue
Block a user