use std::collections::HashMap;
use anyhow::Result;
use derive_config::DeriveTomlConfig;
use inquire::{
list_option::ListOption,
validator::{ErrorMessage, Validation},
Confirm,
MultiSelect,
Select,
};
use serde::{Deserialize, Serialize};
use strum::{Display, IntoEnumIterator};
use crate::{discord, discord::DEVELOPER_ID, provider::ProviderKind};
#[derive(Display, Deserialize, Serialize, Default)]
pub enum Attribution {
#[strum(to_string = "Anonymously (VRC-LOG Dev)")]
#[default]
Anonymous,
#[strum(to_string = "Discord RPC ({0})")]
DiscordRPC(String),
#[strum(to_string = "Discord ID (Manual Input)")]
DiscordID(String),
}
impl Attribution {
#[must_use]
pub fn get_user_id(&self) -> String {
match self {
Self::Anonymous => DEVELOPER_ID.to_string(),
Self::DiscordID(id) => id.clone(),
Self::DiscordRPC(id) => discord::get_user()
.and_then(|u| u.id)
.unwrap_or_else(|| id.clone()),
}
}
}
#[derive(DeriveTomlConfig, Deserialize, Serialize, Default)]
pub struct Settings {
pub attribution: Attribution,
pub clear_amplitude: bool,
pub print_scanned: bool,
pub providers: HashMap<ProviderKind, bool>,
}
impl Settings {
pub fn try_wizard() -> Result<Self> {
let mut attributions = vec![
Attribution::Anonymous,
Attribution::DiscordID(String::new()),
];
if let Some(user) = discord::get_user() {
attributions.insert(1, Attribution::DiscordRPC(user.id.unwrap()));
}
let attribution = Select::new("How do you want to be credited?", attributions).prompt()?;
let providers = {
let providers = ProviderKind::iter().collect::<Vec<_>>();
let enabled = MultiSelect::new("Select which providers to use:", providers.clone())
.with_default(&[0])
.with_validator(|list: &[ListOption<&ProviderKind>]| {
if list.is_empty() {
let message = String::from("You must select at least one.");
Ok(Validation::Invalid(ErrorMessage::Custom(message)))
} else {
Ok(Validation::Valid)
}
})
.prompt()?;
providers
.iter()
.map(|provider| (*provider, enabled.contains(provider)))
.collect()
};
let clear_amplitude = Confirm::new(
"Clear amplitude file after reading? (Helps with privacy by removing tracked data)",
)
.with_default(true)
.prompt()?;
let print_scanned = Confirm::new(
"Print all scanned avatar ids instead of just the uniquely discovered ones",
)
.with_default(false)
.prompt()?;
Ok(Self {
attribution,
clear_amplitude,
print_scanned,
providers,
})
}
}