Compare commits
No commits in common. "9436e2afe9d0e48660826c30a4d658e1a8db567a" and "4ee17e2188c1d4e45ea9908ce772508aea860881" have entirely different histories.
9436e2afe9
...
4ee17e2188
7 changed files with 1 additions and 1222 deletions
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
|
|
@ -20,9 +20,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"args": [],
|
"args": [],
|
||||||
"env": {
|
|
||||||
"RUST_LOG": "shrupl=debug",
|
|
||||||
},
|
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|
|
||||||
1014
Cargo.lock
generated
1014
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -4,7 +4,3 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.11.8"
|
|
||||||
log = "0.4.27"
|
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
|
||||||
ureq = { version = "3.0.11", features = ["json"] }
|
|
||||||
|
|
|
||||||
37
doc/notes.md
37
doc/notes.md
|
|
@ -1,37 +0,0 @@
|
||||||
outline of sharry uploading
|
|
||||||
|
|
||||||
1. POST to "new" route
|
|
||||||
- uri: https://sharry.yavook.de/api/v2/alias/upload/new
|
|
||||||
- hdr: `Sharry-Alias: $alias_id`
|
|
||||||
- res.status == 200
|
|
||||||
- res_json.success == true
|
|
||||||
- res_json.message == "Share created."
|
|
||||||
- $share_id := res_json.id
|
|
||||||
|
|
||||||
1. POST to "tus" route
|
|
||||||
- uri: https://sharry.yavook.de/api/v2/alias/upload/$share_id/files/tus
|
|
||||||
- hdr: `Sharry-Alias: $alias_id`
|
|
||||||
- hdr: `Sharry-File-Length: $file_bytes`
|
|
||||||
- hdr: `Sharry-File-Name: $file_name`
|
|
||||||
- hdr: `Sharry-File-Type: $file_mimetype`
|
|
||||||
- hdr: `Tus-Resumable: 1.0.0`
|
|
||||||
- hdr: `Upload-Length: $file_bytes`
|
|
||||||
- res.status == 201
|
|
||||||
- $patch_uri := res_hdr.Location
|
|
||||||
|
|
||||||
1. (multi) PATCH to "$patch_uri"
|
|
||||||
- hdr: `Sharry-Alias`, `Sharry-File-Length`, `Sharry-File-Name`, `Sharry-File-Type`, `Tus-Resumable`
|
|
||||||
- hdr: `Upload-Offset: 10485760 * (n-1)` for nth chunk
|
|
||||||
- body: up to 10 MiB of binary data
|
|
||||||
- res.status == 204
|
|
||||||
- better use res_hdr.Upload-Offset
|
|
||||||
|
|
||||||
1. (opt) POST to "notify" route
|
|
||||||
- uri: https://sharry.yavook.de/api/v2/alias/mail/notify/$share_id
|
|
||||||
- hdr: `Sharry-Alias`
|
|
||||||
- res.status == 200
|
|
||||||
- res_json.success, res_json.message
|
|
||||||
|
|
||||||
hints
|
|
||||||
|
|
||||||
- https://stackoverflow.com/questions/59586787/rust-how-to-do-http-put-of-large-files
|
|
||||||
29
src/main.rs
29
src/main.rs
|
|
@ -1,30 +1,3 @@
|
||||||
mod sharry;
|
|
||||||
|
|
||||||
use log::info;
|
|
||||||
use sharry::{
|
|
||||||
Alias,
|
|
||||||
api::{NewShareRequest, URI},
|
|
||||||
};
|
|
||||||
use std::time::Duration;
|
|
||||||
use ureq::Agent;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
println!("Hello, world!");
|
||||||
|
|
||||||
let agent: Agent = Agent::config_builder()
|
|
||||||
.timeout_global(Some(Duration::from_secs(5)))
|
|
||||||
.build()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let alias = Alias::new(
|
|
||||||
URI::new("sharry.yavook.de"),
|
|
||||||
"G7RYoWME1W7-pcgipemJcr8-39FcMd92gBu-RgufeHc51z6",
|
|
||||||
);
|
|
||||||
|
|
||||||
let share = alias.create_share(&agent, &NewShareRequest::new(Some("foo"), "", 10));
|
|
||||||
|
|
||||||
let share = share.unwrap();
|
|
||||||
info!("share: {:?}", share);
|
|
||||||
|
|
||||||
share.notify(&agent).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
use log::debug;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct URI {
|
|
||||||
protocol: String,
|
|
||||||
base_url: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl URI {
|
|
||||||
pub fn new_protocol(base_url: &str, protocol: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
protocol: protocol.into(),
|
|
||||||
base_url: base_url.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(base_url: &str) -> Self {
|
|
||||||
Self::new_protocol(base_url, "https")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_endpoint(&self, endpoint: &str) -> String {
|
|
||||||
let uri = format!("{}://{}/api/v2/{}", self.protocol, self.base_url, endpoint);
|
|
||||||
debug!("uri: {:?}", uri);
|
|
||||||
|
|
||||||
uri
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub struct NewShareRequest<'t> {
|
|
||||||
name: Option<&'t str>,
|
|
||||||
validity: u32,
|
|
||||||
description: &'t str,
|
|
||||||
maxViews: u32,
|
|
||||||
password: Option<&'t str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t> NewShareRequest<'t> {
|
|
||||||
pub fn new(name: Option<&'t str>, description: &'t str, max_views: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name,
|
|
||||||
validity: 0,
|
|
||||||
description: description,
|
|
||||||
maxViews: max_views,
|
|
||||||
password: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct NewShareResponse {
|
|
||||||
pub success: bool,
|
|
||||||
pub message: String,
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct NotifyShareResponse {
|
|
||||||
pub success: bool,
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
pub mod api;
|
|
||||||
|
|
||||||
use api::{NewShareRequest, NewShareResponse, NotifyShareResponse, URI};
|
|
||||||
use log::debug;
|
|
||||||
use ureq::{self, RequestBuilder};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Alias {
|
|
||||||
uri: URI,
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Alias {
|
|
||||||
pub fn new(uri: URI, id: &str) -> Self {
|
|
||||||
Self { uri, id: id.into() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_headers<B>(&self, req: RequestBuilder<B>) -> RequestBuilder<B> {
|
|
||||||
req.header("Sharry-Alias", &self.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_share(
|
|
||||||
&self,
|
|
||||||
http: &ureq::Agent,
|
|
||||||
data: &NewShareRequest,
|
|
||||||
) -> Result<Share, ureq::Error> {
|
|
||||||
let endpoint = self.uri.get_endpoint("alias/upload/new");
|
|
||||||
|
|
||||||
let res = self
|
|
||||||
.add_headers(http.post(endpoint))
|
|
||||||
.send_json(data)?
|
|
||||||
.body_mut()
|
|
||||||
.read_json::<NewShareResponse>()?;
|
|
||||||
|
|
||||||
debug!("response: {:?}", res);
|
|
||||||
assert!(res.success);
|
|
||||||
assert_eq!(res.message, "Share created.");
|
|
||||||
|
|
||||||
Ok(Share {
|
|
||||||
alias: self,
|
|
||||||
id: res.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Share<'t> {
|
|
||||||
alias: &'t Alias,
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t> Share<'t> {
|
|
||||||
pub fn add_file(&self) {}
|
|
||||||
|
|
||||||
pub fn notify(&self, http: &ureq::Agent) -> Result<(), ureq::Error> {
|
|
||||||
let endpoint = self
|
|
||||||
.alias
|
|
||||||
.uri
|
|
||||||
.get_endpoint(&format!("alias/mail/notify/{}", &self.id));
|
|
||||||
|
|
||||||
let res = self
|
|
||||||
.alias
|
|
||||||
.add_headers(http.post(endpoint))
|
|
||||||
.send_empty()?
|
|
||||||
.body_mut()
|
|
||||||
.read_json::<NotifyShareResponse>()?;
|
|
||||||
|
|
||||||
debug!("response: {:?}", res);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue