pixeldrain/
lib.rs

1mod client;
2mod model;
3
4pub use self::client::Client;
5pub use self::model::FileInfo;
6pub use self::model::ListUserFilesResponse;
7pub use self::model::UploadFileResponse;
8pub use reqwest::Body;
9use std::path::Path;
10use tokio_util::io::ReaderStream;
11
12/// A file upload
13#[derive(Debug)]
14pub struct FileUpload {
15    /// The file name
16    pub file_name: String,
17
18    /// The file body
19    pub body: Body,
20}
21
22impl FileUpload {
23    pub async fn from_path<P>(path: P) -> std::io::Result<Self>
24    where
25        P: AsRef<Path>,
26    {
27        let path = path.as_ref();
28
29        let file_name = path
30            .file_name()
31            .and_then(|value| value.to_str())
32            .ok_or_else(|| std::io::Error::other("Missing file name"))?
33            .to_string();
34
35        let file = tokio::fs::File::open(path).await?;
36        let body = reqwest::Body::from(file);
37
38        Ok(Self { file_name, body })
39    }
40
41    pub fn from_async_read<R>(file_name: String, reader: R) -> Self
42    where
43        R: tokio::io::AsyncRead + Send + 'static,
44    {
45        Self {
46            file_name,
47            body: reqwest::Body::wrap_stream(ReaderStream::new(reader)),
48        }
49    }
50}
51
52/// Library error
53#[derive(Debug, thiserror::Error)]
54pub enum Error {
55    #[error("http error")]
56    Reqwest(#[from] reqwest::Error),
57
58    #[error("missing token")]
59    MissingToken,
60}
61
62#[cfg(test)]
63mod test {
64    use super::*;
65    use std::path::Path;
66    use std::sync::LazyLock;
67
68    fn try_read_to_string<P>(path: P) -> std::io::Result<Option<String>>
69    where
70        P: AsRef<Path>,
71    {
72        match std::fs::read_to_string(path) {
73            Ok(value) => Ok(Some(value)),
74            Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None),
75            Err(error) => Err(error),
76        }
77    }
78
79    fn load_token() -> String {
80        if let Some(token) = try_read_to_string("token.txt").expect("failed to load token.txt") {
81            return token;
82        }
83
84        std::env::var("PIXELDRAIN_RS_TOKEN")
85            .expect("missing `PIXELDRAIN_RS_TOKEN` environment variable")
86    }
87
88    static TOKEN: LazyLock<String> = LazyLock::new(load_token);
89
90    #[tokio::test]
91    async fn user_list_works() {
92        let client = Client::new();
93        client.set_token(&TOKEN);
94
95        let response = client.list_user_files().await.expect("failed to list");
96        dbg!(response);
97    }
98}