getpocket/ext/
modifying.rs

1// TODO: remove this derive after implementing the code
2#![allow(unused_variables)]
3// TODO: remove this derive after implementing the code
4#![allow(dead_code)]
5
6use crate::client::{GetPocket, RecordSendDirect};
7use anyhow::Result;
8use async_trait::async_trait;
9use serde::{Deserialize, Serialize};
10use thiserror::Error;
11
12#[derive(Error, Debug)]
13pub enum ModifyingError<'a> {
14    #[error("Invalid Params: `{0}`")]
15    InvalidParams(&'a str),
16}
17
18#[derive(Debug, Deserialize, Clone)]
19pub struct RecordModified {
20    pub is_success: bool,
21    pub status: i32,
22    #[serde(skip_serializing_if = "Vec::is_empty")]
23    pub errors: Vec<Option<String>>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub data: Option<serde_json::Value>,
26}
27
28#[derive(Debug, Serialize)]
29pub enum Action {
30    #[serde(rename = "archive")]
31    Archive,
32    #[serde(rename = "readd")]
33    Readd,
34    #[serde(rename = "favorite")]
35    Favorite,
36    #[serde(rename = "unfavorite")]
37    Unfavorite,
38    #[serde(rename = "delete")]
39    Delete,
40}
41
42#[derive(Debug, Serialize)]
43pub struct RequestArchive {
44    action: Action,
45    /// The id of the item to perform the action on.
46    item_id: i64,
47    /// The time the action occurred. Unix epoch in milliseconds
48    #[serde(skip_serializing_if = "Option::is_none")]
49    time: Option<i32>,
50}
51
52#[derive(Debug, Serialize)]
53pub struct RequestReadd {
54    action: Action,
55    /// The id of the item to perform the action on.
56    item_id: i64,
57    /// The time the action occurred. Unix epoch in milliseconds
58    #[serde(skip_serializing_if = "Option::is_none")]
59    time: Option<i32>,
60}
61
62#[derive(Debug, Serialize)]
63pub struct RequestFavorite {
64    action: Action,
65    /// The id of the item to perform the action on.
66    item_id: i64,
67    /// The time the action occurred. Unix epoch in milliseconds
68    #[serde(skip_serializing_if = "Option::is_none")]
69    time: Option<i32>,
70}
71
72#[derive(Debug, Serialize)]
73pub struct RequestUnfavorite {
74    action: Action,
75    /// The id of the item to perform the action on.
76    item_id: i64,
77    /// The time the action occurred. Unix epoch in milliseconds
78    #[serde(skip_serializing_if = "Option::is_none")]
79    time: Option<i32>,
80}
81
82#[derive(Debug, Serialize)]
83pub struct RequestDelete {
84    action: Action,
85    /// The id of the item to perform the action on.
86    item_id: i64,
87    /// The time the action occurred. Unix epoch in milliseconds
88    #[serde(skip_serializing_if = "Option::is_none")]
89    time: Option<i32>,
90}
91
92/// <https://getpocket.com/developer/docs/v3/modify>
93#[async_trait]
94pub trait ModifyingExt {
95    #[deprecated(
96        since = "0.3.0",
97        note = "This function will be removed in next version. Please see the README for migration guidance."
98    )]
99    /// Move an item to the user's archive
100    async fn archive(&self, item_id: i64) -> Result<RecordModified>;
101
102    #[deprecated(
103        since = "0.3.0",
104        note = "This function will be removed in next version. Please see the README for migration guidance."
105    )]
106    /// Re-add (unarchive) an item to the user's list
107    async fn readd(&self, item_id: i64) -> Result<RecordModified>;
108
109    #[deprecated(
110        since = "0.3.0",
111        note = "This function will be removed in next version. Please see the README for migration guidance."
112    )]
113    /// Mark an item as a favorite
114    async fn favorite(&self, item_id: i64) -> Result<RecordModified>;
115
116    #[deprecated(
117        since = "0.3.0",
118        note = "This function will be removed in next version. Please see the README for migration guidance."
119    )]
120    /// Remove an item from the user's favorites
121    async fn unfavorite(&self, item_id: i64) -> Result<RecordModified>;
122
123    #[deprecated(
124        since = "0.3.0",
125        note = "This function will be removed in next version. Please see the README for migration guidance."
126    )]
127    /// Permanently remove an item from the user's account
128    async fn delete(&self, item_id: i64) -> Result<RecordModified>;
129}
130
131#[async_trait]
132impl ModifyingExt for GetPocket {
133    /// Move an item to the user's archive
134    async fn archive(&self, item_id: i64) -> Result<RecordModified> {
135        let params = RequestArchive {
136            action: Action::Archive,
137            item_id,
138            time: None,
139        };
140
141        let resp = &self.send(&[params]).await?;
142
143        Ok(resp.into())
144    }
145
146    /// Move an item from the user's archive back into their unread list.
147    async fn readd(&self, item_id: i64) -> Result<RecordModified> {
148        let params = RequestReadd {
149            action: Action::Readd,
150            item_id,
151            time: None,
152        };
153
154        let resp = &self.send(&[params]).await?;
155
156        Ok(resp.into())
157    }
158
159    /// Mark an item as a favorite
160    async fn favorite(&self, item_id: i64) -> Result<RecordModified> {
161        let params = RequestFavorite {
162            action: Action::Favorite,
163            item_id,
164            time: None,
165        };
166
167        let resp = &self.send(&[params]).await?;
168
169        Ok(resp.into())
170    }
171
172    /// Remove an item from the user's favorites
173    async fn unfavorite(&self, item_id: i64) -> Result<RecordModified> {
174        let params = RequestUnfavorite {
175            action: Action::Unfavorite,
176            item_id,
177            time: None,
178        };
179
180        let resp = &self.send(&[params]).await?;
181
182        Ok(resp.into())
183    }
184
185    /// Permanently remove an item from the user's account
186    async fn delete(&self, item_id: i64) -> Result<RecordModified> {
187        let params = RequestDelete {
188            action: Action::Delete,
189            item_id,
190            time: None,
191        };
192
193        let resp = &self.send(&[params]).await?;
194
195        Ok(resp.into())
196    }
197}
198
199impl From<&RecordSendDirect> for RecordModified {
200    fn from(record: &RecordSendDirect) -> Self {
201        match record {
202            RecordSendDirect::Standart(record) => {
203                let Some(first_action_result) = record.action_results.get(0) else {
204                    return Self {
205                        is_success: false,
206                        status: record.status,
207                        errors: vec![Some("No action results".to_string())],
208                        data: None,
209                    };
210                };
211
212                Self {
213                    is_success: *first_action_result,
214                    status: record.status,
215                    errors: vec![],
216                    data: None,
217                }
218            }
219            RecordSendDirect::Extended(record) => Self {
220                is_success: !record.action_errors.is_empty(),
221                status: record.status,
222                errors: record.action_errors.clone(),
223                data: Some(record.action_results.clone()),
224            },
225        }
226    }
227}