This commit is contained in:
Brandon Thomas committed 2025-10-29 02:04:45 -04:00
1 parent 829944068d
commit 32d7cfb620
17 files changed
+148 -44

No files matched your search

@@ -1,4 +1,5 @@
/// Type for File IDs.
/// File IDs are UUIds.
#[derive(Clone, Debug)]
pub struct FileId(pub String);
@@ -0,0 +1,18 @@
use std::path::Path;
/// Descriptor of a file to be uploaded
/// Includes necessary metadata
pub enum FileUploadSpec<P: AsRef<Path>> {
/// Path to the file
Path(P),
/// Bytes of the file
Bytes {
/// Must be owned.
bytes: Vec<u8>,
/// Must be owned.
filename: String,
/// Mime type
mimetype: String,
}
}
@@ -1,2 +1,3 @@
pub mod file_id;
pub mod file_upload_spec;
pub mod user_id;
+2 -2
View File
@@ -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;
@@ -1 +1,2 @@
pub mod request_client_secrets;
pub mod request_client_secrets;
mod upload_image_and_generate_video;
@@ -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<Path>> {
//pub file_id: &'a FileId,
pub user_id: &'a UserId,
// NB: Must be owned.
pub file: FileUploadSpec<P>,
pub cookies: &'a str,
pub individual_request_timeout: Option<Duration>,
}
pub struct ImageUploadResult {
}
pub async fn upload_image_and_generate_video<P: AsRef<Path>>(args: UploadImageAndGenerateVideo<'_, P>) -> Result<ImageUploadResult, GrokError> {
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(())
}
}
@@ -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()?;
@@ -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;
pub mod create_media_post;
pub mod index_page;
pub mod upload_file;
pub mod video_gen_chat_conversation;
@@ -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<Path>> {
pub file: FileSpec<'a, P>,
pub struct GrokUploadFile<P: AsRef<Path>> {
pub file: FileUploadSpec<P>,
pub cookie: String,
pub request_timeout: Option<Duration>,
}
pub enum FileSpec<'a, P: AsRef<Path>> {
/// 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<String>,
pub file_id: Option<FileId>,
pub file_uri: Option<String>,
}
impl <'a, P> GrokUploadFile<'a, P> where P: AsRef<Path> {
impl <P> GrokUploadFile<P> where P: AsRef<Path> {
pub async fn upload(&self) -> Result<GrokUploadFileResponse, GrokError> {
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<Path> {
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,
};
@@ -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;
@@ -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]
@@ -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]