mirror of
https://github.com/Waradu/streamshare.git
synced 2025-04-20 19:34:09 +02:00
init
This commit is contained in:
commit
67788708fd
5 changed files with 1746 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
1622
Cargo.lock
generated
Normal file
1622
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
18
Cargo.toml
Normal file
18
Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "streamshare"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Upload to streamshare library"
|
||||||
|
license = "MIT"
|
||||||
|
homepage = "https://waradu.dev"
|
||||||
|
repository = "https://github.com/Waradu/streamshare"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = ["Waradu"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
reqwest = { version = "0.12.8", features = ["json", "rustls-tls"] }
|
||||||
|
tokio-tungstenite = { version = "0.24.0", features = ["rustls-tls-webpki-roots"] }
|
||||||
|
futures = "0.3"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
20
README.md
Normal file
20
README.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Streamshare
|
||||||
|
|
||||||
|
Upload files to [streamshare](https://streamshare.wireway.ch)
|
||||||
|
|
||||||
|
#### Example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
match upload(&file_path).await {
|
||||||
|
Ok((file_identifier, _deletion_token)) => {
|
||||||
|
let download_url = format!(
|
||||||
|
"https://streamshare.wireway.ch/download/{}",
|
||||||
|
file_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("File uploaded successfully");
|
||||||
|
println!("Download URL: {}", download_url);
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("Error: {}", e),
|
||||||
|
}
|
||||||
|
```
|
85
src/lib.rs
Normal file
85
src/lib.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use std::path::Path;
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tokio::fs::File;
|
||||||
|
use tokio_tungstenite::{connect_async, tungstenite::{self, Message}};
|
||||||
|
use futures::{SinkExt, StreamExt};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct CreateResponse {
|
||||||
|
file_identifier: String,
|
||||||
|
deletion_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn upload(file_path: &str) -> Result<(String, String), Box<dyn std::error::Error>> {
|
||||||
|
let path = Path::new(file_path);
|
||||||
|
let metadata = fs::metadata(path).await?;
|
||||||
|
if !metadata.is_file() {
|
||||||
|
return Err("Selected item is not a file".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_name = path
|
||||||
|
.file_name()
|
||||||
|
.and_then(|s| s.to_str())
|
||||||
|
.unwrap_or("unknown");
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
let create_url = "https://streamshare.wireway.ch/api/create";
|
||||||
|
|
||||||
|
let res = client
|
||||||
|
.post(create_url)
|
||||||
|
.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://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 = 64 * 1024;
|
||||||
|
|
||||||
|
let mut buffer = vec![0u8; CHUNK_SIZE];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let n = file.read(&mut buffer).await?;
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let chunk = &buffer[..n];
|
||||||
|
|
||||||
|
ws_stream.send(Message::Binary(chunk.to_vec())).await?;
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue