diff --git a/examples/basic.rs b/examples/basic.rs index bfe4344..ccac7d6 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,16 +1,16 @@ use std::env; use teslatte::auth::AccessToken; use teslatte::products::Product; -use teslatte::Api; +use teslatte::OwnerApi; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let api = match env::var("TESLA_ACCESS_TOKEN") { - Ok(t) => Api::new(AccessToken(t), None), + Ok(t) => OwnerApi::new(AccessToken(t), None), Err(_) => { - let api = Api::from_interactive_url().await.unwrap(); + let api = OwnerApi::from_interactive_url().await.unwrap(); println!("TOKEN: {:?}", api.access_token); api } diff --git a/src/auth.rs b/src/auth.rs index 55a3e2f..5d0be5b 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,5 +1,5 @@ use crate::error::TeslatteError::{CouldNotFindCallbackCode, CouldNotFindState}; -use crate::{Api, TeslatteError}; +use crate::{OwnerApi, TeslatteError}; use derive_more::{Display, FromStr}; use rand::Rng; use reqwest::Client; @@ -22,11 +22,11 @@ struct Callback { state: String, } -impl Api { +impl OwnerApi { /// Show a URL for the user to click on to log into tesla.com, the ask them to paste the /// URL they end up on, which is a 404 page. The URL contains OAuth information needed to /// complete authentication for an access key. - pub async fn from_interactive_url() -> Result { + pub async fn from_interactive_url() -> Result { let login_form = Self::get_login_url_for_user().await; println!("{}", "-".repeat(80)); println!("{}", login_form.url); @@ -40,12 +40,12 @@ page, where the URL will start with https://auth.tesla.com/void/callback?code=.. let callback_url = ask_input("Enter the whole URL of the 404 page: "); println!(); // Newline to make the next output more separated and clear. - Api::from_callback_url(&login_form, &callback_url).await + OwnerApi::from_callback_url(&login_form, &callback_url).await } /// Generate a [LoginForm] containing a URL the user should visit. /// - /// See [Api::from_callback_url()] for the next step. + /// See [OwnerApi::from_callback_url()] for the next step. pub async fn get_login_url_for_user() -> LoginForm { let code = Code::new(); let state = random_string(8); @@ -54,11 +54,11 @@ page, where the URL will start with https://auth.tesla.com/void/callback?code=.. } /// Parse a callback URL that the user was redirected to after logging in via - /// [Api::from_interactive_url()]. + /// [OwnerApi::from_interactive_url()]. pub async fn from_callback_url( login_form: &LoginForm, callback_url: &str, - ) -> Result { + ) -> Result { let callback = Self::extract_callback_from_url(callback_url)?; if callback.state != login_form.state { return Err(TeslatteError::StateMismatch { @@ -70,12 +70,14 @@ page, where the URL will start with https://auth.tesla.com/void/callback?code=.. let bearer = Self::exchange_auth_for_bearer(&login_form.code, &callback.code).await?; let access_token = AccessToken(bearer.access_token); let refresh_token = RefreshToken(bearer.refresh_token); - Ok(Api::new(access_token, Some(refresh_token))) + Ok(OwnerApi::new(access_token, Some(refresh_token))) } - pub async fn from_refresh_token(refresh_token: &RefreshToken) -> Result { + pub async fn from_refresh_token( + refresh_token: &RefreshToken, + ) -> Result { let response = Self::refresh_token(refresh_token).await?; - Ok(Api::new( + Ok(OwnerApi::new( response.access_token, Some(response.refresh_token), )) diff --git a/src/cli/energy.rs b/src/cli/energy.rs index d383efa..6454e5d 100644 --- a/src/cli/energy.rs +++ b/src/cli/energy.rs @@ -1,7 +1,7 @@ use crate::cli::print_json; use crate::energy_sites::{CalendarHistoryValues, HistoryKind, HistoryPeriod}; use crate::products::EnergySiteId; -use crate::Api; +use crate::OwnerApi; use chrono::DateTime; use clap::{Args, Subcommand}; use miette::{IntoDiagnostic, WrapErr}; @@ -23,7 +23,7 @@ pub struct EnergySiteArgs { } impl EnergySiteArgs { - pub async fn run(&self, api: &Api) -> miette::Result<()> { + pub async fn run(&self, api: &OwnerApi) -> miette::Result<()> { match &self.command { EnergySiteCommand::SiteStatus => { print_json(api.energy_sites_site_status(&self.id).await); diff --git a/src/cli/powerwall.rs b/src/cli/powerwall.rs index 8b5e3e0..77b5f76 100644 --- a/src/cli/powerwall.rs +++ b/src/cli/powerwall.rs @@ -1,7 +1,7 @@ use crate::cli::print_json_data; use crate::energy_sites::{HistoryKind, HistoryPeriod}; use crate::powerwall::{PowerwallEnergyHistoryValues, PowerwallId}; -use crate::Api; +use crate::OwnerApi; use clap::{Args, Subcommand}; #[derive(Debug, Subcommand)] @@ -21,7 +21,7 @@ pub struct PowerwallArgs { } impl PowerwallArgs { - pub async fn run(&self, api: &Api) -> miette::Result<()> { + pub async fn run(&self, api: &OwnerApi) -> miette::Result<()> { match self.command { PowerwallCommand::Status => { print_json_data(api.powerwall_status(&self.id).await?); diff --git a/src/cli/vehicle.rs b/src/cli/vehicle.rs index 9c5a5ef..57ab5e0 100644 --- a/src/cli/vehicle.rs +++ b/src/cli/vehicle.rs @@ -2,7 +2,7 @@ use crate::cli::print_json; use crate::vehicles::{ SetChargeLimit, SetChargingAmps, SetScheduledCharging, SetScheduledDeparture, SetTemperatures, }; -use crate::{Api, VehicleId}; +use crate::{OwnerApi, VehicleId}; use clap::{Args, Subcommand}; #[derive(Debug, Subcommand)] @@ -74,7 +74,7 @@ pub struct VehicleArgs { } impl VehicleArgs { - pub async fn run(self, api: &Api) -> miette::Result<()> { + pub async fn run(self, api: &OwnerApi) -> miette::Result<()> { match self.command { VehicleCommand::VehicleData => { print_json(api.vehicle_data(&self.id).await); diff --git a/src/energy_sites.rs b/src/energy_sites.rs index 359866e..cc03b51 100644 --- a/src/energy_sites.rs +++ b/src/energy_sites.rs @@ -1,11 +1,11 @@ use crate::products::EnergySiteId; -use crate::{get_arg, get_args, join_query_pairs, rfc3339, Api, Values}; +use crate::{get_arg, get_args, join_query_pairs, rfc3339, OwnerApi, Values}; use chrono::{DateTime, FixedOffset}; use serde::Deserialize; use strum::{Display, EnumString, IntoStaticStr}; #[rustfmt::skip] -impl Api { +impl OwnerApi { get_arg!(energy_sites_site_status, SiteStatus, "/energy_sites/{}/site_status", EnergySiteId); get_arg!(energy_sites_live_status, LiveStatus, "/energy_sites/{}/live_status", EnergySiteId); get_arg!(energy_sites_site_info, SiteInfo, "/energy_sites/{}/site_info", EnergySiteId); diff --git a/src/lib.rs b/src/lib.rs index 5c67845..fc1189b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,13 +25,13 @@ trait Values { /// Vehicle ID used by the owner-api endpoint. /// -/// This data comes from [`Api::vehicles()`] `id` field. +/// This data comes from [`OwnerApi::vehicles()`] `id` field. #[derive(Debug, Serialize, Deserialize, Clone, Display, FromStr)] pub struct VehicleId(u64); /// Vehicle ID used by other endpoints. /// -/// This data comes from [`Api::vehicles()`] `vehicle_id` field. +/// This data comes from [`OwnerApi::vehicles()`] `vehicle_id` field. #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ExternalVehicleId(u64); @@ -53,15 +53,15 @@ impl Display for RequestData<'_> { /// /// Main entry point for the API. It contains the access token and refresh token, and can be used /// to make requests to the API. -pub struct Api { +pub struct OwnerApi { pub access_token: AccessToken, pub refresh_token: Option, client: Client, } -impl Api { +impl OwnerApi { pub fn new(access_token: AccessToken, refresh_token: Option) -> Self { - Api { + OwnerApi { access_token, refresh_token, client: Client::builder() @@ -119,7 +119,10 @@ impl Api { let response_body = request_builder .header("Accept", "application/json") - .header("Authorization", format!("Bearer {}", self.access_token.0.trim())) + .header( + "Authorization", + format!("Bearer {}", self.access_token.0.trim()), + ) .send() .await .map_err(|source| TeslatteError::FetchError { @@ -347,7 +350,7 @@ mod tests { payload: "doesn't matter", }; - let e = Api::parse_json::(&request_data, s.to_string()); + let e = OwnerApi::parse_json::(&request_data, s.to_string()); if let Err(e) = e { if let TeslatteError::ServerError { msg, description, .. diff --git a/src/main.rs b/src/main.rs index 9ba48f8..5e417e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use teslatte::cli::energy::EnergySiteArgs; use teslatte::cli::powerwall::PowerwallArgs; use teslatte::cli::print_json; use teslatte::cli::vehicle::VehicleArgs; -use teslatte::Api; +use teslatte::OwnerApi; /// Teslatte /// @@ -76,7 +76,7 @@ async fn main() -> miette::Result<()> { match args.command { Command::Auth { save } => { - let api = Api::from_interactive_url().await?; + let api = OwnerApi::from_interactive_url().await?; print_or_save_tokens(save, &api); } Command::Refresh { refresh_token } => { @@ -88,7 +88,7 @@ async fn main() -> miette::Result<()> { } }; - let api = Api::from_refresh_token(&refresh_token).await?; + let api = OwnerApi::from_refresh_token(&refresh_token).await?; print_or_save_tokens(save, &api); } Command::Api(api_args) => { @@ -103,7 +103,7 @@ async fn main() -> miette::Result<()> { } }; - let api = Api::new(access_token, refresh_token); + let api = OwnerApi::new(access_token, refresh_token); match api_args.command { ApiCommand::Vehicles => { print_json(api.vehicles().await); @@ -126,7 +126,7 @@ async fn main() -> miette::Result<()> { Ok(()) } -fn print_or_save_tokens(save: bool, api: &Api) { +fn print_or_save_tokens(save: bool, api: &OwnerApi) { let access_token = api.access_token.clone(); let refresh_token = api.refresh_token.clone().unwrap(); diff --git a/src/powerwall.rs b/src/powerwall.rs index dd3f233..5b365f0 100644 --- a/src/powerwall.rs +++ b/src/powerwall.rs @@ -1,12 +1,12 @@ use crate::energy_sites::{HistoryKind, HistoryPeriod}; use crate::products::GatewayId; -use crate::{get_arg, get_args, join_query_pairs, rfc3339, Api, Values}; +use crate::{get_arg, get_args, join_query_pairs, rfc3339, OwnerApi, Values}; use chrono::{DateTime, FixedOffset}; use derive_more::{Display, FromStr}; use serde::{Deserialize, Serialize}; #[rustfmt::skip] -impl Api { +impl OwnerApi { get_arg!(powerwall_status, PowerwallStatus, "/powerwalls/{}/status", PowerwallId); get_args!(powerwall_energy_history, PowerwallEnergyHistory, "/powerwalls/{}/energyhistory", PowerwallEnergyHistoryValues); } diff --git a/src/products.rs b/src/products.rs index defe63f..0216bce 100644 --- a/src/products.rs +++ b/src/products.rs @@ -1,13 +1,13 @@ use crate::error::TeslatteError; use crate::powerwall::PowerwallId; use crate::vehicles::VehicleData; -use crate::{get, Api}; +use crate::{get, OwnerApi}; use derive_more::Display; use serde::{Deserialize, Serialize}; use std::str::FromStr; #[rustfmt::skip] -impl Api { +impl OwnerApi { get!(products, Vec, "/products"); } @@ -226,7 +226,10 @@ mod tests { assert_eq!(v.api_version, 42); assert_eq!(v.backseat_token, None); assert_eq!(v.backseat_token_updated_at, None); - assert_eq!(v.vehicle_config.unwrap().aux_park_lamps, Some("Eu".to_string())); + assert_eq!( + v.vehicle_config.unwrap().aux_park_lamps, + Some("Eu".to_string()) + ); } else { panic!("Wrong EnergySite"); } diff --git a/src/vehicles.rs b/src/vehicles.rs index a689fe4..e9c328b 100644 --- a/src/vehicles.rs +++ b/src/vehicles.rs @@ -2,11 +2,13 @@ /// /// Sometimes the API will return a null for a field where I've put in a non Option type, which /// will cause the deserializer to fail. Please log an issue to fix these if you come across it. -use crate::{get, get_arg, post_arg, post_arg_empty, Api, Empty, ExternalVehicleId, VehicleId}; +use crate::{ + get, get_arg, post_arg, post_arg_empty, Empty, ExternalVehicleId, OwnerApi, VehicleId, +}; use serde::{Deserialize, Serialize}; #[rustfmt::skip] -impl Api { +impl OwnerApi { get!(vehicles, Vec, "/vehicles"); get_arg!(vehicle_data, VehicleData, "/vehicles/{}/vehicle_data", VehicleId); post_arg_empty!(wake_up, "/vehicles/{}/command/wake_up", VehicleId); @@ -482,7 +484,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/charge_state", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -529,7 +531,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/climate_state", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -556,7 +558,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/drive_state", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -578,7 +580,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/gui_settings", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -628,7 +630,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/vehicle_config", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -703,7 +705,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/data_request/vehicle_state", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -713,7 +715,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -723,7 +725,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -733,7 +735,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -743,7 +745,7 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } #[test] @@ -753,6 +755,6 @@ mod tests { let request_data = RequestData::Get { url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", }; - Api::parse_json::(&request_data, s.to_string()).unwrap(); + OwnerApi::parse_json::(&request_data, s.to_string()).unwrap(); } }