From 5ca4dd36005c8bf0dde43455f7ab9780d7a0b386 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 16 Feb 2023 03:53:00 -0500 Subject: [PATCH] use session cookie credentials instead, because API sessions broken --- Cargo.lock | 45 ++++++++++++++ crates/lib/fakeyou_client/Cargo.toml | 2 +- crates/lib/fakeyou_client/src/credentials.rs | 45 ++++++++++++++ .../fakeyou_client/src/fakeyou_api_client.rs | 59 +++++++++++++++---- crates/lib/fakeyou_client/src/lib.rs | 1 + crates/programs/aichatbot-sidecar/src/main.rs | 8 ++- .../aichatbot-sidecar/src/startup_args.rs | 4 ++ 7 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 crates/lib/fakeyou_client/src/credentials.rs diff --git a/Cargo.lock b/Cargo.lock index cdb57a736..b9d40aa95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1658,6 +1658,33 @@ dependencies = [ "version_check", ] +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding 2.2.0", + "time 0.3.14", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" +dependencies = [ + "cookie 0.16.2", + "idna 0.2.3", + "log", + "publicsuffix", + "serde", + "serde_json", + "time 0.3.14", + "url 2.3.1", +] + [[package]] name = "copyless" version = "0.1.5" @@ -5022,6 +5049,22 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" +dependencies = [ + "idna 0.3.0", + "psl-types", +] + [[package]] name = "pulldown-cmark" version = "0.8.0" @@ -5344,6 +5387,8 @@ checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64 0.21.0", "bytes 1.3.0", + "cookie 0.16.2", + "cookie_store", "encoding_rs", "futures-core", "futures-util", diff --git a/crates/lib/fakeyou_client/Cargo.toml b/crates/lib/fakeyou_client/Cargo.toml index b3af6556d..9f79f6819 100644 --- a/crates/lib/fakeyou_client/Cargo.toml +++ b/crates/lib/fakeyou_client/Cargo.toml @@ -31,7 +31,7 @@ serde_json = "1.0.64" toml = "0.5.8" # HTTP -reqwest = { version = "0.11", features = ["json"] } # HTTP Client +reqwest = { version = "0.11", features = ["json", "cookies"] } # HTTP Client [dev-dependencies] # None yet diff --git a/crates/lib/fakeyou_client/src/credentials.rs b/crates/lib/fakeyou_client/src/credentials.rs new file mode 100644 index 000000000..5db4ecef3 --- /dev/null +++ b/crates/lib/fakeyou_client/src/credentials.rs @@ -0,0 +1,45 @@ + +#[derive(Clone)] +pub enum FakeYouCredentials { + ApiToken(ApiTokenCredentials), + SessionCookie(SessionCookieCredentials), + //UserAccount(UserAccountCredentials), +} + +#[derive(Clone)] +pub struct ApiTokenCredentials { + pub (crate) token: String, +} + +#[derive(Clone)] +pub struct SessionCookieCredentials { + pub (crate) cookie_value: String, +} + +//#[derive(Clone)] +//pub (crate) struct UserAccountCredentials { +// pub (crate) username_or_email: String, +// pub (crate) password: String, +//} + +impl FakeYouCredentials { + pub fn from_api_token(token: &str) -> Self { + Self::ApiToken(ApiTokenCredentials { + token: token.to_string(), + }) + } + + /// NB: This is not the full header, just the cookie *value*. + pub fn from_session_cookie_payload(value: &str) -> Self { + Self::SessionCookie(SessionCookieCredentials { + cookie_value: value.to_string(), + }) + } + + //pub fn from_user_details(username_or_email: &str, password: &str) -> Self { + // Self::UserAccount(UserAccountCredentials { + // username_or_email: username_or_email.to_string(), + // password: password.to_string, + // }) + //} +} diff --git a/crates/lib/fakeyou_client/src/fakeyou_api_client.rs b/crates/lib/fakeyou_client/src/fakeyou_api_client.rs index 621256ee8..7344e99fa 100644 --- a/crates/lib/fakeyou_client/src/fakeyou_api_client.rs +++ b/crates/lib/fakeyou_client/src/fakeyou_api_client.rs @@ -1,22 +1,54 @@ +use std::sync::Arc; use crate::api::tts_inference::{CreateTtsInferenceRequest, CreateTtsInferenceResponse, TtsInferenceJobStatus}; use errors::AnyhowResult; -use reqwest::Client; +use reqwest::{Client, ClientBuilder, RequestBuilder, Url}; +use reqwest::cookie::Jar; +use crate::credentials::FakeYouCredentials; const AUTHORIZATION_HEADER: &'static str = "Authorization"; +const SESSION_COOKIE_NAME : &'static str = "session"; /// A client to consume FakeYou's API via API sessions (vs user sessions). pub struct FakeYouApiClient { api_domain: String, - api_token: String, + credentials: FakeYouCredentials, client: Client, } impl FakeYouApiClient { - pub fn make_production_client(api_token: &str) -> Self { + pub fn make_production_client_from_credentials(credentials: FakeYouCredentials) -> AnyhowResult { + let mut client_builder = ClientBuilder::new(); + + match &credentials { + FakeYouCredentials::SessionCookie(credentials ) => { + let cookie = format!( + "{}={}; Domain=.fakeyou.com", + SESSION_COOKIE_NAME, + &credentials.cookie_value + ); + let url = "https://fakeyou.com".parse::()?; + let jar = Jar::default(); + jar.add_cookie_str(&cookie, &url); + client_builder = client_builder + .cookie_store(true) + .cookie_provider(Arc::new(jar)); + } + _ => {}, // NB: Other methods don't need handling. + } + + Ok(Self { + api_domain: "api.fakeyou.com".to_string(), + credentials, + client: client_builder.build()?, + }) + } + + pub fn make_production_client_from_api_token(api_token: &str) -> Self { + let credentials = FakeYouCredentials::from_api_token(api_token); Self { api_domain: "api.fakeyou.com".to_string(), - api_token: api_token.to_string(), + credentials, client: Client::new(), } } @@ -25,9 +57,8 @@ impl FakeYouApiClient { pub async fn create_tts_inference(&self, request: CreateTtsInferenceRequest<'_>) -> AnyhowResult { let url = format!("https://{}/tts/inference", self.api_domain); - let response = self.client - .post(url) - .header(AUTHORIZATION_HEADER, &self.api_token) + let response = self.add_credentials(self.client + .post(url)) .json(&request) .send() .await? @@ -43,9 +74,8 @@ impl FakeYouApiClient { pub async fn get_tts_inference_job_status(&self, inference_job_token: &str) -> AnyhowResult { let url = format!("https://{}/tts/job/{}", self.api_domain, inference_job_token); - let response = self.client - .get(url) - .header(AUTHORIZATION_HEADER, &self.api_token) + let response = self.add_credentials(self.client + .get(url)) .send() .await? .text() @@ -55,4 +85,13 @@ impl FakeYouApiClient { Ok(response) } + + fn add_credentials(&self, request_builder: RequestBuilder) -> RequestBuilder { + match &self.credentials { + FakeYouCredentials::ApiToken(api_token) => { + request_builder.header(AUTHORIZATION_HEADER, &api_token.token) + } + _ => request_builder, // NB: Other auth types already handled. + } + } } diff --git a/crates/lib/fakeyou_client/src/lib.rs b/crates/lib/fakeyou_client/src/lib.rs index 3479a2bc1..8fc8a5aee 100644 --- a/crates/lib/fakeyou_client/src/lib.rs +++ b/crates/lib/fakeyou_client/src/lib.rs @@ -20,6 +20,7 @@ #[macro_use] extern crate serde_derive; pub mod api; +pub mod credentials; pub mod fakeyou_api_client; pub mod get_audio_url; diff --git a/crates/programs/aichatbot-sidecar/src/main.rs b/crates/programs/aichatbot-sidecar/src/main.rs index 75bc85e05..036ee51f5 100644 --- a/crates/programs/aichatbot-sidecar/src/main.rs +++ b/crates/programs/aichatbot-sidecar/src/main.rs @@ -35,6 +35,7 @@ use std::sync::Arc; use std::thread; use std::time::Duration; use tokio::runtime::{Builder, Runtime}; +use fakeyou_client::credentials::FakeYouCredentials; use fakeyou_client::fakeyou_api_client::FakeYouApiClient; use web_scrapers::sites::cnn::cnn_article_scraper::cnn_article_scraper; use web_scrapers::sites::techcrunch::techcrunch_article_scraper::techcrunch_article_scraper; @@ -96,8 +97,11 @@ pub async fn main() -> AnyhowResult<()> { let openai_client = Arc::new(openai_client); - let fakeyou_client = Arc::new(FakeYouApiClient::make_production_client( - &startup_args.fakeyou_api_token)); + let fakeyou_credentials = FakeYouCredentials::from_session_cookie_payload( + &startup_args.fakeyou_session_cookie_payload); + + let fakeyou_client = + Arc::new(FakeYouApiClient::make_production_client_from_credentials(fakeyou_credentials)?); let save_directory = SaveDirectory::new(&startup_args.save_directory); diff --git a/crates/programs/aichatbot-sidecar/src/startup_args.rs b/crates/programs/aichatbot-sidecar/src/startup_args.rs index 606a44223..8ad251313 100644 --- a/crates/programs/aichatbot-sidecar/src/startup_args.rs +++ b/crates/programs/aichatbot-sidecar/src/startup_args.rs @@ -13,6 +13,7 @@ pub struct StartupArgs { pub openai_secret_key: String, pub fakeyou_api_token: String, + pub fakeyou_session_cookie_payload: String, } /// Read in environment and CLI args and output the consolidated startup state @@ -31,12 +32,15 @@ pub fn get_startup_args() -> AnyhowResult { let fakeyou_api_token = easyenv::get_env_string_required("FAKEYOU_API_TOKEN")?; + let fakeyou_session_cookie_payload = easyenv::get_env_string_required("FAKEYOU_SESSION_COOKIE_PAYLOAD")?; + let save_directory = get_save_directory(&matches)?; Ok(StartupArgs { save_directory, openai_secret_key, fakeyou_api_token, + fakeyou_session_cookie_payload, }) }