From 32d7cfb62022249da60703040cfa5420a968d854 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Wed, 29 Oct 2025 02:04:45 -0400 Subject: [PATCH] refactor --- .../crypto_signature/xStatsigIDGenerator.py | 0 .../crypto_signature/xctid.py | 0 .../{metadata => _metadata}/login_flow.txt | 0 .../src/{types => datatypes}/file_id.rs | 1 + .../src/datatypes/file_upload_spec.rs | 18 ++++ .../src/{types => datatypes}/mod.rs | 1 + .../src/{types => datatypes}/user_id.rs | 0 crates/api_clients/grok_client/src/lib.rs | 4 +- .../video_gen_request_flows.md | 0 .../grok_client/src/recipes/mod.rs | 3 +- .../upload_image_and_generate_video.rs | 91 +++++++++++++++++++ .../grok_create_media_post.rs | 8 +- .../grok_client/src/requests/mod.rs | 8 +- .../requests/upload_file/grok_upload_file.rs | 36 +++----- .../grok_video_gen_chat_conversation.rs | 6 +- .../utils/user_and_file_id_to_image_url.rs | 8 +- .../utils/user_and_file_id_to_video_url.rs | 8 +- 17 files changed, 148 insertions(+), 44 deletions(-) rename crates/api_clients/grok_client/src/credentials/{metadata => _metadata}/crypto_signature/xStatsigIDGenerator.py (100%) rename crates/api_clients/grok_client/src/credentials/{metadata => _metadata}/crypto_signature/xctid.py (100%) rename crates/api_clients/grok_client/src/credentials/{metadata => _metadata}/login_flow.txt (100%) rename crates/api_clients/grok_client/src/{types => datatypes}/file_id.rs (76%) create mode 100644 crates/api_clients/grok_client/src/datatypes/file_upload_spec.rs rename crates/api_clients/grok_client/src/{types => datatypes}/mod.rs (56%) rename crates/api_clients/grok_client/src/{types => datatypes}/user_id.rs (100%) rename crates/api_clients/grok_client/src/recipes/{metadata => _metadata}/video_gen_request_flows.md (100%) create mode 100644 crates/api_clients/grok_client/src/recipes/upload_image_and_generate_video.rs diff --git a/crates/api_clients/grok_client/src/credentials/metadata/crypto_signature/xStatsigIDGenerator.py b/crates/api_clients/grok_client/src/credentials/_metadata/crypto_signature/xStatsigIDGenerator.py similarity index 100% rename from crates/api_clients/grok_client/src/credentials/metadata/crypto_signature/xStatsigIDGenerator.py rename to crates/api_clients/grok_client/src/credentials/_metadata/crypto_signature/xStatsigIDGenerator.py diff --git a/crates/api_clients/grok_client/src/credentials/metadata/crypto_signature/xctid.py b/crates/api_clients/grok_client/src/credentials/_metadata/crypto_signature/xctid.py similarity index 100% rename from crates/api_clients/grok_client/src/credentials/metadata/crypto_signature/xctid.py rename to crates/api_clients/grok_client/src/credentials/_metadata/crypto_signature/xctid.py diff --git a/crates/api_clients/grok_client/src/credentials/metadata/login_flow.txt b/crates/api_clients/grok_client/src/credentials/_metadata/login_flow.txt similarity index 100% rename from crates/api_clients/grok_client/src/credentials/metadata/login_flow.txt rename to crates/api_clients/grok_client/src/credentials/_metadata/login_flow.txt diff --git a/crates/api_clients/grok_client/src/types/file_id.rs b/crates/api_clients/grok_client/src/datatypes/file_id.rs similarity index 76% rename from crates/api_clients/grok_client/src/types/file_id.rs rename to crates/api_clients/grok_client/src/datatypes/file_id.rs index da4b803734..9f555bfe15 100644 --- a/crates/api_clients/grok_client/src/types/file_id.rs +++ b/crates/api_clients/grok_client/src/datatypes/file_id.rs @@ -1,4 +1,5 @@ /// Type for File IDs. /// File IDs are UUIds. +#[derive(Clone, Debug)] pub struct FileId(pub String); \ No newline at end of file diff --git a/crates/api_clients/grok_client/src/datatypes/file_upload_spec.rs b/crates/api_clients/grok_client/src/datatypes/file_upload_spec.rs new file mode 100644 index 0000000000..2e2e435645 --- /dev/null +++ b/crates/api_clients/grok_client/src/datatypes/file_upload_spec.rs @@ -0,0 +1,18 @@ +use std::path::Path; + +/// Descriptor of a file to be uploaded +/// Includes necessary metadata +pub enum FileUploadSpec> { + /// Path to the file + Path(P), + + /// Bytes of the file + Bytes { + /// Must be owned. + bytes: Vec, + /// Must be owned. + filename: String, + /// Mime type + mimetype: String, + } +} diff --git a/crates/api_clients/grok_client/src/types/mod.rs b/crates/api_clients/grok_client/src/datatypes/mod.rs similarity index 56% rename from crates/api_clients/grok_client/src/types/mod.rs rename to crates/api_clients/grok_client/src/datatypes/mod.rs index 2b30f9cbd4..00a22af064 100644 --- a/crates/api_clients/grok_client/src/types/mod.rs +++ b/crates/api_clients/grok_client/src/datatypes/mod.rs @@ -1,2 +1,3 @@ pub mod file_id; +pub mod file_upload_spec; pub mod user_id; diff --git a/crates/api_clients/grok_client/src/types/user_id.rs b/crates/api_clients/grok_client/src/datatypes/user_id.rs similarity index 100% rename from crates/api_clients/grok_client/src/types/user_id.rs rename to crates/api_clients/grok_client/src/datatypes/user_id.rs diff --git a/crates/api_clients/grok_client/src/lib.rs b/crates/api_clients/grok_client/src/lib.rs index 4515f8e950..f0d3e6b848 100644 --- a/crates/api_clients/grok_client/src/lib.rs +++ b/crates/api_clients/grok_client/src/lib.rs @@ -8,8 +8,8 @@ pub (crate) mod client; // User lib pub mod credentials; +pub mod datatypes; pub mod error; +pub mod recipes; pub mod requests; -pub mod types; pub mod utils; -mod recipes; diff --git a/crates/api_clients/grok_client/src/recipes/metadata/video_gen_request_flows.md b/crates/api_clients/grok_client/src/recipes/_metadata/video_gen_request_flows.md similarity index 100% rename from crates/api_clients/grok_client/src/recipes/metadata/video_gen_request_flows.md rename to crates/api_clients/grok_client/src/recipes/_metadata/video_gen_request_flows.md diff --git a/crates/api_clients/grok_client/src/recipes/mod.rs b/crates/api_clients/grok_client/src/recipes/mod.rs index 6ec390436b..1d09adac78 100644 --- a/crates/api_clients/grok_client/src/recipes/mod.rs +++ b/crates/api_clients/grok_client/src/recipes/mod.rs @@ -1 +1,2 @@ -pub mod request_client_secrets; \ No newline at end of file +pub mod request_client_secrets; +mod upload_image_and_generate_video; \ No newline at end of file diff --git a/crates/api_clients/grok_client/src/recipes/upload_image_and_generate_video.rs b/crates/api_clients/grok_client/src/recipes/upload_image_and_generate_video.rs new file mode 100644 index 0000000000..de49886365 --- /dev/null +++ b/crates/api_clients/grok_client/src/recipes/upload_image_and_generate_video.rs @@ -0,0 +1,91 @@ +use crate::datatypes::file_id::FileId; +use crate::datatypes::file_upload_spec::FileUploadSpec; +use crate::datatypes::user_id::UserId; +use crate::error::grok_error::GrokError; +use crate::requests::upload_file::grok_upload_file::GrokUploadFile; +use log::info; +use std::path::Path; +use std::time::Duration; +use crate::utils::user_and_file_id_to_image_url::user_and_file_id_to_image_url; + +pub struct UploadImageAndGenerateVideo<'a, P: AsRef> { + //pub file_id: &'a FileId, + pub user_id: &'a UserId, + + // NB: Must be owned. + pub file: FileUploadSpec

