use colored::{ColoredString, Colorize};
use std::{io, time::Duration};
use smartcar::*;
use auth_client::{AuthClient, AuthUrlOptionsBuilder};
use response::*;
use vehicle::Vehicle;
const DELAY: u64 = 300;
#[tokio::main]
async fn main() -> Result<(), error::Error> {
let auth_client = AuthClient::from_env(true);
let auth_url_options = AuthUrlOptionsBuilder::new().set_force_prompt(true);
let scope = ScopeBuilder::new().add_permissions([
Permission::ReadVehicleInfo,
Permission::ReadOdometer,
Permission::ReadVin,
Permission::ReadCharge,
Permission::ReadBattery,
Permission::ReadTires,
]);
let auth_url = auth_client.get_auth_url(&scope, Some(&auth_url_options));
_print_instructions(&auth_url).await;
let mut auth_code = String::new();
io::stdin()
.read_line(&mut auth_code)
.expect("Expected the query `code`");
println!("\nYou entered: {}", auth_code.blue());
let (access, _) = auth_client
.exchange_code(auth_code.trim())
.await?;
let (ids, _) = smartcar::get_vehicles(&access, None, None).await?;
let vehicle = Vehicle::new(&ids.vehicles[0], &access.access_token);
let (attributes, _) = vehicle.attributes().await?;
let (odometer, _) = vehicle.odometer().await?;
let (vin, _) = vehicle.vin().await?;
let (battery_level, _) = vehicle.battery_level().await?;
let (charging_status, _) = vehicle.charging_status().await?;
_retro_narrative(attributes, odometer, vin, battery_level, charging_status).await;
Ok(())
}
async fn _print_instructions(auth_url: &str) {
let mut message = "\nSMARTCAR RUST SDK - GETTING STARTED - CLI"
.yellow()
.bold();
println!("{message}");
println!(
"\nIn this example, you you will be playing both the roles of the application developer"
);
println!("AND the vehicle owner (i.e the user).");
println!("\nYou will begin by going through Smartcar Connect.");
println!("Smartcar Connect is the authorization flow that your users will go through.");
println!("Through Connect, your users can can grant your application permission(s)");
println!("to make requests to their vehicle.");
println!("\nYou are going to request permission to get the attributes,");
println!("odometer reading, vin, charge state, and battery level of a Tesla!");
message = "\nP.S. Be a good sport and actually pick a Tesla :)".yellow();
println!("{message}");
println!("\nWe are going to be using test mode with mock cars. While in test mode,");
println!("when prompted, you can choose any car and in enter fake credentials");
message = "e.g. blah@blah.com, pass1234".white();
println!("{message}");
println!("\nAfter going through Smartcar Connect, you will be redirected to your");
println!("REDIRECT URI with an auth code (i.e. with query of `code`).");
println!("For example, if your redirect URI is:");
message = "http://fake-redirect-uri.com/".cyan();
println!("{message}");
println!("\n...upon permission approval, it will be called like this:");
message = "http://fake-redirect-uri.com/callback?code=12345-abcde".cyan();
println!("{message}");
println!("\nIn this example is, your auth `code` is:");
message = "12345-abcde".purple();
println!("{message}");
println!("\nPaste the following URL in a browser to proceed with the Smartcar Connect flow:");
let a = auth_url.clone().green();
println!("\n{a}");
message = "After you finish, paste your code below:"
.red()
.bold();
println!("\n{message}");
}
async fn _retro_narrative(
attributes: VehicleAttributes,
odometer: Odometer,
vin: Vin,
battery_level: BatteryLevel,
charging_status: ChargingStatus,
) {
async fn _print_and_delay(msg: &ColoredString) {
println!("{}", msg);
tokio::time::sleep(Duration::from_millis(DELAY)).await;
}
let mut _m = String::new();
_m = "Successfully exchanged the code for access tokens".to_string();
_print_and_delay(&_m.white()).await;
_m = "\nSuccessfully got the list of vehicle ids".to_string();
_print_and_delay(&_m.white()).await;
_m = "\nUsing the first vehicle".to_string();
_print_and_delay(&_m.white()).await;
_m = format!(
"\nGot vehicle's id, make, model, and year!\n\n{:#?}",
attributes
);
_print_and_delay(&_m.purple()).await;
_m = format!("\nGot the vehicle's odometer reading!\n\n{:#?}", odometer);
_print_and_delay(&_m.red()).await;
_m = format!("\nGot the vehicle's vin!\n\n{:#?}", vin);
_print_and_delay(&_m.yellow()).await;
_m = format!("\nGot the vehicle's battery!\n\n{:#?}", battery_level);
_print_and_delay(&_m.green()).await;
_m = format!("\nGot the vehicle's charge!\n\n{:#?}", charging_status);
_print_and_delay(&_m.blue()).await;
println!("\n\nEND");
}