refractored code

This commit is contained in:
Waradu 2024-10-20 17:21:39 +02:00
parent 11456948d5
commit 2d635f5807
No known key found for this signature in database
GPG key ID: F85AAC8BA8B8DAAD
4 changed files with 116 additions and 85 deletions

2
Cargo.lock generated
View file

@ -1084,7 +1084,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]] [[package]]
name = "streamshare" name = "streamshare"
version = "3.0.0" version = "4.0.0"
dependencies = [ dependencies = [
"futures", "futures",
"reqwest", "reqwest",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "streamshare" name = "streamshare"
version = "3.0.0" version = "4.0.0"
edition = "2021" edition = "2021"
description = "Upload to streamshare library" description = "Upload to streamshare library"
license = "MIT" license = "MIT"

View file

@ -7,6 +7,8 @@ Upload files to [streamshare](https://streamshare.wireway.ch)
Upload: Upload:
```rust ```rust
let client = StreamShare::default();
let callback = |uploaded_bytes, total_bytes| { let callback = |uploaded_bytes, total_bytes| {
println!( println!(
"Uploaded {}b of {}b", "Uploaded {}b of {}b",
@ -15,7 +17,7 @@ let callback = |uploaded_bytes, total_bytes| {
); );
} }
match upload(&file_path, callback).await { match client.upload(&file_path, callback).await {
Ok((file_identifier, _deletion_token)) => { Ok((file_identifier, _deletion_token)) => {
let download_url = format!( let download_url = format!(
"https://streamshare.wireway.ch/download/{}", "https://streamshare.wireway.ch/download/{}",
@ -32,7 +34,9 @@ match upload(&file_path, callback).await {
Delete: Delete:
```rust ```rust
match streamshare::delete(file_identifier, deletion_token).await { let client = StreamShare::default();
match client.delete(file_identifier, deletion_token).await {
Ok(_) => println!("File deleted successfully"), Ok(_) => println!("File deleted successfully"),
Err(e) => eprintln!("Error deleting file: {}", e), Err(e) => eprintln!("Error deleting file: {}", e),
} }

View file

@ -17,97 +17,124 @@ struct CreateResponse {
deletion_token: String, deletion_token: String,
} }
pub async fn upload<F>(file_path: &str, mut callback: F) -> Result<(String, String), Box<dyn std::error::Error>> pub struct StreamShare {
where server_url: String,
F: FnMut(u64, u64) chunk_size: usize,
{ client: Client,
let path = Path::new(file_path); }
let metadata = fs::metadata(path).await?;
if !metadata.is_file() { impl StreamShare {
return Err("Selected item is not a file".into()); pub fn new(server_url: String, chunk_size: usize) -> Self {
Self {
server_url: server_url,
chunk_size: chunk_size,
client: Client::new(),
}
} }
let file_size = metadata.len(); pub async fn upload<F>(
let file_name = path &self,
.file_name() file_path: &str,
.and_then(|s| s.to_str()) mut callback: F,
.unwrap_or("unknown"); ) -> Result<(String, String), Box<dyn std::error::Error>>
where
let client = Client::new(); F: FnMut(u64, u64),
let create_url = "https://streamshare.wireway.ch/api/create"; {
let path = Path::new(file_path);
let res = client let metadata = fs::metadata(path).await?;
.post(create_url) if !metadata.is_file() {
.json(&serde_json::json!({ "name": file_name })) return Err(format!("Selected item is not a file: {}", file_path).into());
.send()
.await?;
if !res.status().is_success() {
return Err(format!("Failed to create upload: {}", res.status()).into());
}
let create_response: CreateResponse = res.json().await?;
let ws_url = format!(
"wss://streamshare.wireway.ch/api/upload/{}",
create_response.file_identifier
);
let (mut ws_stream, _) = connect_async(ws_url).await?;
let mut file = File::open(path).await?;
const CHUNK_SIZE: usize = 1024 * 1024;
let mut buffer = vec![0u8; CHUNK_SIZE];
let mut uploaded: u64 = 0;
loop {
let n = file.read(&mut buffer).await?;
if n == 0 {
break;
} }
let chunk = &buffer[..n]; let file_size = metadata.len();
ws_stream.send(Message::Binary(chunk.to_vec())).await?; let file_name = path
uploaded += n as u64; .file_name()
.and_then(|s| s.to_str())
.unwrap_or("unknown");
callback(uploaded, file_size); let create_url = format!("https://{}/api/create", self.server_url);
match ws_stream.next().await { let res = self
Some(Ok(Message::Text(text))) if text == "ACK" => (), .client
Some(Ok(msg)) => { .post(&create_url)
return Err(format!("Unexpected message: {:?}", msg).into()); .json(&serde_json::json!({ "name": file_name }))
.send()
.await?;
if !res.status().is_success() {
return Err(format!("Failed to create upload: {}", res.status()).into());
}
let create_response: CreateResponse = res.json().await?;
let ws_url = format!(
"wss://{}/api/upload/{}",
self.server_url, create_response.file_identifier
);
let (mut ws_stream, _) = connect_async(ws_url).await?;
let mut file = File::open(path).await?;
let mut buffer = vec![0u8; self.chunk_size];
let mut uploaded: u64 = 0;
loop {
let n = file.read(&mut buffer).await?;
if n == 0 {
break;
} }
Some(Err(e)) => return Err(format!("WebSocket error: {}", e).into()),
None => return Err("WebSocket closed unexpectedly".into()), let chunk = &buffer[..n];
ws_stream.send(Message::Binary(chunk.to_vec())).await?;
uploaded += n as u64;
callback(uploaded, file_size);
match ws_stream.next().await {
Some(Ok(Message::Text(text))) if text == "ACK" => (),
Some(Ok(msg)) => {
return Err(format!("Unexpected message: {:?}", msg).into());
}
Some(Err(e)) => return Err(format!("WebSocket error: {}", e).into()),
None => return Err("WebSocket closed unexpectedly".into()),
}
}
ws_stream
.close(Some(tungstenite::protocol::CloseFrame {
code: tungstenite::protocol::frame::coding::CloseCode::Normal,
reason: "FILE_UPLOAD_DONE".into(),
}))
.await?;
Ok((
create_response.file_identifier,
create_response.deletion_token,
))
}
pub async fn delete(
&self,
file_identifier: &str,
deletion_token: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let delete_url = format!(
"https://{}/api/delete/{}/{}",
self.server_url, file_identifier, deletion_token
);
let res = self.client.delete(&delete_url).send().await?;
if res.status().is_success() {
Ok(())
} else {
Err(format!("Failed to delete file: {}", res.status()).into())
} }
} }
ws_stream
.close(Some(tungstenite::protocol::CloseFrame {
code: tungstenite::protocol::frame::coding::CloseCode::Normal,
reason: "FILE_UPLOAD_DONE".into(),
}))
.await?;
Ok((
create_response.file_identifier,
create_response.deletion_token,
))
} }
pub async fn delete( impl Default for StreamShare {
file_identifier: &str, fn default() -> Self {
deletion_token: &str, Self {
) -> Result<(), Box<dyn std::error::Error>> { server_url: "streamshare.wireway.ch".to_string(),
let client = Client::new(); chunk_size: 1024 * 1024,
let delete_url = format!( client: Client::new(),
"https://streamshare.wireway.ch/api/delete/{}/{}", }
file_identifier, deletion_token
);
let res = client.delete(&delete_url).send().await?;
if res.status().is_success() {
Ok(())
} else {
Err(format!("Failed to delete file: {}", res.status()).into())
} }
} }