nblm_core/client/api/
sources.rs1use bytes::Bytes;
2use reqwest::{
3 header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE},
4 Method,
5};
6
7use crate::error::{Error, Result};
8use crate::models::{
9 BatchCreateSourcesRequest, BatchCreateSourcesResponse, BatchDeleteSourcesRequest,
10 BatchDeleteSourcesResponse, UploadSourceFileResponse, UserContent,
11};
12
13use crate::client::NblmClient;
14
15impl NblmClient {
17 pub async fn batch_create_sources(
18 &self,
19 notebook_id: &str,
20 request: BatchCreateSourcesRequest,
21 ) -> Result<BatchCreateSourcesResponse> {
22 let path = format!(
23 "{}/sources:batchCreate",
24 self.url_builder.notebook_path(notebook_id)
25 );
26 let url = self.url_builder.build_url(&path)?;
27 self.http
28 .request_json(Method::POST, url, Some(&request))
29 .await
30 }
31
32 pub async fn add_sources(
33 &self,
34 notebook_id: &str,
35 contents: Vec<UserContent>,
36 ) -> Result<BatchCreateSourcesResponse> {
37 let request = BatchCreateSourcesRequest {
38 user_contents: contents,
39 };
40 self.batch_create_sources(notebook_id, request).await
41 }
42
43 pub async fn batch_delete_sources(
44 &self,
45 notebook_id: &str,
46 request: BatchDeleteSourcesRequest,
47 ) -> Result<BatchDeleteSourcesResponse> {
48 let path = format!(
49 "{}/sources:batchDelete",
50 self.url_builder.notebook_path(notebook_id)
51 );
52 let url = self.url_builder.build_url(&path)?;
53 self.http
54 .request_json(Method::POST, url, Some(&request))
55 .await
56 }
57
58 pub async fn delete_sources(
59 &self,
60 notebook_id: &str,
61 source_names: Vec<String>,
62 ) -> Result<BatchDeleteSourcesResponse> {
63 let request = BatchDeleteSourcesRequest {
64 names: source_names,
65 };
66 self.batch_delete_sources(notebook_id, request).await
67 }
68
69 pub async fn upload_source_file(
70 &self,
71 notebook_id: &str,
72 file_name: &str,
73 content_type: &str,
74 data: Vec<u8>,
75 ) -> Result<UploadSourceFileResponse> {
76 if notebook_id.trim().is_empty() {
77 return Err(Error::validation("notebook_id cannot be empty"));
78 }
79 if file_name.trim().is_empty() {
80 return Err(Error::validation("file name cannot be empty"));
81 }
82 if content_type.trim().is_empty() {
83 return Err(Error::validation("content type cannot be empty"));
84 }
85
86 let path = format!(
87 "{}/sources:uploadFile",
88 self.url_builder.notebook_path(notebook_id)
89 );
90 let mut url = self.url_builder.build_upload_url(&path)?;
91 url.query_pairs_mut().append_pair("uploadType", "media");
92
93 let mut headers = HeaderMap::new();
94 headers.insert(
95 HeaderName::from_static("x-goog-upload-protocol"),
96 HeaderValue::from_static("raw"),
97 );
98 let file_name_header = HeaderValue::from_str(file_name)
99 .map_err(|_| Error::validation("file name contains invalid characters"))?;
100 headers.insert(
101 HeaderName::from_static("x-goog-upload-file-name"),
102 file_name_header,
103 );
104 let content_type_header = HeaderValue::from_str(content_type)
105 .map_err(|_| Error::validation("content type contains invalid characters"))?;
106 headers.insert(CONTENT_TYPE, content_type_header);
107
108 let bytes = Bytes::from(data);
109 self.http
110 .request_binary(Method::POST, url, headers, bytes)
111 .await
112 }
113
114 pub async fn get_source(
125 &self,
126 notebook_id: &str,
127 source_id: &str,
128 ) -> Result<crate::models::NotebookSource> {
129 if notebook_id.trim().is_empty() {
130 return Err(Error::validation("notebook_id cannot be empty"));
131 }
132 if source_id.trim().is_empty() {
133 return Err(Error::validation("source_id cannot be empty"));
134 }
135
136 let path = format!(
137 "{}/sources/{}",
138 self.url_builder.notebook_path(notebook_id),
139 source_id
140 );
141 let url = self.url_builder.build_url(&path)?;
142 self.http
143 .request_json::<(), _>(Method::GET, url, None::<&()>)
144 .await
145 }
146}