use reqwest::blocking::{Client, multipart};
use reqwest::header::AUTHORIZATION;
use serde::Deserialize;
use std::env;
use std::fs::File;
use std::path::Path;
const RIVALZ_API_URL: &str = "https://be.rivalz.ai/api-v1";
#[derive(Deserialize)]
struct UploadResponse {
data: UploadData,
}
#[derive(Deserialize)]
struct UploadData {
uploadHash: String,
}
#[derive(Deserialize)]
struct DownloadResponse {
data: DownloadData,
}
#[derive(Deserialize)]
struct DownloadData {
file: FileData,
name: String,
}
#[derive(Deserialize)]
struct FileData {
data: String,
}
pub struct RivalzClient {
secret: String,
client: Client,
}
impl RivalzClient {
pub fn new(secret: Option<String>) -> Self {
let secret = secret.unwrap_or_else(|| env::var("SECRET_TOKEN").unwrap());
let client = Client::new();
RivalzClient { secret, client }
}
pub fn upload_file(&self, file_path: &str) -> Result<String, Box<dyn std::error::Error>> {
if !Path::new(file_path).exists() {
return Err(format!("File not found: {}", file_path).into());
}
let file = File::open(file_path)?;
let file_part = multipart::Part::reader(file).file_name(file_path.to_string());
let form = multipart::Form::new().part("file", file_part);
let res = self.client.post(format!("{}/ipfs/upload-file", RIVALZ_API_URL))
.header(AUTHORIZATION, format!("Bearer {}", self.secret))
.multipart(form)
.send();
let res = match res {
Ok(response) => response,
Err(e) => return Err(format!("Network error: {}", e).into()),
};
if res.status().is_client_error() || res.status().is_server_error() {
return Err(format!("HTTP error: {}", res.status()).into());
}
let upload_response: Result<UploadResponse, _> = res.json();
let upload_response = match upload_response {
Ok(response) => response,
Err(e) => return Err(format!("Failed to parse JSON response: {}", e).into()),
};
match self.get_ipfs_hash(&upload_response.data.uploadHash) {
Ok(hash) => Ok(hash),
Err(e) => Err(format!("Failed to get IPFS hash: {}", e).into()),
}
}
fn get_ipfs_hash(&self, upload_hash: &str) -> Result<String, Box<dyn std::error::Error>> {
loop {
let res = self.client.get(format!("{}/upload-history/{}", RIVALZ_API_URL, upload_hash))
.header(AUTHORIZATION, format!("Bearer {}", self.secret))
.send()?;
let upload_info: UploadData = res.json()?;
if !upload_info.uploadHash.is_empty() {
return Ok(upload_info.uploadHash);
}
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
}