feat(user): user view and user browse

This commit is contained in:
Cyborus 2024-06-17 23:38:58 -04:00
parent 839a63bb39
commit 3a00896674
No known key found for this signature in database
2 changed files with 107 additions and 6 deletions

View file

@ -241,7 +241,7 @@ struct SpecialRender {
// blue: &'static str,
bright_blue: &'static str,
// cyan: &'static str,
// bright_cyan: &'static str,
bright_cyan: &'static str,
yellow: &'static str,
// bright_yellow: &'static str,
// magenta: &'static str,
@ -292,7 +292,7 @@ impl SpecialRender {
// blue: "\x1b[34m",
bright_blue: "\x1b[94m",
// cyan: "\x1b[36m",
// bright_cyan: "\x1b[96m",
bright_cyan: "\x1b[96m",
yellow: "\x1b[33m",
// bright_yellow: "\x1b[93m",
// magenta: "\x1b[35m",
@ -334,7 +334,7 @@ impl SpecialRender {
// blue: "",
bright_blue: "",
// cyan: "",
// bright_cyan: "",
bright_cyan: "",
yellow: "",
// bright_yellow: "",
// magenta: "",

View file

@ -1,6 +1,8 @@
use clap::{Args, Subcommand};
use eyre::OptionExt;
use forgejo_api::Forgejo;
use crate::repo::RepoInfo;
use crate::{repo::RepoInfo, SpecialRender};
#[derive(Args, Clone, Debug)]
pub struct UserCommand {
@ -11,13 +13,112 @@ pub struct UserCommand {
}
#[derive(Subcommand, Clone, Debug)]
pub enum UserSubcommand {}
pub enum UserSubcommand {
View {
/// The name of the user to view
user: Option<String>,
},
Browse {
/// The name of the user to open in your browser
user: Option<String>,
},
}
impl UserCommand {
pub async fn run(self, keys: &mut crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
let repo = RepoInfo::get_current(host_name, None, self.remote.as_deref())?;
let api = keys.get_api(repo.host_url()).await?;
match self.command {}
match self.command {
UserSubcommand::View { user } => view_user(&api, user.as_deref()).await?,
UserSubcommand::Browse { user } => {
browse_user(&api, repo.host_url(), user.as_deref()).await?
}
}
Ok(())
}
}
async fn view_user(api: &Forgejo, user: Option<&str>) -> eyre::Result<()> {
let SpecialRender {
bold,
dash,
bright_cyan,
light_grey,
reset,
..
} = *crate::special_render();
let user_data = match user {
Some(user) => api.user_get(user).await?,
None => api.user_get_current().await?,
};
let username = user_data
.login
.as_deref()
.ok_or_eyre("user has no username")?;
print!("{bright_cyan}{bold}{username}{reset}");
if let Some(pronouns) = user_data.pronouns.as_deref() {
if !pronouns.is_empty() {
print!("{light_grey} {dash} {bold}{pronouns}{reset}");
}
}
println!();
let followers = user_data.followers_count.unwrap_or_default();
let following = user_data.following_count.unwrap_or_default();
println!("{bold}{followers}{reset} followers {dash} {bold}{following}{reset} following");
let mut first = true;
if let Some(website) = user_data.website.as_deref() {
if !website.is_empty() {
print!("{bold}{website}{reset}");
first = false;
}
}
if let Some(email) = user_data.email.as_deref() {
if !email.is_empty() && !email.contains("noreply") {
if !first {
print!(" {dash} ");
}
print!("{bold}{email}{reset}");
}
}
if !first {
println!();
}
if let Some(desc) = user_data.description.as_deref() {
if !desc.is_empty() {
println!();
println!("{}", crate::markdown(desc));
println!();
}
}
let joined = user_data
.created
.ok_or_eyre("user does not have join date")?;
let date_format = time::macros::format_description!("[month repr:short] [day], [year]");
println!("Joined on {bold}{}{reset}", joined.format(&date_format)?);
Ok(())
}
async fn browse_user(api: &Forgejo, host_url: &url::Url, user: Option<&str>) -> eyre::Result<()> {
let username = match user {
Some(user) => user.to_owned(),
None => {
let myself = api.user_get_current().await?;
myself
.login
.ok_or_eyre("authenticated user does not have login")?
}
};
// `User` doesn't have an `html_url` field, so we gotta construct the user
// page url ourselves
let mut url = host_url.clone();
url.path_segments_mut()
.map_err(|_| eyre::eyre!("invalid host url"))?
.push(&username);
open::that(url.as_str())?;
Ok(())
}