openai_interface/files/
delete.rs1pub mod request {
4 use url::Url;
5
6 use crate::{
7 errors::OapiError,
8 rest::delete::{Delete, DeleteNoStream},
9 };
10
11 #[derive(Debug, Default)]
12 pub struct DeleteRequest<'a> {
13 pub file_id: &'a str,
14 pub extra_headers: serde_json::Map<String, serde_json::Value>,
16 }
17
18 impl Delete for DeleteRequest<'_> {
19 fn build_url(&self, base_url: &str) -> Result<String, crate::errors::OapiError> {
21 let url = Url::parse(base_url)
22 .map_err(|e| OapiError::UrlError(e))?
23 .join("files/")
24 .unwrap()
25 .join(self.file_id)
26 .map_err(|e| OapiError::UrlError(e))?;
27
28 println!("Built URL: {}", url);
29 Ok(url.to_string())
30 }
31 }
32
33 impl<'a> DeleteNoStream for DeleteRequest<'a> {
34 type Response = super::response::FileDeleted;
35 }
36}
37
38mod response {
39 use std::str::FromStr;
40
41 use serde::Deserialize;
42
43 use crate::errors::OapiError;
44
45 #[derive(Debug, Deserialize, Clone)]
46 pub struct FileDeleted {
47 pub id: String,
48 pub deleted: bool,
49 pub object: FileDeletedObject,
50 }
51
52 #[derive(Debug, Deserialize, Clone)]
53 #[serde(rename_all = "snake_case")]
54 pub enum FileDeletedObject {
55 File,
56 }
57
58 impl FromStr for FileDeleted {
59 type Err = crate::errors::OapiError;
60
61 fn from_str(s: &str) -> Result<Self, Self::Err> {
62 serde_json::from_str(s).map_err(|e| OapiError::DeserializationError(e.to_string()))
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use std::sync::LazyLock;
70
71 use anyhow::{Context, anyhow};
72
73 use crate::{
74 files::{delete::request::DeleteRequest, list::request::ListFilesRequest},
75 rest::{delete::DeleteNoStream, get::GetNoStream},
76 };
77
78 const MODELSTUDIO_BASE_URL: &str = "https://dashscope.aliyuncs.com/compatible-mode/v1/";
79 const MODELSTUDIO_KEY: LazyLock<&str> =
80 LazyLock::new(|| include_str!("../../keys/modelstudio_domestic_key").trim());
81
82 #[tokio::test]
83 async fn test_modelstudio_delete_files() -> anyhow::Result<()> {
84 let list_request = ListFilesRequest::default();
85 let list_response = list_request
86 .get_response(MODELSTUDIO_BASE_URL, &MODELSTUDIO_KEY)
87 .await
88 .with_context(|| anyhow!("Failed to list files."))?;
89
90 let files = list_response
91 .data
92 .iter()
93 .filter_map(|file_object| {
94 let name = file_object.filename.as_str();
95 let file_id = file_object.id.as_str();
96 if name.starts_with("test") {
97 Some(file_id)
98 } else {
99 None
100 }
101 })
102 .collect::<Vec<&str>>();
103
104 let futures = files
105 .iter()
106 .map(|file| async move {
107 let delete_request = DeleteRequest {
108 file_id: file,
109 ..Default::default()
110 };
111 delete_request
112 .get_response(MODELSTUDIO_BASE_URL, &MODELSTUDIO_KEY)
113 .await
114 .with_context(|| anyhow!("Failed to delete file {}", file))
115 })
116 .collect::<Vec<_>>();
117
118 let results = futures_util::future::join_all(futures).await;
119
120 for result in results {
121 result?;
122 }
123
124 Ok(())
125 }
126}