shrupl/src/sharry/mod.rs

122 lines
3 KiB
Rust
Raw Normal View History

2025-05-23 01:11:11 +00:00
mod api;
2025-05-22 17:34:44 +00:00
2025-05-23 01:11:11 +00:00
pub use api::{NewShareRequest, URI};
use api::{NewShareResponse, NotifyShareResponse};
2025-05-22 17:34:44 +00:00
use log::debug;
2025-05-23 01:11:11 +00:00
use std::{ffi::OsStr, fs, path::Path};
2025-05-22 21:07:49 +00:00
use ureq::{self, RequestBuilder};
2025-05-22 17:34:44 +00:00
#[derive(Debug)]
2025-05-22 21:07:49 +00:00
pub struct Alias {
uri: URI,
2025-05-22 17:34:44 +00:00
id: String,
}
2025-05-22 21:07:49 +00:00
impl Alias {
2025-05-23 01:11:11 +00:00
pub fn new(uri: URI, id: impl Into<String>) -> Self {
2025-05-22 21:07:49 +00:00
Self { uri, id: id.into() }
}
fn add_headers<B>(&self, req: RequestBuilder<B>) -> RequestBuilder<B> {
req.header("Sharry-Alias", &self.id)
2025-05-22 17:34:44 +00:00
}
pub fn create_share(
&self,
http: &ureq::Agent,
data: &NewShareRequest,
) -> Result<Share, ureq::Error> {
2025-05-22 21:07:49 +00:00
let endpoint = self.uri.get_endpoint("alias/upload/new");
let res = self
.add_headers(http.post(endpoint))
2025-05-22 17:34:44 +00:00
.send_json(data)?
.body_mut()
.read_json::<NewShareResponse>()?;
2025-05-22 21:07:49 +00:00
debug!("response: {:?}", res);
assert!(res.success);
assert_eq!(res.message, "Share created.");
2025-05-22 17:34:44 +00:00
Ok(Share {
alias: self,
2025-05-22 21:07:49 +00:00
id: res.id,
2025-05-22 17:34:44 +00:00
})
}
}
#[derive(Debug)]
pub struct Share<'t> {
2025-05-22 21:07:49 +00:00
alias: &'t Alias,
2025-05-22 17:34:44 +00:00
id: String,
}
impl<'t> Share<'t> {
2025-05-23 01:11:11 +00:00
pub fn create_file(
&self,
http: &ureq::Agent,
path: impl AsRef<OsStr> + AsRef<Path>,
) -> Result<(), ureq::Error> {
let filename = Path::new(&path)
.file_name()
.and_then(OsStr::to_str)
.unwrap_or("file.bin");
let size = fs::metadata(&path)?.len();
let endpoint = self
.alias
.uri
.get_endpoint(&format!("alias/upload/{}/files/tus", &self.id));
let res = self
.alias
.add_headers(http.post(endpoint))
.header("Sharry-File-Name", filename)
// .header("Sharry-File-Type", "application/octet-stream")
// .header("Sharry-File-Length", size)
// .header("Tus-Resumable", "1.0.0")
.header("Upload-Length", size)
.send_empty()?;
assert_eq!(res.status(), ureq::http::StatusCode::CREATED);
let location = res
.headers()
.get("Location")
.ok_or_else(|| ureq::Error::Other("Location header not found".into()))?
.to_str()
.map_err(|_| ureq::Error::Other("Location header invalid".into()))?;
debug!("location: {}", location);
// let start = 10;
// let count = 10;
// let mut f = File::open(path)?;
// f.seek(SeekFrom::Start(0));
// let mut buf = vec![0; count];
// f.read_exact(&mut buf)?;
Ok(())
}
2025-05-22 21:07:49 +00:00
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(())
}
2025-05-22 17:34:44 +00:00
}