From 24e70bb2d9e778fe9f3ad1e6307be941acbff5f6 Mon Sep 17 00:00:00 2001 From: lluni <36239317+lluni@users.noreply.github.com> Date: Sun, 12 Mar 2023 22:24:43 +0100 Subject: [PATCH 1/5] feat: add support for private profiles --- Cargo.lock | 207 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +- credentials.ini | 5 ++ src/main.rs | 5 +- src/trakt.rs | 18 ++++- src/utils.rs | 142 +++++++++++++++++++++++++++++++++ 6 files changed, 373 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 379b06d..d4592b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,18 +20,36 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bumpalo" version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cc" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.0" @@ -57,12 +75,38 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "configparser" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06821ea598337a8412cf47c5b71c3bc694a7f0aed188ac28b836fab164a2c202" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "crc32fast" version = "1.3.1" @@ -72,6 +116,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "discord-rich-presence" version = "0.2.0" @@ -94,6 +158,7 @@ dependencies = [ "discord-rich-presence", "serde", "ureq", + "webbrowser", ] [[package]] @@ -146,6 +211,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "jni" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "js-sys" version = "0.3.56" @@ -186,12 +271,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -202,6 +302,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "num-integer" version = "0.1.44" @@ -221,6 +327,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "once_cell" version = "1.9.0" @@ -251,6 +366,32 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "raw-window-handle" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f851a03551ceefd30132e447f07f96cb7011d6b658374f3aed847333adb5559" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "ring" version = "0.16.20" @@ -284,6 +425,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "sct" version = "0.7.0" @@ -342,6 +492,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "thiserror" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.1.43" @@ -434,6 +604,17 @@ dependencies = [ "getrandom", ] +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -504,6 +685,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d1fa1e5c829b2bf9eb1e28fb950248b797cd6a04866fbdfa8bc31e5eef4c78" +dependencies = [ + "core-foundation", + "dirs", + "jni", + "log", + "ndk-context", + "objc", + "raw-window-handle", + "url", + "web-sys", +] + [[package]] name = "webpki" version = "0.22.0" @@ -551,6 +749,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 2d67962..13ccc6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ ureq = { version = "2.4.0", features = ["json"] } configparser = "3.0.0" serde = { version = "1.0.136", features = ["derive"] } chrono = "0.4.19" +webbrowser = "0.8.7" [profile.release] -strip = "debuginfo" \ No newline at end of file +strip = "debuginfo" diff --git a/credentials.ini b/credentials.ini index f846b7d..8dbc2ba 100644 --- a/credentials.ini +++ b/credentials.ini @@ -1,6 +1,11 @@ [Trakt API] traktClientID = 543dhkjlasfkjdsgh0928354237489230954sdkfjsdlfjhsdh4327 traktUser = exampleuser +enabledOAuth = false +traktClientSecret = +OAuthAccessToken = +OAuthRefreshToken = +OAuthRefreshTokenExpiresAt = [Discord] discordClientID = 457098328950423 diff --git a/src/main.rs b/src/main.rs index 1d327c1..c630dca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,10 @@ use discrakt::{ use std::{thread::sleep, time::Duration}; fn main() -> Result<(), Box> { - let cfg = load_config(); + let mut cfg = load_config(); + cfg.check_oauth(); let mut discord = Discord::new(cfg.discord_token); - let mut trakt = Trakt::new(cfg.trakt_client_id, cfg.trakt_username); + let mut trakt = Trakt::new(cfg.trakt_client_id, cfg.trakt_username, cfg.trakt_access_token); Discord::connect(&mut discord); loop { diff --git a/src/trakt.rs b/src/trakt.rs index 472cf48..2bb22a9 100644 --- a/src/trakt.rs +++ b/src/trakt.rs @@ -57,10 +57,11 @@ pub struct Trakt { agent: Agent, client_id: String, username: String, + oauth_access_token: Option } impl Trakt { - pub fn new(client_id: String, username: String) -> Trakt { + pub fn new(client_id: String, username: String, oauth_access_token: Option) -> Trakt { Trakt { cache: HashMap::default(), agent: AgentBuilder::new() @@ -69,19 +70,28 @@ impl Trakt { .build(), client_id, username, + oauth_access_token, } } pub fn get_watching(&self) -> Option { let endpoint = format!("https://api.trakt.tv/users/{}/watching", self.username); - let response = match self + let request = self .agent .get(&endpoint) .set("Content-Type", "application/json") .set("trakt-api-version", "2") - .set("trakt-api-key", &self.client_id) - .call() + .set("trakt-api-key", &self.client_id); + // add Authorization header if there is a (valid) OAuth access token + let request = if self.oauth_access_token.is_some() { + let authorization = format!("Bearer {}", self.oauth_access_token.as_ref().unwrap()); + request.set("Authorization", &authorization) + } else { + request + }; + + let response = match request.call() { Ok(response) => response, Err(_) => return None, diff --git a/src/utils.rs b/src/utils.rs index 853f9da..127acaa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,10 +1,130 @@ +use std::{time::Duration, io}; + use chrono::{SecondsFormat, Utc}; use configparser::ini::Ini; +use serde::Deserialize; +use ureq::AgentBuilder; + +#[derive(Deserialize)] +pub struct TraktAccessToken { + pub access_token: String, + pub token_type: String, + pub expires_in: u64, + pub refresh_token: String, + pub scope: String, + pub created_at: u64, +} pub struct Env { pub discord_token: String, pub trakt_username: String, pub trakt_client_id: String, + pub trakt_oauth_enabled: bool, + pub trakt_client_secret: Option, + pub trakt_access_token: Option, + pub trakt_refresh_token: Option, + pub trakt_refresh_token_expires_at: Option, +} + +impl Env { + pub fn check_oauth(&mut self) { + if self.trakt_oauth_enabled { + if self.trakt_access_token.is_none() || self.trakt_access_token.as_ref().unwrap().is_empty() { + self.authorize_app(); + } else if let Some(expires_at) = self.trakt_refresh_token_expires_at { + if Utc::now().timestamp() as u64 > expires_at { + self.exchange_refresh_token_for_access_token(); + } + } + } + } + + fn authorize_app(&mut self) { + if webbrowser::open( + &format!("https://trakt.tv/oauth/authorize?response_type=code&client_id={}&redirect_uri=urn:ietf:wg:oauth:2.0:oob", self.trakt_client_id) + ).is_err() { + eprintln!("Failed to open webbrowser to authorize discrakt"); + return; + }; + self.exchange_code_for_access_token(); + } + + fn exchange_code_for_access_token(&mut self) { + // read OAuth code from command line + print!("Enter code from website: "); + io::Write::flush(&mut io::stdout()).expect("Failed to flush stdout"); + let mut code = String::new(); + io::stdin().read_line(&mut code).expect("Failed to read line"); + let code = code.trim(); + + let agent = AgentBuilder::new() + .timeout_read(Duration::from_secs(5)) + .timeout_write(Duration::from_secs(5)) + .build(); + let response = match agent + .post("https://api.trakt.tv/oauth/token") + .set("Content-Type", "application/json") + .send_json(ureq::json!({ + "code": code, + "client_id": self.trakt_client_id, + "client_secret": self.trakt_client_secret.as_ref().expect("client_secret not found"), + "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", + "grant_type": "authorization_code", + })) + { + Ok(response) => response, + Err(_) => return, + }; + + let json_response: Option = match response.into_json() { + Ok(body) => body, + Err(_) => None, + }; + + if let Some(json_response) = json_response { + self.trakt_access_token = Some(json_response.access_token.clone()); + self.trakt_refresh_token = Some(json_response.refresh_token.clone()); + self.trakt_refresh_token_expires_at = Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months + set_oauth_tokens(&json_response); + } else { + eprintln!("Failed to exchange code for access token"); + } + } + + fn exchange_refresh_token_for_access_token(&mut self) { + let agent = AgentBuilder::new() + .timeout_read(Duration::from_secs(5)) + .timeout_write(Duration::from_secs(5)) + .build(); + let response = match agent + .post("https://api.trakt.tv/oauth/token") + .set("Content-Type", "application/json") + .send_json(ureq::json!({ + "code": "Get the code from the webbrowser", + "client_id": self.trakt_client_id, + "client_secret": self.trakt_client_secret.as_ref().expect("client_secret not found"), + "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", + "grant_type": "refresh_token", + })) + { + Ok(response) => response, + Err(_) => return, + }; + + let json_response: Option = match response.into_json() { + Ok(body) => body, + Err(_) => None, + }; + + if let Some(json_response) = json_response { + self.trakt_access_token = Some(json_response.access_token.clone()); + self.trakt_refresh_token = Some(json_response.refresh_token.clone()); + self.trakt_refresh_token_expires_at = Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months + set_oauth_tokens(&json_response); + } else { + eprintln!("Failed to exchange refresh token for access token"); + } + } } pub fn load_config() -> Env { @@ -21,9 +141,31 @@ pub fn load_config() -> Env { trakt_client_id: config .get("Trakt API", "traktClientID") .expect("traktClientID not found"), + trakt_oauth_enabled: config + .getbool("Trakt API", "enabledOAuth") + .expect("enableOAuth not found") + .unwrap_or(false), + trakt_client_secret: config + .get("Trakt API", "traktClientSecret"), + trakt_access_token: config + .get("Trakt API", "OAuthAccessToken"), + trakt_refresh_token: config + .get("Trakt API", "OAuthRefreshToken"), + trakt_refresh_token_expires_at: config + .getuint("Trakt API", "OAuthRefreshTokenExpiresAt") + .unwrap_or_default(), } } +fn set_oauth_tokens(json_response: &TraktAccessToken) { + let mut config = Ini::new(); + config.load("credentials.ini").expect("Failed to load credentials.ini"); + config.setstr("Trakt API", "OAuthAccessToken", Some(json_response.access_token.as_str())); + config.setstr("Trakt API", "OAuthRefreshToken", Some(json_response.refresh_token.as_str())); + config.set("Trakt API", "OAuthRefreshTokenExpiresAt", Some(json_response.created_at.to_string())); + config.write("credentials.ini").expect("Failed to write credentials.ini"); +} + pub fn log(message: &str) { println!( "{} : {}", From 1280a4d878a0e2917700961cb5efe00f66dfcb20 Mon Sep 17 00:00:00 2001 From: lluni <36239317+lluni@users.noreply.github.com> Date: Sun, 12 Mar 2023 22:48:41 +0100 Subject: [PATCH 2/5] chore: rustfmt --- src/main.rs | 6 +++++- src/trakt.rs | 5 ++--- src/utils.rs | 51 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index c630dca..65911f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,11 @@ fn main() -> Result<(), Box> { let mut cfg = load_config(); cfg.check_oauth(); let mut discord = Discord::new(cfg.discord_token); - let mut trakt = Trakt::new(cfg.trakt_client_id, cfg.trakt_username, cfg.trakt_access_token); + let mut trakt = Trakt::new( + cfg.trakt_client_id, + cfg.trakt_username, + cfg.trakt_access_token, + ); Discord::connect(&mut discord); loop { diff --git a/src/trakt.rs b/src/trakt.rs index 2bb22a9..6948afa 100644 --- a/src/trakt.rs +++ b/src/trakt.rs @@ -57,7 +57,7 @@ pub struct Trakt { agent: Agent, client_id: String, username: String, - oauth_access_token: Option + oauth_access_token: Option, } impl Trakt { @@ -91,8 +91,7 @@ impl Trakt { request }; - let response = match request.call() - { + let response = match request.call() { Ok(response) => response, Err(_) => return None, }; diff --git a/src/utils.rs b/src/utils.rs index 127acaa..580a146 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use std::{time::Duration, io}; +use std::{io, time::Duration}; use chrono::{SecondsFormat, Utc}; use configparser::ini::Ini; @@ -29,7 +29,9 @@ pub struct Env { impl Env { pub fn check_oauth(&mut self) { if self.trakt_oauth_enabled { - if self.trakt_access_token.is_none() || self.trakt_access_token.as_ref().unwrap().is_empty() { + if self.trakt_access_token.is_none() + || self.trakt_access_token.as_ref().unwrap().is_empty() + { self.authorize_app(); } else if let Some(expires_at) = self.trakt_refresh_token_expires_at { if Utc::now().timestamp() as u64 > expires_at { @@ -54,7 +56,9 @@ impl Env { print!("Enter code from website: "); io::Write::flush(&mut io::stdout()).expect("Failed to flush stdout"); let mut code = String::new(); - io::stdin().read_line(&mut code).expect("Failed to read line"); + io::stdin() + .read_line(&mut code) + .expect("Failed to read line"); let code = code.trim(); let agent = AgentBuilder::new() @@ -84,7 +88,8 @@ impl Env { if let Some(json_response) = json_response { self.trakt_access_token = Some(json_response.access_token.clone()); self.trakt_refresh_token = Some(json_response.refresh_token.clone()); - self.trakt_refresh_token_expires_at = Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months + self.trakt_refresh_token_expires_at = + Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months set_oauth_tokens(&json_response); } else { eprintln!("Failed to exchange code for access token"); @@ -119,7 +124,8 @@ impl Env { if let Some(json_response) = json_response { self.trakt_access_token = Some(json_response.access_token.clone()); self.trakt_refresh_token = Some(json_response.refresh_token.clone()); - self.trakt_refresh_token_expires_at = Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months + self.trakt_refresh_token_expires_at = + Some(json_response.created_at + 60 * 60 * 24 * 30 * 3); // secs * mins * hours * days * months => 3 months set_oauth_tokens(&json_response); } else { eprintln!("Failed to exchange refresh token for access token"); @@ -145,12 +151,9 @@ pub fn load_config() -> Env { .getbool("Trakt API", "enabledOAuth") .expect("enableOAuth not found") .unwrap_or(false), - trakt_client_secret: config - .get("Trakt API", "traktClientSecret"), - trakt_access_token: config - .get("Trakt API", "OAuthAccessToken"), - trakt_refresh_token: config - .get("Trakt API", "OAuthRefreshToken"), + trakt_client_secret: config.get("Trakt API", "traktClientSecret"), + trakt_access_token: config.get("Trakt API", "OAuthAccessToken"), + trakt_refresh_token: config.get("Trakt API", "OAuthRefreshToken"), trakt_refresh_token_expires_at: config .getuint("Trakt API", "OAuthRefreshTokenExpiresAt") .unwrap_or_default(), @@ -159,11 +162,27 @@ pub fn load_config() -> Env { fn set_oauth_tokens(json_response: &TraktAccessToken) { let mut config = Ini::new(); - config.load("credentials.ini").expect("Failed to load credentials.ini"); - config.setstr("Trakt API", "OAuthAccessToken", Some(json_response.access_token.as_str())); - config.setstr("Trakt API", "OAuthRefreshToken", Some(json_response.refresh_token.as_str())); - config.set("Trakt API", "OAuthRefreshTokenExpiresAt", Some(json_response.created_at.to_string())); - config.write("credentials.ini").expect("Failed to write credentials.ini"); + config + .load("credentials.ini") + .expect("Failed to load credentials.ini"); + config.setstr( + "Trakt API", + "OAuthAccessToken", + Some(json_response.access_token.as_str()), + ); + config.setstr( + "Trakt API", + "OAuthRefreshToken", + Some(json_response.refresh_token.as_str()), + ); + config.set( + "Trakt API", + "OAuthRefreshTokenExpiresAt", + Some(json_response.created_at.to_string()), + ); + config + .write("credentials.ini") + .expect("Failed to write credentials.ini"); } pub fn log(message: &str) { From 66a1de5967d4c79222b0a715f75350977062d922 Mon Sep 17 00:00:00 2001 From: lluni <36239317+lluni@users.noreply.github.com> Date: Mon, 13 Mar 2023 01:43:47 +0100 Subject: [PATCH 3/5] fix: send auth header only when there is a valid token --- src/trakt.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/trakt.rs b/src/trakt.rs index 6948afa..9d47587 100644 --- a/src/trakt.rs +++ b/src/trakt.rs @@ -84,7 +84,9 @@ impl Trakt { .set("trakt-api-version", "2") .set("trakt-api-key", &self.client_id); // add Authorization header if there is a (valid) OAuth access token - let request = if self.oauth_access_token.is_some() { + let request = if self.oauth_access_token.is_some() + && !self.oauth_access_token.as_ref().unwrap().is_empty() + { let authorization = format!("Bearer {}", self.oauth_access_token.as_ref().unwrap()); request.set("Authorization", &authorization) } else { From be79c4776e41c1ecd62c074c6a3fc8440fac25ac Mon Sep 17 00:00:00 2001 From: lluni <36239317+lluni@users.noreply.github.com> Date: Mon, 13 Mar 2023 16:58:10 +0100 Subject: [PATCH 4/5] fix: write to ini with case sensitivity --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index 580a146..6b01154 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -161,7 +161,7 @@ pub fn load_config() -> Env { } fn set_oauth_tokens(json_response: &TraktAccessToken) { - let mut config = Ini::new(); + let mut config = Ini::new_cs(); config .load("credentials.ini") .expect("Failed to load credentials.ini"); From 43367360f9d6d6326325717f1b7523cb7ddddf88 Mon Sep 17 00:00:00 2001 From: lluni <36239317+lluni@users.noreply.github.com> Date: Mon, 13 Mar 2023 17:10:12 +0100 Subject: [PATCH 5/5] fix: keep the order of entries in credentials.ini --- Cargo.lock | 23 +++++++++++++++++++++-- Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4592b6..7a36925 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,9 +87,12 @@ dependencies = [ [[package]] name = "configparser" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06821ea598337a8412cf47c5b71c3bc694a7f0aed188ac28b836fab164a2c202" +checksum = "5458d9d1a587efaf5091602c59d299696a3877a439c8f6d461a2d3cce11df87a" +dependencies = [ + "indexmap", +] [[package]] name = "core-foundation" @@ -194,6 +197,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "idna" version = "0.2.3" @@ -205,6 +214,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 13ccc6d..49b071d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ exclude = [ [dependencies] discord-rich-presence = "0.2.0" ureq = { version = "2.4.0", features = ["json"] } -configparser = "3.0.0" +configparser = { version = "3.0.2", features = ["indexmap"] } serde = { version = "1.0.136", features = ["derive"] } chrono = "0.4.19" webbrowser = "0.8.7"