Rewrites every write-good.Passive hit in the hive-forge clap help text
into terse, imperative, active voice (meaning unchanged) and drops
clap-markdown's own fixed footer ('This document was generated
automatically by...') via MarkdownOptions::show_footer(false), since
that string isn't ours to reword and vale flagged it too.
docs/tools/{hivectl,swarmctl,forge}-cli.md are generated from each
crate's clap tree (see hive-forge/src/main.rs's MarkdownDocs verb) —
regenerated here from the fixed source, not hand-edited.
Refs #4549
113 lines
4.3 KiB
Rust
113 lines
4.3 KiB
Rust
//! `reaction <number> [--comment <id>] [list|add|remove] [content]` —
|
|
//! list, add, or remove emoji reactions on an issue/PR or one of its
|
|
//! comments.
|
|
//!
|
|
//! Forgejo's reaction endpoints work on the shared issue/PR index (PRs
|
|
//! are issues internally, same as `dependency`) when no `--comment` is
|
|
//! given; `--comment <id>` redirects to the separate comment-reaction
|
|
//! endpoint pair, keyed on the comment's own id (not the parent
|
|
//! issue/PR number — `number` still has to be passed so this verb slots
|
|
//! into `issue <n> reaction` / `pr <n> reaction` like every other
|
|
//! generic verb, but it's otherwise unused on that path).
|
|
//!
|
|
//! `content` is Forgejo's reaction shortcode vocabulary (`+1`, `-1`,
|
|
//! `laugh`, `confused`, `heart`, `hooray`, `rocket`, `eyes`, …), not a
|
|
//! raw emoji character — same set the forge web UI's reaction picker
|
|
//! offers. `--list-allowed` prints the *actual* instance-configured
|
|
//! list (`GET /settings/ui`'s `allowed_reactions`) instead of leaving a
|
|
//! caller to guess it or learn it from a 403 — this is instance-global,
|
|
//! not issue/PR-scoped, so `number`/`--comment` are ignored when it's
|
|
//! set (the number is still required positionally, same as every other
|
|
//! generic verb, but unused on this path).
|
|
|
|
use anyhow::Result;
|
|
use clap::{Args as ClapArgs, Subcommand};
|
|
use forgejo_api::structs::EditReactionOption;
|
|
|
|
use crate::client::{Client, index};
|
|
use crate::verbs::{comment_reactions, issue_reactions, print_json};
|
|
|
|
#[derive(ClapArgs)]
|
|
pub struct Args {
|
|
/// Issue or PR number. Ignored (but still required) when you pass
|
|
/// `--list-allowed`.
|
|
pub(crate) number: u64,
|
|
/// Target a specific comment's reactions instead of the issue/PR
|
|
/// itself — the comment's own id (from `comments`/`comment-show`),
|
|
/// not its position in the thread.
|
|
#[arg(long)]
|
|
comment: Option<u64>,
|
|
/// Print the instance's actual configured reaction shortcodes
|
|
/// (`GET /settings/ui`) instead of listing/adding/removing —
|
|
/// instance-global, ignores `number`/`--comment`.
|
|
#[arg(long)]
|
|
pub(crate) list_allowed: bool,
|
|
#[command(subcommand)]
|
|
action: Option<Action>,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
enum Action {
|
|
/// List reactions (default when you give no action).
|
|
List,
|
|
/// Add a reaction — a Forgejo shortcode, for example `+1`, `heart`, `rocket`.
|
|
Add { content: String },
|
|
/// Remove your own reaction with this content.
|
|
Remove { content: String },
|
|
}
|
|
|
|
pub fn run(client: &Client, args: Args) -> Result<()> {
|
|
if args.list_allowed {
|
|
let settings = client.api().get_general_ui_settings().send()?;
|
|
return print_json(&serde_json::json!(
|
|
settings.allowed_reactions.unwrap_or_default()
|
|
));
|
|
}
|
|
let (owner, name) = client.owner_repo()?;
|
|
match args.action.unwrap_or(Action::List) {
|
|
Action::List => {}
|
|
Action::Add { content } => {
|
|
let body = EditReactionOption {
|
|
content: Some(content),
|
|
};
|
|
match args.comment {
|
|
Some(id) => {
|
|
client
|
|
.api()
|
|
.issue_post_comment_reaction(owner, name, index(id)?, body)
|
|
.send()?;
|
|
}
|
|
None => {
|
|
client
|
|
.api()
|
|
.issue_post_issue_reaction(owner, name, index(args.number)?, body)
|
|
.send()?;
|
|
}
|
|
}
|
|
}
|
|
Action::Remove { content } => {
|
|
let body = EditReactionOption {
|
|
content: Some(content),
|
|
};
|
|
match args.comment {
|
|
Some(id) => {
|
|
client
|
|
.api()
|
|
.issue_delete_comment_reaction(owner, name, index(id)?, body)
|
|
.send()?;
|
|
}
|
|
None => {
|
|
client
|
|
.api()
|
|
.issue_delete_issue_reaction(owner, name, index(args.number)?, body)
|
|
.send()?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let reactions = match args.comment {
|
|
Some(id) => comment_reactions(client, owner, name, id)?,
|
|
None => issue_reactions(client, owner, name, args.number)?,
|
|
};
|
|
print_json(&serde_json::json!(reactions))
|
|
}
|