Add a feed through one function, from the CLI and the page alike (#161)
`ipx add` and the page's Add feed were the same steps written twice: find the feed, look for it in the catalogue by same_feed, add_one, store. They had drifted, and #153's lock had to be put into both by hand. add_to_catalogue() now does the shared part, under the lock, and answers the id and whether the feed was there already; each caller still finds the feed itself, so the page can call a bad address the caller's mistake (400), and then does its own part: the CLI lists or categorises, the page subscribes and scans. add_one is private to it now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
52
src/main.rs
52
src/main.rs
@@ -794,38 +794,54 @@ async fn add(
|
||||
category: Option<String>,
|
||||
list: bool,
|
||||
) -> Result<()> {
|
||||
let mut cfg = ctx.edit_cfg().await;
|
||||
let url = &feed::find_feed(&ctx.client, &feed::expand_input(url)).await?;
|
||||
// Includes feeds derived from an OPML, or the same show could be added twice.
|
||||
if let Some(existing) = subscriptions(ctx).await?.iter().find(|s| feed::same_feed(&s.cfg.url, url)) {
|
||||
// Listing a feed the catalogue already has, or giving it a category, is the point of
|
||||
// asking again: it changes those, and nothing else.
|
||||
if let Some(f) = cfg.feeds.get_mut(&existing.id)
|
||||
&& (list || category.is_some())
|
||||
{
|
||||
let url = feed::find_feed(&ctx.client, &feed::expand_input(url)).await?;
|
||||
let (id, existed) = add_to_catalogue(ctx, &url, folder, keywords).await?;
|
||||
// Listing a feed the catalogue already has, or giving it a category, is the point of asking
|
||||
// again: it changes those, and nothing else. A feed an OPML lists has no entry to change.
|
||||
if list || category.is_some() {
|
||||
let mut cfg = ctx.edit_cfg().await;
|
||||
if let Some(f) = cfg.feeds.get_mut(&id) {
|
||||
f.listed |= list;
|
||||
if category.is_some() {
|
||||
f.category = category;
|
||||
}
|
||||
ctx.store_cfg(cfg).await?;
|
||||
println!("{} is already in the catalogue; updated its Directory listing", existing.id);
|
||||
return Ok(());
|
||||
if existed {
|
||||
println!("{id} is already in the catalogue; updated its Directory listing");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
anyhow::bail!("already subscribed as {:?}", existing.id);
|
||||
}
|
||||
let id = add_one(ctx, &mut cfg, url, folder, keywords).await?;
|
||||
if let Some(f) = cfg.feeds.get_mut(&id) {
|
||||
f.category = category;
|
||||
f.listed = list;
|
||||
if existed {
|
||||
anyhow::bail!("already subscribed as {id:?}");
|
||||
}
|
||||
ctx.store_cfg(cfg).await?;
|
||||
println!("added {id}{}", if list { ", listed in the Directory" } else { "" });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds the feed at `url` to the catalogue unless it is there already, a feed an OPML lists
|
||||
/// included, so one show is never added twice: its id, and whether it was there. For `ipx add`
|
||||
/// and the page's Add feed alike, which were the same steps written twice (#161); each finds the
|
||||
/// feed first, to say its own way why an address is not one.
|
||||
pub async fn add_to_catalogue(
|
||||
ctx: &Ctx,
|
||||
url: &str,
|
||||
folder: Option<String>,
|
||||
keywords: Vec<String>,
|
||||
) -> Result<(String, bool)> {
|
||||
// Taken before the duplicate check, so two people adding the same feed at once add it once.
|
||||
let mut cfg = ctx.edit_cfg().await;
|
||||
if let Some(existing) = subscriptions(ctx).await?.into_iter().find(|s| feed::same_feed(&s.cfg.url, url)) {
|
||||
return Ok((existing.id, true));
|
||||
}
|
||||
let id = add_one(ctx, &mut cfg, url, folder, keywords).await?;
|
||||
ctx.store_cfg(cfg).await?;
|
||||
Ok((id, false))
|
||||
}
|
||||
|
||||
/// Returns the new feed id. Adding checks the address is a feed first (`feed::find_feed`); this
|
||||
/// still names one it cannot read from its URL rather than failing.
|
||||
pub async fn add_one(
|
||||
async fn add_one(
|
||||
ctx: &Ctx,
|
||||
cfg: &mut config::Config,
|
||||
url: &str,
|
||||
|
||||
Reference in New Issue
Block a user