summer_ipfs_client/
pin.rs

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 fn pin_add(&self, hash: &str, recursive: bool) -> Result<PinResponse, Error> {
27        let mut url = self.get_url()?;
28        url.set_path("api/v0/pin/add");
29        url.query_pairs_mut()
30            .append_pair("arg", hash)
31            .append_pair("recursive", &recursive.to_string())
32            .append_pair("progress", "false");
33        let resp = reqwest::get(url)?;
34        Ok(serde_json::from_reader(resp)?)
35    }
36
37    pub fn pin_rm(&self, hash: &str, recursive: bool) -> Result<PinResponse, Error> {
38        let mut url = self.get_url()?;
39        url.set_path("api/v0/pin/rm");
40        url.query_pairs_mut()
41            .append_pair("arg", hash)
42            .append_pair("recursive", &recursive.to_string());
43        let resp = reqwest::get(url)?;
44        Ok(serde_json::from_reader(resp)?)
45    }
46
47
48    pub fn pin_list(&self) -> Result<Vec<PinnedHash>, Error> {
49        let mut url = self.get_url()?;
50        url.set_path("api/v0/pin/ls");
51        let resp = reqwest::get(url)?;
52        let json_resp: serde_json::Value = serde_json::from_reader(resp)?;
53
54        let mut hashes = Vec::new();
55
56        let keys = json_resp.get("Keys").ok_or(err_msg(""))?.as_object().ok_or(err_msg(""))?;
57
58        for (key, value) in keys.iter() {
59            hashes.push(PinnedHash {
60                hash: key.clone(),
61                pin_type: match &value.get("Type").ok_or(err_msg(""))?.as_str().ok_or(err_msg(""))? {
62                    &"direct" => PinType::Direct,
63                    &"indirect" => PinType::Indirect,
64                    &"recursive" => PinType::Recursive,
65                    _ => PinType::Direct
66                }
67            });
68        }
69        
70        Ok(hashes)
71    }
72}
73
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_pin_full() {
81        let api = IpfsApi::new("127.0.0.1", 5001);
82        
83        let hello = "QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u";
84
85        for pin in api.pin_list().unwrap() {
86            if pin.pin_type == PinType::Direct || pin.pin_type == PinType::Recursive {
87                api.pin_rm(&pin.hash, true).unwrap();
88            }
89        }
90
91        let resp = api.pin_add(hello, false).unwrap();
92        
93        assert_eq!(resp.pins.len(), 1);
94        assert_eq!(resp.pins[0], "QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u".to_string());
95    }
96}