1use bytes::Bytes;
2use reqwest::Method;
3use serde::{Deserialize, Serialize};
4
5use crate::utils::pagination::Response;
6use crate::utils::Field;
7use crate::{ternary, PaperlessClient};
8
9#[derive(Serialize, Deserialize, Clone, Debug, Default)]
10pub struct Document {
11 pub id: u64,
12 pub title: String,
13 pub content: String,
14
15 pub tags: Vec<u64>,
16 pub document_type: Option<String>,
17 pub correspondent: Option<String>,
18
19 pub created: String,
20 pub created_date: Option<String>,
21 pub modified: Option<String>,
22 pub added: String,
23
24 pub archive_serial_number: Option<String>,
25 pub original_file_name: String,
26 pub archived_file_name: Option<String>,
27
28 pub notes: Vec<String>,
29 pub custom_fields: Vec<Field>,
31
32 #[serde(rename = "__search_hit__")]
33 pub search_hit: Option<SearchHit>,
34}
35
36#[derive(Serialize, Deserialize, Clone, Debug, Default)]
37pub struct Metadata {
38 pub original_checksum: String,
39 pub original_size: String,
40 pub original_mime_type: String,
41 pub media_filename: String,
42 pub has_archive_version: bool,
43 pub original_metadata: Vec<Field>,
44
45 pub archive_checksum: Option<String>,
46 pub archive_size: Option<String>,
47 pub archive_metadata: Option<String>,
48}
49
50#[derive(Serialize, Deserialize, Clone, Debug, Default)]
51pub struct SearchHit {
52 pub rank: u64,
53 pub score: f64,
54}
55
56impl PaperlessClient {
57 pub async fn search_documents(
58 &self,
59 query: &str,
60 ) -> Result<Response<Document>, Box<dyn std::error::Error>> {
61 let formatted_query = query.replace(' ', "%20");
62 let url = format!("{}/documents/?query={}", self.base_url, formatted_query);
63
64 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
65 self.call_endpoint(request_builder).await
66 }
67
68 pub async fn fetch_documents(&self) -> Result<Response<Document>, Box<dyn std::error::Error>> {
69 let url = format!("{}/documents/", self.base_url);
70
71 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
72 self.call_endpoint(request_builder).await
73 }
74
75 pub async fn fetch_document(
76 &self,
77 document_id: u64,
78 ) -> Result<Document, Box<dyn std::error::Error>> {
79 let url = format!("{}/documents/{}/", self.base_url, document_id);
80
81 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
82 self.call_endpoint(request_builder).await
83 }
84
85 pub async fn download_document(
86 &self,
87 document_id: u64,
88 original: bool,
89 download_path: &str,
90 ) -> Result<(), Box<dyn std::error::Error>> {
91 let url = format!("{}/documents/{}/download/", self.base_url, document_id);
92 let query_url = format!("{}{}", url, ternary!(original, "?original=true", ""));
93
94 let request_builder = self.prepare_endpoint(Method::GET, query_url).await?;
95 self.call_downloadable_endpoint(request_builder, download_path)
96 .await
97 }
98
99 pub async fn preview_document(
100 &self,
101 document_id: u64,
102 original: bool,
103 ) -> Result<Bytes, Box<dyn std::error::Error>> {
104 let url = format!("{}/documents/{}/preview/", self.base_url, document_id);
105 let query_url = format!("{}{}", url, ternary!(original, "?original=true", ""));
106
107 let request_builder = self.prepare_endpoint(Method::GET, query_url).await?;
108 self.call_binary_endpoint(request_builder).await
109 }
110
111 pub async fn fetch_document_thumbnail(
112 &self,
113 document_id: u64,
114 ) -> Result<String, Box<dyn std::error::Error>> {
115 let url = format!("{}/documents/{}/thumb/", self.base_url, document_id);
116
117 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
118 self.call_endpoint(request_builder).await
119 }
120
121 pub async fn fetch_document_metadata(
122 &self,
123 document_id: u64,
124 ) -> Result<Metadata, Box<dyn std::error::Error>> {
125 let url = format!("{}/documents/{}/metadata/", self.base_url, document_id);
126
127 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
128 self.call_endpoint(request_builder).await
129 }
130
131 pub async fn fetch_document_notes(
132 &self,
133 document_id: u64,
134 ) -> Result<Vec<String>, Box<dyn std::error::Error>> {
135 let url = format!("{}/documents/{}/notes/", self.base_url, document_id);
136
137 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
138 self.call_endpoint(request_builder).await
139 }
140
141 pub async fn fetch_document_share_links(
142 &self,
143 document_id: u64,
144 ) -> Result<Vec<String>, Box<dyn std::error::Error>> {
145 let url = format!("{}/documents/{}/share-links/", self.base_url, document_id);
146
147 let request_builder = self.prepare_endpoint(Method::GET, url).await?;
148 self.call_endpoint(request_builder).await
149 }
150}