use clap::Parser; use eyre::{Context, ContextCompat}; use graphql_client::{reqwest::post_graphql_blocking as post_graphql, GraphQLQuery}; use reqwest::blocking::Client; #[derive(clap::ValueEnum, Clone, Debug)] enum Availability { Busy, Free, } #[derive(Parser, Debug, Clone)] #[command(author, version, about, long_about = None)] struct Args { /// Emoji to set ':smile:' #[arg(short, long)] emoji: Option, /// Message to display #[arg(short, long)] message: Option, #[arg(value_enum)] availability: Option, #[arg(long)] expires_in_minutes: Option, #[arg(short, long)] organization_id: Option, #[clap(env, long)] github_token: Option, #[clap(env, long)] github_url: Option, } struct Status { emoji: Option, message: Option, availability: Availability, expires: Option>, organization_id: Option, } fn main() -> eyre::Result<()> { let args = Args::parse(); let status = get_status_input(args.clone())?; let github_token = get_github_token(args.clone())?; set_github_status(args.github_url, github_token, status)?; Ok(()) } fn get_status_input(args: Args) -> eyre::Result { Ok(Status { emoji: args.emoji, message: args.message, availability: match args.availability { Some(av) => av, None => Availability::Free, }, expires: match args.expires_in_minutes { Some(0) => None, Some(min) => Some(chrono::offset::Utc::now() + chrono::Duration::minutes(min)), None => None, }, organization_id: args.organization_id, }) } fn get_github_token(args: Args) -> eyre::Result { match args.github_token { Some(token) => Ok(token), None => { // Temporary maybe moved because this should support different providers Err(eyre::anyhow!("could not find github_token variable")) } } } type DateTime = String; #[derive(GraphQLQuery)] #[graphql( schema_path = "commands/schema/github.graphql", query_path = "commands/mutations/setGithubStatus.graphql", response_derives = "Debug" )] pub struct SetStatus; fn set_github_status( github_url: Option, github_token: String, status: Status, ) -> eyre::Result<()> { let client = Client::builder() .user_agent("graphql-rust/0.10.0") .default_headers( std::iter::once(( reqwest::header::AUTHORIZATION, reqwest::header::HeaderValue::from_str(&format!("Bearer {}", github_token)) .context("could not format bearer token")?, )) .collect(), ) .build()?; let variables = set_status::Variables { status: set_status::ChangeUserStatusInput { client_mutation_id: None, emoji: status.emoji, expires_at: status .expires .map(|expires| expires.to_rfc3339_opts(chrono::SecondsFormat::Millis, true)), limited_availability: Some(match status.availability { Availability::Busy => true, Availability::Free => false, }), message: status.message, organization_id: status.organization_id, }, }; let response_body = post_graphql::( &client, match github_url { Some(url) => url, None => "https://api.github.com/graphql".into(), }, variables, ) .unwrap(); let _: set_status::ResponseData = response_body.data.context("missing response data")?; Ok(()) }