1use crate::client::Client;
2use crate::types::ids::{PostId, UserId};
3use crate::types::pagination::{PostsOptions, RepliesOptions};
4use crate::types::post::{Post, PostsResponse, RepliesResponse};
5use crate::types::search::SearchOptions;
6
7fn next_cursor(paging: &crate::types::pagination::Paging) -> Option<String> {
12 paging
13 .cursors
14 .as_ref()
15 .and_then(|c| c.after.clone())
16 .or_else(|| paging.after.clone())
17}
18
19pub struct PostIterator<'a> {
25 client: &'a Client,
26 user_id: UserId,
27 options: PostsOptions,
28 cursor: Option<String>,
29 done: bool,
30}
31
32impl<'a> PostIterator<'a> {
33 pub fn new(client: &'a Client, user_id: UserId, options: Option<PostsOptions>) -> Self {
35 Self {
36 client,
37 user_id,
38 options: options.unwrap_or_default(),
39 cursor: None,
40 done: false,
41 }
42 }
43
44 pub async fn next(&mut self) -> crate::Result<Option<PostsResponse>> {
46 if self.done {
47 return Ok(None);
48 }
49
50 let mut opts = self.options.clone();
51 if let Some(ref c) = self.cursor {
52 opts.after = Some(c.clone());
53 }
54
55 let resp = self
56 .client
57 .get_user_posts(&self.user_id, Some(&opts))
58 .await?;
59
60 if let Some(c) = next_cursor(&resp.paging) {
61 self.cursor = Some(c);
62 } else {
63 self.done = true;
64 }
65
66 if resp.data.is_empty() {
67 self.done = true;
68 return Ok(None);
69 }
70
71 Ok(Some(resp))
72 }
73
74 pub fn has_next(&self) -> bool {
76 !self.done
77 }
78
79 pub fn reset(&mut self) {
81 self.cursor = None;
82 self.done = false;
83 }
84
85 pub async fn collect_all(&mut self) -> crate::Result<Vec<Post>> {
87 let mut all = Vec::new();
88 while self.has_next() {
89 if let Some(resp) = self.next().await? {
90 all.extend(resp.data);
91 }
92 }
93 Ok(all)
94 }
95}
96
97pub struct ReplyIterator<'a> {
103 client: &'a Client,
104 post_id: PostId,
105 options: RepliesOptions,
106 cursor: Option<String>,
107 done: bool,
108}
109
110impl<'a> ReplyIterator<'a> {
111 pub fn new(client: &'a Client, post_id: PostId, options: Option<RepliesOptions>) -> Self {
113 Self {
114 client,
115 post_id,
116 options: options.unwrap_or_default(),
117 cursor: None,
118 done: false,
119 }
120 }
121
122 pub async fn next(&mut self) -> crate::Result<Option<RepliesResponse>> {
124 if self.done {
125 return Ok(None);
126 }
127
128 let mut opts = self.options.clone();
129 if let Some(ref c) = self.cursor {
130 opts.after = Some(c.clone());
131 }
132
133 let resp = self.client.get_replies(&self.post_id, Some(&opts)).await?;
134
135 if let Some(c) = next_cursor(&resp.paging) {
136 self.cursor = Some(c);
137 } else {
138 self.done = true;
139 }
140
141 if resp.data.is_empty() {
142 self.done = true;
143 return Ok(None);
144 }
145
146 Ok(Some(resp))
147 }
148
149 pub fn has_next(&self) -> bool {
151 !self.done
152 }
153
154 pub fn reset(&mut self) {
156 self.cursor = None;
157 self.done = false;
158 }
159
160 pub async fn collect_all(&mut self) -> crate::Result<Vec<Post>> {
162 let mut all = Vec::new();
163 while self.has_next() {
164 if let Some(resp) = self.next().await? {
165 all.extend(resp.data);
166 }
167 }
168 Ok(all)
169 }
170}
171
172pub struct SearchIterator<'a> {
178 client: &'a Client,
179 query: String,
180 options: SearchOptions,
181 cursor: Option<String>,
182 done: bool,
183}
184
185impl<'a> SearchIterator<'a> {
186 pub fn new(
188 client: &'a Client,
189 query: impl Into<String>,
190 options: Option<SearchOptions>,
191 ) -> Self {
192 Self {
193 client,
194 query: query.into(),
195 options: options.unwrap_or_default(),
196 cursor: None,
197 done: false,
198 }
199 }
200
201 pub async fn next(&mut self) -> crate::Result<Option<PostsResponse>> {
203 if self.done {
204 return Ok(None);
205 }
206
207 let mut opts = self.options.clone();
208 if let Some(ref c) = self.cursor {
209 opts.after = Some(c.clone());
210 }
211
212 let resp = self.client.keyword_search(&self.query, Some(&opts)).await?;
213
214 if let Some(c) = next_cursor(&resp.paging) {
215 self.cursor = Some(c);
216 } else {
217 self.done = true;
218 }
219
220 if resp.data.is_empty() {
221 self.done = true;
222 return Ok(None);
223 }
224
225 Ok(Some(resp))
226 }
227
228 pub fn has_next(&self) -> bool {
230 !self.done
231 }
232
233 pub fn reset(&mut self) {
235 self.cursor = None;
236 self.done = false;
237 }
238
239 pub async fn collect_all(&mut self) -> crate::Result<Vec<Post>> {
241 let mut all = Vec::new();
242 while self.has_next() {
243 if let Some(resp) = self.next().await? {
244 all.extend(resp.data);
245 }
246 }
247 Ok(all)
248 }
249}