Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/hive-forge/src/verbs/subscription.rs

95 lines
3.2 KiB
Rust

//! `subscription [--watch|--unwatch|--list] [repo]` — get or set the
//! current user's watch subscription for a repo, or list every repo the
//! user watches (`--list`, for auditing the notification firehose).
//!
//! There is deliberately no `--ignore`: Forgejo's subscription endpoint
//! has no way to mark a repo ignored without also watching it (its PUT
//! takes no body), so a mute flag here can only ever be subscribe or
//! unsubscribe under the hood. Rather than keep a flag that refuses with
//! an error, this verb just exposes the two states Forgejo actually has.
use anyhow::Result;
use clap::Args as ClapArgs;
use serde_json::json;
use crate::client::{Client, is_not_found};
use crate::verbs::print_json;
#[derive(ClapArgs)]
pub struct Args {
/// Subscribe (watch the repo).
#[arg(long, group = "action")]
watch: bool,
/// Unsubscribe (stop watching).
#[arg(long, group = "action")]
unwatch: bool,
/// List every repo the current user watches (ignores `[repo]`).
#[arg(long, group = "action")]
list: bool,
}
/// Run the `subscription` verb: `--list` all watched repos, set the
/// current repo's watch (`--watch` / `--unwatch`), or get its current
/// state.
///
/// # Errors
/// Propagates transport / non-2xx errors from the Forgejo client calls
/// and from `print_json`.
pub fn run(client: &Client, args: Args) -> Result<()> {
if args.list {
// List every repo the authed user watches, so an agent can audit
// its notification firehose and decide what to `--unwatch`. Not
// repo-scoped. Paginated, with a generous page cap so a
// misbehaving server can't spin us forever.
const MAX_PAGES: u32 = 50;
const PAGE: u32 = 50;
let mut watching: Vec<String> = Vec::new();
for page in 1..=MAX_PAGES {
let (_, repos) = client
.api()
.user_current_list_subscriptions()
.page(page)
.page_size(PAGE)
.send()?;
let n = repos.len();
watching.extend(repos.into_iter().filter_map(|r| r.full_name));
if n < PAGE as usize {
break;
}
}
return print_json(&json!({ "watching": watching }));
}
let (owner, name) = client.owner_repo()?;
if args.unwatch {
client
.api()
.user_current_delete_subscription(owner, name)
.send()?;
println!("unsubscribed");
return Ok(());
}
if args.watch {
let resp = client
.api()
.user_current_put_subscription(owner, name)
.send()?;
return print_json(&json!({
"subscribed": resp.subscribed,
"ignored": resp.ignored,
}));
}
// Forgejo returns 404 when the current user is not watching the repo
// (rather than a response with subscribed=false).
match client
.api()
.user_current_check_subscription(owner, name)
.send()
{
Ok(resp) => print_json(&json!({
"subscribed": resp.subscribed,
"ignored": resp.ignored,
})),
Err(e) if is_not_found(&e) => print_json(&json!({ "subscribed": false, "ignored": false })),
Err(e) => Err(e.into()),
}
}