1use crate::IpfsApi;
2
3use reqwest;
4use serde_json;
5use failure::{Error, err_msg};
6
7#[derive(Deserialize, Debug, PartialEq, Hash)]
8#[serde(rename_all = "PascalCase")]
9pub struct PinResponse {
10 pins: Vec<String>
11}
12
13#[derive(PartialEq)]
14pub enum PinType {
15 Direct,
16 Indirect,
17 Recursive,
18}
19
20pub struct PinnedHash {
21 pub hash: String,
22 pub pin_type: PinType,
23}
24
25impl IpfsApi {
26 pub async fn pin_add(&self, hash: &str, recursive: bool) -> Result<PinResponse, Error> {
32 let mut url = self.get_url()?;
33 url.set_path("api/v0/pin/add");
34 url.query_pairs_mut()
35 .append_pair("arg", hash)
36 .append_pair("recursive", &recursive.to_string())
37 .append_pair("progress", "false");
38
39 Ok(reqwest::get(url).await?.json().await?)
40 }
41
42 pub async fn pin_rm(&self, hash: &str, recursive: bool) -> Result<PinResponse, Error> {
44 let mut url = self.get_url()?;
45 url.set_path("api/v0/pin/rm");
46 url.query_pairs_mut()
47 .append_pair("arg", hash)
48 .append_pair("recursive", &recursive.to_string());
49
50 Ok(reqwest::get(url).await?.json().await?)
51 }
52
53
54 pub async fn pin_list(&self) -> Result<Vec<PinnedHash>, Error> {
56 let mut url = self.get_url()?;
57 url.set_path("api/v0/pin/ls");
58 let resp: serde_json::Value = reqwest::get(url).await?.json().await?;
59
60 let mut hashes = Vec::new();
61
62 let keys = resp.get("Keys").ok_or(err_msg(""))?.as_object().ok_or(err_msg(""))?;
63
64 for (key, value) in keys.iter() {
65 hashes.push(PinnedHash {
66 hash: key.clone(),
67 pin_type: match &value.get("Type").ok_or(err_msg(""))?.as_str().ok_or(err_msg(""))? {
68 &"direct" => PinType::Direct,
69 &"indirect" => PinType::Indirect,
70 &"recursive" => PinType::Recursive,
71 _ => PinType::Direct
72 },
73 });
74 }
75
76 Ok(hashes)
77 }
78}
79
80
81#[cfg(test)]
82mod tests {
83 use crate::IpfsApi;
84 use pin::PinType;
85
86 #[test]
88 fn test_pin_full() {
89 let api = IpfsApi::new("127.0.0.1", 5001);
90
91 let hello = "QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u";
93
94 for pin in api.pin_list().unwrap() {
96 if pin.pin_type == PinType::Direct || pin.pin_type == PinType::Recursive {
97 api.pin_rm(&pin.hash, true).unwrap();
98 }
99 }
100
101 let resp = api.pin_add(hello, false).unwrap();
103
104 assert_eq!(resp.pins.len(), 1);
106 assert_eq!(resp.pins[0], "QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u".to_string());
107 }
108}