restructure sharry module (logic)

This commit is contained in:
Jörn-Michael Miehe 2025-05-24 00:22:24 +00:00
parent 58b8c1dd7c
commit 8d8f7bb0a8
5 changed files with 70 additions and 110 deletions

View file

@ -1,7 +1,7 @@
mod sharry; mod sharry;
use log::info; use log::info;
use sharry::{Alias, NewShareRequest, URI}; use sharry::{Alias, NewShareRequest, Share};
use std::time::Duration; use std::time::Duration;
use ureq::Agent; use ureq::Agent;
@ -14,16 +14,15 @@ fn main() {
.into(); .into();
let alias = Alias::new( let alias = Alias::new(
URI::new("sharry.yavook.de"), "sharry.yavook.de".into(),
"G7RYoWME1W7-pcgipemJcr8-39FcMd92gBu-RgufeHc51z6", "G7RYoWME1W7-pcgipemJcr8-39FcMd92gBu-RgufeHc51z6",
); );
let share = alias.create_share(&agent, &NewShareRequest::new(Some("foo"), "", 10)); let share = NewShareRequest::new(Some("foo"), "", 10);
let share = Share::create(&agent, &alias, share).unwrap();
let share = share.unwrap();
info!("share: {:?}", share); info!("share: {:?}", share);
share.create_file(&agent, "./myfile.dat").unwrap(); // share.create_file(&agent, "./myfile.dat").unwrap();
share.notify(&agent).unwrap(); share.notify(&agent).unwrap();
} }

View file

@ -1,41 +1,38 @@
use log::debug; use std::fmt::{Debug, Display};
use ureq::{Agent, RequestBuilder};
use super::{ use log::debug;
api::{NewShareRequest, NewShareResponse, URI}, use ureq::RequestBuilder;
share::Share,
}; use super::api::URI;
#[derive(Debug)] #[derive(Debug)]
pub struct Alias { pub struct Alias {
pub(super) uri: URI, pub(super) api_uri: String,
pub(super) id: String, pub(super) id: String,
} }
impl Alias { pub(super) trait SharryAlias {
pub fn new(uri: URI, id: impl Into<String>) -> Self { fn sharry_header(self, alias: &Alias) -> Self;
Self { uri, id: id.into() } }
}
pub(super) fn add_headers<B>(&self, req: RequestBuilder<B>) -> RequestBuilder<B> { impl<B> SharryAlias for RequestBuilder<B> {
req.header("Sharry-Alias", &self.id) fn sharry_header(self, alias: &Alias) -> Self {
} self.header("Sharry-Alias", &alias.id)
}
pub fn create_share(&self, http: &Agent, data: &NewShareRequest) -> Result<Share, ureq::Error> { }
let endpoint = self.uri.get_endpoint("alias/upload/new");
impl Alias {
let res = self pub fn new(api_uri: URI, id: impl Into<String>) -> Self {
.add_headers(http.post(endpoint)) Self {
.send_json(data)? api_uri: api_uri.into(),
.body_mut() id: id.into(),
.read_json::<NewShareResponse>()?; }
}
debug!("response: {:?}", res);
pub(super) fn get_endpoint(&self, endpoint: impl Display + Debug) -> String {
if !(res.success && (res.message == "Share created.")) { let uri = format!("{}/{}", self.api_uri, endpoint);
return Err(ureq::Error::Other("unexpected response json".into())); debug!("endpoint uri: {:?}", uri);
}
uri
Ok(Share::new(self, res.id))
} }
} }

View file

@ -1,31 +1,28 @@
use std::fmt::Display;
use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct URI { pub struct URI {
protocol: String, protocol: String,
base_url: String, base_url: String,
} }
impl URI { impl URI {
pub fn new_protocol(base_url: impl Into<String>, protocol: impl Into<String>) -> Self { pub fn with_protocol(protocol: impl Into<String>, base_url: impl Into<String>) -> Self {
Self { Self {
protocol: protocol.into(), protocol: protocol.into(),
base_url: base_url.into(), base_url: base_url.into(),
} }
} }
}
pub fn new(base_url: impl Into<String>) -> Self { impl From<&str> for URI {
Self::new_protocol(base_url, "https") fn from(value: &str) -> Self {
Self::with_protocol("https", value)
} }
}
pub(super) fn get_endpoint(&self, endpoint: impl Display) -> String { impl Into<String> for URI {
let uri = format!("{}://{}/api/v2/{}", self.protocol, self.base_url, endpoint); fn into(self) -> String {
debug!("uri: {:?}", uri); format!("{}://{}/api/v2", self.protocol, self.base_url)
uri
} }
} }

View file

@ -4,3 +4,4 @@ mod share;
pub use alias::Alias; pub use alias::Alias;
pub use api::{NewShareRequest, URI}; pub use api::{NewShareRequest, URI};
pub use share::Share;

View file

@ -1,81 +1,47 @@
use log::debug; use log::{debug, warn};
use std::{ffi::OsStr, fs, path::Path};
use ureq::{Agent, http::StatusCode};
use super::{alias::Alias, api}; use super::{
use api::NotifyShareResponse; alias::{Alias, SharryAlias},
api::{NewShareRequest, NewShareResponse, NotifyShareResponse},
};
#[derive(Debug)] #[derive(Debug)]
pub struct Share<'t> { pub struct Share<'t> {
alias: &'t Alias, pub(super) alias: &'t Alias,
id: String, pub(super) id: String,
} }
impl<'t> Share<'t> { impl<'t> Share<'t> {
pub(super) fn new(alias: &'t Alias, id: String) -> Self { pub fn create(
Self { alias, id } http: &ureq::Agent,
} alias: &'t Alias,
data: NewShareRequest,
) -> Result<Self, ureq::Error> {
let res = http
.post(alias.get_endpoint("alias/upload/new"))
.sharry_header(alias)
.send_json(data)?
.body_mut()
.read_json::<NewShareResponse>()?;
pub fn create_file( debug!("response: {:?}", res);
&self,
http: &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(); if !(res.success && (res.message == "Share created.")) {
warn!("unexpected json response");
let endpoint = self return Err(ureq::Error::Other("unexpected json response".into()));
.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()?;
if res.status() != StatusCode::CREATED {
return Err(ureq::Error::Other("unexpected response status".into()));
} }
let location = res Ok(Self { alias, id: res.id })
.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(())
} }
pub fn notify(&self, http: &ureq::Agent) -> Result<(), ureq::Error> { pub fn notify(&self, http: &ureq::Agent) -> Result<(), ureq::Error> {
let endpoint = self let endpoint = self
.alias .alias
.uri .get_endpoint(format!("alias/mail/notify/{}", self.id));
.get_endpoint(&format!("alias/mail/notify/{}", &self.id));
let res = self let res = http
.alias .post(endpoint)
.add_headers(http.post(endpoint)) .sharry_header(self.alias)
.send_empty()? .send_empty()?
.body_mut() .body_mut()
.read_json::<NotifyShareResponse>()?; .read_json::<NotifyShareResponse>()?;