pigrabbit/
prclient.rs

1use crate::PigRabbitError;
2use serde::Serialize;
3
4use crate::types::*;
5const API_URL: &str = "https://porkbun.com/api/json/v3/";
6pub struct PRClient {
7    pub key: Keys,
8    client: reqwest::Client,
9}
10
11/// **The domain_name argument for each function is the one that you own on PorkBun.com**
12impl PRClient {
13    pub fn new(keys: Keys) -> Self {
14        let client = reqwest::Client::new();
15        Self { key: keys, client }
16    }
17
18    /// The `send_request` function that execute the post request with the given body.
19    async fn send_request<T: Serialize>(
20        client: &mut reqwest::Client,
21        url: &str,
22        body: T,
23    ) -> Result<serde_json::Value, PigRabbitError> {
24        let res: serde_json::Value = client.post(url).json(&body).send().await?.json().await?;
25        Ok(res)
26    }
27
28    /// The `ping_test` pings the server to check if the server is online as well as testing credentials.
29    pub async fn ping_test(&mut self) -> Result<(), PigRabbitError> {
30        let url = format!("{API_URL}ping");
31        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
32        match res["status"].as_str().unwrap() {
33            "SUCCESS" => Ok(()),
34            _ => Err(PigRabbitError::ResponseError(res)),
35        }
36    }
37
38    /// The add_record function adds a DNS Record and return an id as an i64.
39    pub async fn add_record(
40        &mut self,
41        domain: &str,
42        record_struct: &Record,
43    ) -> Result<i64, PigRabbitError> {
44        let url = format!("{API_URL}dns/create/{domain}");
45        let body = ComplicatedBody {
46            secretapikey: &self.key.secretapikey,
47            apikey: &self.key.apikey,
48            name: &record_struct.name,
49            dtype: &record_struct.dtype,
50            content: &record_struct.content,
51            ttl: &record_struct.ttl,
52        };
53        let res = Self::send_request(&mut self.client, &url, &body).await?;
54        match res["status"].as_str().unwrap() {
55            "SUCCESS" => Ok(res["id"].as_i64().unwrap()),
56            _ => Err(PigRabbitError::ResponseError(res)),
57        }
58    }
59
60    /// This function edits the record based on the domain.
61    /// While the id requires you to get the id from the api.
62    ///
63    /// You can use the `retrieve_by_domain_with_id` function with an  empty id
64    /// to list all of your records.
65    pub async fn edit_by_domain_and_id(
66        &mut self,
67        domain: &str,
68        id: &str,
69        record_struct: &Record,
70    ) -> Result<(), PigRabbitError> {
71        let url = format!("{API_URL}dns/edit/{domain}/{id}");
72        let body = ComplicatedBody {
73            secretapikey: &self.key.secretapikey,
74            apikey: &self.key.apikey,
75            name: &record_struct.name,
76            dtype: &record_struct.dtype,
77            content: &record_struct.content,
78            ttl: &record_struct.ttl,
79        };
80        let res = Self::send_request(&mut self.client, &url, &body).await?;
81        match res["status"].as_str().unwrap() {
82            "SUCCESS" => Ok(()),
83            _ => Err(PigRabbitError::ResponseError(res)),
84        }
85    }
86
87    /// This function edits the record based on the domain, type and(or) subdomain.
88    pub async fn edit_by_domain_subdomain_and_type(
89        &mut self,
90        domain: &str,
91        subdomain: &str,
92        record_struct: &Record,
93    ) -> Result<(), PigRabbitError> {
94        let domain_type = &record_struct.dtype;
95        let url = format!("{API_URL}dns/editByNameType/{domain}/{domain_type}/{subdomain}");
96        let body = SimpleBody {
97            secretapikey: &self.key.secretapikey,
98            apikey: &self.key.apikey,
99            content: &record_struct.content,
100            ttl: &record_struct.ttl,
101        };
102        let res = Self::send_request(&mut self.client, &url, &body).await?;
103        match res["status"].as_str().unwrap() {
104            "SUCCESS" => Ok(()),
105            _ => Err(PigRabbitError::ResponseError(res)),
106        }
107    }
108
109    /// This function deletes the record with the domain name, type and subdomain specified.
110    pub async fn del_by_type_with_subdomain(
111        &mut self,
112        dtype: &str,
113        domain: &str,
114        subdomain: &str,
115    ) -> Result<(), PigRabbitError> {
116        let url = format!("{API_URL}dns/deleteByNameType/{domain}/{dtype}/{subdomain}");
117        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
118        match res["status"].as_str().unwrap() {
119            "SUCCESS" => Ok(()),
120            _ => Err(PigRabbitError::ResponseError(res)),
121        }
122    }
123
124    /// This function deletes the record with the domain name and id specified.
125    pub async fn del_by_id(&mut self, domain: &str, id: &str) -> Result<(), PigRabbitError> {
126        let url = format!("{API_URL}dns/delete/{domain}/{id}");
127        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
128        match res["status"].as_str().unwrap() {
129            "SUCCESS" => Ok(()),
130            _ => Err(PigRabbitError::ResponseError(res)),
131        }
132    }
133
134    /// This function retrieve the record information
135    /// with the domain name, type and subdomain specified.
136    pub async fn retreive_by_type_with_subdomain(
137        &mut self,
138        dtype: &str,
139        domain: &str,
140        subdomain: &str,
141    ) -> Result<Vec<RecordInfo>, PigRabbitError> {
142        let url = format!("{API_URL}dns/retrieveByNameType/{domain}/{dtype}/{subdomain}");
143        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
144
145        match res["status"].as_str().unwrap() {
146            "SUCCESS" => Ok(res["records"]
147                .as_array()
148                .map(|c| {
149                    c.iter()
150                        .map(|m| serde_json::from_value(m.to_owned()).unwrap())
151                        .collect()
152                })
153                .unwrap()),
154            _ => Err(PigRabbitError::ResponseError(res)),
155        }
156    }
157
158    /// This function,
159    ///
160    /// *with a specified id*: retrieves the information on the specific record that
161    /// you wanted to view.
162    ///
163    /// *without a specified id*: lists all the records under that domain name.
164    pub async fn retreive_by_domain_with_id(
165        &mut self,
166        domain: &str,
167        id: &str,
168    ) -> Result<Vec<RecordInfo>, PigRabbitError> {
169        let url = format!("{API_URL}dns/retrieve/{domain}/{id}");
170        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
171
172        match res["status"].as_str().unwrap() {
173            "SUCCESS" => Ok(res["records"]
174                .as_array()
175                .map(|c| {
176                    c.iter()
177                        .map(|m| serde_json::from_value(m.to_owned()).unwrap())
178                        .collect()
179                })
180                .unwrap()),
181            _ => Err(PigRabbitError::ResponseError(res)),
182        }
183    }
184
185    /// This function retrieves all the ssl certificates attatched to the domain specified.
186    pub async fn retreive_ssl_by_domain(
187        &mut self,
188        domain: &str,
189    ) -> Result<Certificate, PigRabbitError> {
190        let url = format!("{API_URL}ssl/retrieve/{domain}");
191        let res = Self::send_request(&mut self.client, &url, &self.key).await?;
192
193        match res["status"].as_str().unwrap() {
194            "SUCCESS" => Ok(serde_json::from_value(res).unwrap()),
195            _ => Err(PigRabbitError::ResponseError(res)),
196        }
197    }
198}