urbit_http_api/apps/
collections.rs

1use crate::apps::notebook::Comment;
2use crate::graph::NodeContents;
3use crate::helper::{get_current_da_time, get_current_time};
4use crate::AuthoredMessage;
5use crate::{Channel, Node, Result, UrbitAPIError};
6
7/// A struct that provides an interface for interacting with Urbit collections
8pub struct Collection<'a> {
9    pub channel: &'a mut Channel,
10}
11
12/// A struct that represents a Collection link
13#[derive(Clone, Debug)]
14pub struct Link {
15    pub title: String,
16    pub author: String,
17    pub time_sent: String,
18    pub url: String,
19    pub comments: Vec<Comment>,
20    pub index: String,
21}
22
23impl Link {
24    /// Create a new `Link`
25    pub fn new(
26        title: &str,
27        author: &str,
28        time_sent: &str,
29        url: &str,
30        comments: &Vec<Comment>,
31        index: &str,
32    ) -> Link {
33        Link {
34            title: title.to_string(),
35            author: author.to_string(),
36            time_sent: time_sent.to_string(),
37            url: url.to_string(),
38            comments: comments.clone(),
39            index: index.to_string(),
40        }
41    }
42
43    /// Convert from a `Node` to a `Link`
44    pub fn from_node(node: &Node) -> Result<Link> {
45        let mut comments: Vec<Comment> = vec![];
46        // Check the to see if the children exist
47        if node.children.len() > 0 && node.children[0].children.len() > 0 {
48            // Find the latest revision of each of the comments
49            for comment_node in &node.children {
50                let mut latest_comment_revision_node = comment_node.children[0].clone();
51                for revision_node in &comment_node.children {
52                    if revision_node.index_tail() > latest_comment_revision_node.index_tail() {
53                        latest_comment_revision_node = revision_node.clone();
54                    }
55                }
56                comments.push(Comment::from_node(&latest_comment_revision_node));
57            }
58        }
59
60        // Acquire the title, which is the first item in the content_list
61        let title = format!("{}", node.contents.content_list[0]["text"]);
62        // Acquire the url, which is the second item in the content_list
63        let url = format!("{}", node.contents.content_list[1]["url"]);
64        let author = node.author.clone();
65        let time_sent = node.time_sent_formatted();
66
67        // Create the note
68        Ok(Link::new(
69            &title,
70            &author,
71            &time_sent,
72            &url,
73            &comments,
74            &node.index,
75        ))
76    }
77}
78
79impl<'a> Collection<'a> {
80    /// Extracts a Collection's graph from the connected ship and parses it into a vector of `Link`s.
81    pub fn export_collection(
82        &mut self,
83        collection_ship: &str,
84        collection_name: &str,
85    ) -> Result<Vec<Link>> {
86        let graph = &self
87            .channel
88            .graph_store()
89            .get_graph(collection_ship, collection_name)?;
90
91        // Parse each top level node (Link) in the collection graph
92        let mut links = vec![];
93        for node in &graph.nodes {
94            let link = Link::from_node(node)?;
95            links.push(link);
96        }
97
98        Ok(links)
99    }
100
101    /// Adds a new link to the specified Collection that your ship has access to.
102    /// Returns the index of the link.
103    pub fn add_link(
104        &mut self,
105        collection_ship: &str,
106        collection_name: &str,
107        title: &str,
108        url: &str,
109    ) -> Result<String> {
110        let mut gs = self.channel.graph_store();
111
112        let link_contents = NodeContents::new().add_text(title).add_url(url);
113        let link_node = gs.new_node(&link_contents);
114
115        if let Ok(_) = gs.add_node(collection_ship, collection_name, &link_node) {
116            Ok(link_node.index)
117        } else {
118            Err(UrbitAPIError::FailedToCreateNote(
119                link_node.to_json().dump(),
120            ))
121        }
122    }
123}