use std::{ffi::OsStr, time::Duration};
use clap_complete::engine::CompletionCandidate;
use timeweb_rs::{apis::apps_api, authenticated};
use crate::config::AppConfig;
const COMPLETION_TIMEOUT: Duration = Duration::from_secs(3);
fn silent_token() -> Option<String> {
if let Ok(token) = std::env::var("TWC_TOKEN")
&& !token.is_empty()
{
return Some(token);
}
if let Ok(config) = AppConfig::load()
&& let Ok(Some(token)) = config.token_for(None)
{
return Some(token);
}
#[cfg(feature = "auth")]
if let Ok(config_path) = AppConfig::path()
&& let Ok(token) = crate::auth::load_token(&config_path)
{
return Some(token);
}
None
}
pub fn complete_app(current: &OsStr) -> Vec<CompletionCandidate> {
let Some(prefix) = current.to_str() else {
return Vec::new();
};
let Some(token) = silent_token() else {
return Vec::new();
};
let config = authenticated(token);
let Ok(runtime) = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
else {
return Vec::new();
};
let Ok(Ok(resp)) = runtime.block_on(async {
tokio::time::timeout(COMPLETION_TIMEOUT, apps_api::get_apps(&config)).await
}) else {
return Vec::new();
};
let mut candidates = Vec::with_capacity(resp.apps.len() * 2);
for app in &resp.apps {
let id = app.id.to_string();
if app.name.starts_with(prefix) {
candidates.push(
CompletionCandidate::new(app.name.as_str())
.help(Some(format!("{id} ยท {:?}", app.status).into()))
);
}
if id.starts_with(prefix) {
candidates
.push(CompletionCandidate::new(id.as_str()).help(Some(app.name.clone().into())));
}
}
candidates
}