, + + pub cookies: &'a str, + + pub individual_request_timeout: Option, +} + +pub struct ImageUploadResult { +} + +pub async fn upload_image_and_generate_video>(args: UploadImageAndGenerateVideo<'_, P>) -> Result { + + info!("Uploading file to Grok..."); + + let request = GrokUploadFile { + //file: FileSpec::Path("/Users/bt/dev/storyteller/storyteller-rust/test_data/image/mochi.jpg"), + file: args.file, + cookie: args.cookies.to_string(), + request_timeout: args.individual_request_timeout, + }; + + let result = request.upload().await?; + + info!("File URI: {:?}", result.file_uri); + info!("File Metadata ID: {:?}", result.file_id); + + let url = user_and_file_id_to_image_url(&args.user_id, &result.file_id.unwrap()); + + info!("Uploaded URI: {:?}", url); + + + info!("Creating media post..."); + + + + Ok(ImageUploadResult { + + }) +} + + +#[cfg(test)] +mod tests { + use log::LevelFilter; + use errors::AnyhowResult; + use crate::datatypes::file_upload_spec::FileUploadSpec; + use crate::datatypes::user_id::UserId; + use crate::recipes::upload_image_and_generate_video::{upload_image_and_generate_video, UploadImageAndGenerateVideo}; + use crate::test_utils::get_test_cookies::get_test_cookies; + use crate::test_utils::setup_test_logging::setup_test_logging; + + #[tokio::test] + #[ignore] // Client side tests only + async fn create_media_post() -> AnyhowResult<()> { + setup_test_logging(LevelFilter::Info); + + let cookies = get_test_cookies()?; + + let user_id = UserId("85980643-ffab-4984-a3de-59a608c47d7f".to_string()); // User + + // Result: GrokUploadFileResponse { file_metadata_id: + // Some("acdee48f-9d6f-4bc6-9d06-fcc97dd4418a"), file_uri: + // Some("users/85980643-ffab-4984-a3de-59a608c47d7f/acdee48f-9d6f-4bc6-9d06-fcc97dd4418a/content") } + + let result = upload_image_and_generate_video(UploadImageAndGenerateVideo { + file: FileUploadSpec::Path("/Users/bt/Pictures/Creatures/Spooky/06.1.jpg"), + cookies: &cookies, + individual_request_timeout: None, + user_id: &user_id, + }).await?; + + assert_eq!(1, 2); + + Ok(()) + } +} diff --git a/crates/api_clients/grok_client/src/requests/create_media_post/grok_create_media_post.rs b/crates/api_clients/grok_client/src/requests/create_media_post/grok_create_media_post.rs index ff33c1c6f4..6379611e23 100644 --- a/crates/api_clients/grok_client/src/requests/create_media_post/grok_create_media_post.rs +++ b/crates/api_clients/grok_client/src/requests/create_media_post/grok_create_media_post.rs @@ -1,11 +1,11 @@ use crate::client::browser_user_agents::FIREFOX_143_MAC_USER_AGENT; +use crate::datatypes::file_id::FileId; +use crate::datatypes::user_id::UserId; use crate::error::grok_client_error::GrokClientError; use crate::error::grok_error::GrokError; use crate::error::grok_generic_api_error::GrokGenericApiError; use crate::requests::create_media_post::request::CreateMediaPostWireRequest; -use crate::requests::upload_file::grok_upload_file::{FileSpec, GrokUploadFile, GrokUploadFileResponse}; -use crate::types::file_id::FileId; -use crate::types::user_id::UserId; +use crate::requests::upload_file::grok_upload_file::{GrokUploadFile, GrokUploadFileResponse}; use crate::utils::user_and_file_id_to_image_url::user_and_file_id_to_image_url; use log::{error, info}; use std::time::Duration; @@ -136,7 +136,7 @@ mod tests { use errors::AnyhowResult; #[tokio::test] - #[ignore] + #[ignore] // Client side tests only async fn create_media_post() -> AnyhowResult<()> { //setup_test_logging(LevelFilter::Trace); let cookies = get_test_cookies()?; diff --git a/crates/api_clients/grok_client/src/requests/mod.rs b/crates/api_clients/grok_client/src/requests/mod.rs index fb4d8a8804..cec7729c08 100644 --- a/crates/api_clients/grok_client/src/requests/mod.rs +++ b/crates/api_clients/grok_client/src/requests/mod.rs @@ -1,7 +1,7 @@ -mod create_media_post; mod get_asset; mod listen_websocket; mod other; -mod upload_file; -mod video_gen_chat_conversation; -pub mod index_page; \ No newline at end of file +pub mod create_media_post; +pub mod index_page; +pub mod upload_file; +pub mod video_gen_chat_conversation; \ No newline at end of file diff --git a/crates/api_clients/grok_client/src/requests/upload_file/grok_upload_file.rs b/crates/api_clients/grok_client/src/requests/upload_file/grok_upload_file.rs index 31c669c141..1c6ca6f6cb 100644 --- a/crates/api_clients/grok_client/src/requests/upload_file/grok_upload_file.rs +++ b/crates/api_clients/grok_client/src/requests/upload_file/grok_upload_file.rs @@ -1,4 +1,6 @@ use crate::client::browser_user_agents::FIREFOX_143_MAC_USER_AGENT; +use crate::datatypes::file_id::FileId; +use crate::datatypes::file_upload_spec::FileUploadSpec; use crate::error::grok_client_error::GrokClientError; use crate::error::grok_error::GrokError; use crate::error::grok_generic_api_error::GrokGenericApiError; @@ -23,42 +25,28 @@ const UPLOAD_FILE_URL : &str = "https://grok.com/rest/app-chat/upload-file"; const INITIAL_BUFFER_SIZE : usize = 1024*1024; /// Request builder -pub struct GrokUploadFile<'a, P: AsRef> { - pub file: FileSpec<'a, P>, +pub struct GrokUploadFile> { + pub file: FileUploadSpec

, pub cookie: String, pub request_timeout: Option, } -pub enum FileSpec<'a, P: AsRef> { - /// Path to the file - Path(P), - - /// Bytes of the file - Bytes { - /// Must be owned. - bytes: &'a [u8], - /// Must be owned. - filename: String, - /// Mime type - mimetype: String, - } -} /// Response type #[derive(Clone, Debug)] pub struct GrokUploadFileResponse { - pub file_metadata_id: Option, + pub file_id: Option, pub file_uri: Option, } -impl <'a, P> GrokUploadFile<'a, P> where P: AsRef { +impl

GrokUploadFile

where P: AsRef { pub async fn upload(&self) -> Result { match &self.file { - FileSpec::Path(path) => { + FileUploadSpec::Path(path) => { self.upload_from_file(path.as_ref()).await } - FileSpec::Bytes { bytes, filename, mimetype } => { + FileUploadSpec::Bytes { bytes, filename, mimetype } => { unimplemented!("todo: implement bytes upload") } } @@ -193,8 +181,11 @@ impl <'a, P> GrokUploadFile<'a, P> where P: AsRef { let response : GrokApiUploadFileResponse = serde_json::from_str(response_body) .map_err(|err| GrokGenericApiError::SerdeResponseParseErrorWithBody(err, response_body.to_string()))?; + let file_id = response.file_metadata_id + .map(|id| FileId(id)); + Ok(GrokUploadFileResponse { - file_metadata_id: response.file_metadata_id, + file_id: file_id, file_uri: response.file_uri, }) } @@ -213,7 +204,8 @@ mod tests { //setup_test_logging(LevelFilter::Trace); let cookies = get_test_cookies()?; let request = GrokUploadFile { - file: FileSpec::Path("/Users/bt/dev/storyteller/storyteller-rust/test_data/image/mochi.jpg"), + //file: FileUploadSpec::Path("/Users/bt/dev/storyteller/storyteller-rust/test_data/image/mochi.jpg"), + file: FileUploadSpec::Path("/Users/bt/Pictures/Creatures/Spooky/06.1.jpg"), cookie: cookies.to_string(), request_timeout: None, }; diff --git a/crates/api_clients/grok_client/src/requests/video_gen_chat_conversation/grok_video_gen_chat_conversation.rs b/crates/api_clients/grok_client/src/requests/video_gen_chat_conversation/grok_video_gen_chat_conversation.rs index 429e6fe440..d1fdbf6a9d 100644 --- a/crates/api_clients/grok_client/src/requests/video_gen_chat_conversation/grok_video_gen_chat_conversation.rs +++ b/crates/api_clients/grok_client/src/requests/video_gen_chat_conversation/grok_video_gen_chat_conversation.rs @@ -1,4 +1,6 @@ use crate::client::browser_user_agents::FIREFOX_143_MAC_USER_AGENT; +use crate::datatypes::file_id::FileId; +use crate::datatypes::user_id::UserId; use crate::error::grok_client_error::GrokClientError; use crate::error::grok_error::GrokError; use crate::error::grok_generic_api_error::GrokGenericApiError; @@ -8,10 +10,8 @@ use crate::requests::index_page::pieces::svg_path_data::SvgPathData; use crate::requests::index_page::pieces::verification_token::VerificationToken; use crate::requests::index_page::pieces::xsid_numbers::XsidNumbers; use crate::requests::index_page::signature::generate_xsid::{generate_xsid, GenerateXsidArgs}; -use crate::requests::upload_file::grok_upload_file::{FileSpec, GrokUploadFile, GrokUploadFileResponse}; +use crate::requests::upload_file::grok_upload_file::{GrokUploadFile, GrokUploadFileResponse}; use crate::requests::video_gen_chat_conversation::request::{CreateChatConversationWireRequest, ToolOverrides}; -use crate::types::file_id::FileId; -use crate::types::user_id::UserId; use crate::utils::user_and_file_id_to_image_url::user_and_file_id_to_image_url; use log::{error, info}; use std::time::Duration; diff --git a/crates/api_clients/grok_client/src/utils/user_and_file_id_to_image_url.rs b/crates/api_clients/grok_client/src/utils/user_and_file_id_to_image_url.rs index bb8f6e9d4f..7e74f8f107 100644 --- a/crates/api_clients/grok_client/src/utils/user_and_file_id_to_image_url.rs +++ b/crates/api_clients/grok_client/src/utils/user_and_file_id_to_image_url.rs @@ -1,5 +1,5 @@ -use crate::types::file_id::FileId; -use crate::types::user_id::UserId; +use crate::datatypes::file_id::FileId; +use crate::datatypes::user_id::UserId; /// Return media URLs to images given the user and file IDs. /// These are non-public and will return 403s unless you're logged in. @@ -11,8 +11,8 @@ pub fn user_and_file_id_to_image_url(user: &UserId, file: &FileId) -> String { #[cfg(test)] mod tests { - use crate::types::file_id::FileId; - use crate::types::user_id::UserId; + use crate::datatypes::file_id::FileId; + use crate::datatypes::user_id::UserId; use crate::utils::user_and_file_id_to_image_url::user_and_file_id_to_image_url; #[test] diff --git a/crates/api_clients/grok_client/src/utils/user_and_file_id_to_video_url.rs b/crates/api_clients/grok_client/src/utils/user_and_file_id_to_video_url.rs index c457cdeebf..0095ae776b 100644 --- a/crates/api_clients/grok_client/src/utils/user_and_file_id_to_video_url.rs +++ b/crates/api_clients/grok_client/src/utils/user_and_file_id_to_video_url.rs @@ -1,5 +1,5 @@ -use crate::types::file_id::FileId; -use crate::types::user_id::UserId; +use crate::datatypes::file_id::FileId; +use crate::datatypes::user_id::UserId; /// Return media URLs to images given the user and file IDs. /// These are non-public and will return 403s unless you're logged in. @@ -15,8 +15,8 @@ pub fn user_and_file_id_to_video_url(user: &UserId, file: &FileId, cache_bust: b #[cfg(test)] mod tests { - use crate::types::file_id::FileId; - use crate::types::user_id::UserId; + use crate::datatypes::file_id::FileId; + use crate::datatypes::user_id::UserId; use crate::utils::user_and_file_id_to_video_url::user_and_file_id_to_video_url; #[test]