From 75be0c17a232e8de2fb1085f60ab51bdab034862 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 19 May 2025 11:49:30 -0400 Subject: [PATCH] wip creds --- .../runwayml_client/src/creds/credentials.rs | 16 +++++ .../src/creds/jwt_bearer_token.rs | 4 +- .../runwayml_client/src/creds/mod.rs | 3 +- .../runwayml_client/src/error/api_error.rs | 16 +++-- .../runwayml_client/src/error/client_error.rs | 6 +- .../api_clients/runwayml_client/src/lib.rs | 3 +- .../src/requests/gen4_image_to_video.rs | 72 +++++++++++++++++++ .../runwayml_client/src/requests/mod.rs | 1 + 8 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 crates/lib/api_clients/runwayml_client/src/creds/credentials.rs create mode 100644 crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs create mode 100644 crates/lib/api_clients/runwayml_client/src/requests/mod.rs diff --git a/crates/lib/api_clients/runwayml_client/src/creds/credentials.rs b/crates/lib/api_clients/runwayml_client/src/creds/credentials.rs new file mode 100644 index 0000000000..5f821b51be --- /dev/null +++ b/crates/lib/api_clients/runwayml_client/src/creds/credentials.rs @@ -0,0 +1,16 @@ +use crate::creds::jwt_bearer_token::JwtBearerToken; +use crate::error::api_error::ApiError; + +#[derive(Clone)] +pub struct Credentials { + pub jwt_bearer_token: Option, +} + +impl Credentials { + pub fn from_jwt_str(jwt_str: &str) -> Result { + let jwt_bearer_token = JwtBearerToken::new(jwt_str.to_string())?; + Ok(Self { + jwt_bearer_token: Some(jwt_bearer_token), + }) + } +} diff --git a/crates/lib/api_clients/runwayml_client/src/creds/jwt_bearer_token.rs b/crates/lib/api_clients/runwayml_client/src/creds/jwt_bearer_token.rs index b5cebe514c..dfbe49a2a1 100644 --- a/crates/lib/api_clients/runwayml_client/src/creds/jwt_bearer_token.rs +++ b/crates/lib/api_clients/runwayml_client/src/creds/jwt_bearer_token.rs @@ -1,5 +1,5 @@ use crate::creds::jwt_claims::JwtClaims; -use errors::AnyhowResult; +use crate::error::api_error::ApiError; use jwt_light::parse_jwt_claims_trait::ParseJwtClaims; /// Sora bearer tokens are JWT tokens that can be minted with a valid cookie/session. @@ -10,7 +10,7 @@ pub struct JwtBearerToken { } impl JwtBearerToken { - pub fn new(raw_jwt: String) -> AnyhowResult { + pub fn new(raw_jwt: String) -> Result { let jwt_claims = JwtClaims::parse_claims(&raw_jwt)?; Ok(Self { raw_jwt, diff --git a/crates/lib/api_clients/runwayml_client/src/creds/mod.rs b/crates/lib/api_clients/runwayml_client/src/creds/mod.rs index 808422952d..a912e0bc59 100644 --- a/crates/lib/api_clients/runwayml_client/src/creds/mod.rs +++ b/crates/lib/api_clients/runwayml_client/src/creds/mod.rs @@ -1,2 +1,3 @@ +pub mod credentials; pub mod jwt_bearer_token; -mod jwt_claims; \ No newline at end of file +pub mod jwt_claims; \ No newline at end of file diff --git a/crates/lib/api_clients/runwayml_client/src/error/api_error.rs b/crates/lib/api_clients/runwayml_client/src/error/api_error.rs index 9ada0157c5..4c37d04c8e 100644 --- a/crates/lib/api_clients/runwayml_client/src/error/api_error.rs +++ b/crates/lib/api_clients/runwayml_client/src/error/api_error.rs @@ -1,17 +1,25 @@ +use jwt_light::error::JwtError; use std::error::Error; use std::fmt::{Display, Formatter}; #[derive(Debug)] pub enum ApiError { - - /// Inability to parse local JWT claims - LocalJwtClaimsParseError(String), + /// Inability to parse JWT. + JwtError(JwtError), } impl Display for ApiError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - todo!() + match self { + ApiError::JwtError(err) => write!(f, "JwtError: {}", err), + } } } impl Error for ApiError {} + +impl From for ApiError { + fn from(err: JwtError) -> Self { + ApiError::JwtError(err) + } +} diff --git a/crates/lib/api_clients/runwayml_client/src/error/client_error.rs b/crates/lib/api_clients/runwayml_client/src/error/client_error.rs index d54209e6f2..37e905aeb7 100644 --- a/crates/lib/api_clients/runwayml_client/src/error/client_error.rs +++ b/crates/lib/api_clients/runwayml_client/src/error/client_error.rs @@ -3,11 +3,15 @@ use std::fmt::{Display, Formatter}; #[derive(Debug)] pub enum ClientError { + /// No JWT bearer token in the credentials + NoJwtBearerToken } impl Display for ClientError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - todo!() + match self { + ClientError::NoJwtBearerToken => write!(f, "No JWT bearer token in the credentials"), + } } } diff --git a/crates/lib/api_clients/runwayml_client/src/lib.rs b/crates/lib/api_clients/runwayml_client/src/lib.rs index 6df1c9b2ad..b1b15c6e87 100644 --- a/crates/lib/api_clients/runwayml_client/src/lib.rs +++ b/crates/lib/api_clients/runwayml_client/src/lib.rs @@ -1,4 +1,5 @@ /// TODO DOCS pub mod creds; -pub mod error; \ No newline at end of file +pub mod error; +pub mod requests; \ No newline at end of file diff --git a/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs b/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs new file mode 100644 index 0000000000..38d33f2176 --- /dev/null +++ b/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs @@ -0,0 +1,72 @@ +use log::{debug, error}; +use reqwest::Client; +use crate::creds::credentials::Credentials; +use crate::error::client_error::ClientError; +use crate::error::runwayml_error::RunwayMlError; + +const GENERATE_URL: &str = "https://api.runwayml.com/v1/tasks"; + +pub async fn gen4_image_to_video( + credentials: &Credentials, +) -> Result { + + let jwt = match credentials.jwt_bearer_token.as_ref() { + Some(token) => token, + None => { + error!("Failed to generate bearer token. No JWT bearer token found."); + return Err(ClientError::NoJwtBearerToken.into()); + } + }; + + let client = Client::builder() + .gzip(true) + .build()?; + + let response = client.get(GENERATE_URL) + .header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:137.0) Gecko/20100101 Firefox/137.0") + .header("Accept", "application/json") + .header("Accept-Encoding", "gzip, deflate, br") + .header("Accept-Language", "en-US,en;q=0.5") + .header("Content-Type", "application/json") + .header("Authorization", jwt.to_authorization_header_value()) + .send() + .await?; + + if !response.status().is_success() { + error!("Failed to generate bearer token: {}", response.status()); + let error = classify_general_http_error(response).await; + return Err(error); + } + + debug!("Bearer token generation response was 200."); + + let response_body = response.text().await?; + + debug!("Auth Response: {}", response_body); + + if &response_body == "null" { + error!("Failed to generate bearer token. Response was `null`."); + return Err(SoraError::FailedToGenerateBearer) + } + + let auth_response: SoraAuthResponse = serde_json::from_str(&response_body)?; + + Ok(auth_response.access_token) + + + + Ok(()) +} + +#[cfg(test)] +mod tests { + use errors::AnyhowResult; + + #[tokio::test] + #[ignore] + async fn send_test_request() -> AnyhowResult<()> { + + + Ok(()) + } +} \ No newline at end of file diff --git a/crates/lib/api_clients/runwayml_client/src/requests/mod.rs b/crates/lib/api_clients/runwayml_client/src/requests/mod.rs new file mode 100644 index 0000000000..c45b7b8da0 --- /dev/null +++ b/crates/lib/api_clients/runwayml_client/src/requests/mod.rs @@ -0,0 +1 @@ +pub mod gen4_image_to_video; \ No newline at end of file