pub struct Feed {
pub ids: VecDeque<String>, // ids, whether of statuses, accounts or what
pub origin: isize,
+
+ extend_past: Option<HashMap<String, String>>,
+ extend_future: Option<HashMap<String, String>>,
}
pub struct Client {
impl ReqParam for &String {
fn param_value(self) -> String { self.clone() }
}
+impl ReqParam for i32 {
+ fn param_value(self) -> String { self.to_string() }
+}
impl ReqParam for bool {
fn param_value(self) -> String {
match self {
};
let req = match ext {
- FeedExtend::Initial => req,
+ FeedExtend::Initial => req.param("limit", 32),
FeedExtend::Past => if let Some(ref feed) = self.feeds.get(&id) {
- match feed.ids.front() {
- None => req,
- Some(id) => req.param("max_id", id),
+ match feed.extend_past {
+ None => return Ok(false),
+ Some(ref params) => {
+ let mut req = req;
+ for (key, value) in params {
+ req = req.param(key, value);
+ }
+ req
+ }
}
} else { req },
FeedExtend::Future => if let Some(ref feed) = self.feeds.get(&id) {
- match feed.ids.back() {
- None => req,
- Some(id) => req.param("min_id", id),
+ match feed.extend_future {
+ None => return Ok(false),
+ Some(ref params) => {
+ let mut req = req;
+ for (key, value) in params {
+ req = req.param(key, value);
+ }
+ req
+ }
}
} else { req },
};
return Err(ClientError::UrlError(
url.clone(), rspstatus.to_string()));
}
+
+ // Keep the Link: headers after we consume the response, for
+ // use later once we've constructed a Feed
+ let link_headers: Vec<_> = rsp.headers()
+ .get_all(reqwest::header::LINK)
+ .iter().cloned().collect();
+
let body = rsp.text()?;
// Decode the JSON response as a different kind of type
self.feeds.insert(id.clone(), Feed {
ids,
origin: 0,
+ extend_past: None,
+ extend_future: None,
});
}
FeedExtend::Future => {
}
}
+ let feed = self.feeds.get_mut(id).unwrap();
+ for linkhdr in link_headers {
+ let linkhdr_str = match linkhdr.to_str() {
+ Ok(s) => Ok(s),
+ Err(e) => Err(ClientError::UrlError(
+ url.clone(), e.to_string())),
+ }?;
+ let links = match parse_link_header::parse(linkhdr_str) {
+ Ok(links) => Ok(links),
+ Err(e) => Err(ClientError::UrlError(
+ url.clone(), e.to_string())),
+ }?;
+ for (rel, link) in links {
+ match rel.as_deref() {
+ // Oh, you think time flows _that_ way?
+ // Confusingly, the Mastodon protocol considers
+ // "next" to be heading into the past and "prev"
+ // the future.
+ Some("next") => feed.extend_past = Some(link.queries),
+ Some("prev") => feed.extend_future = Some(link.queries),
+ _ => (),
+ }
+ }
+ }
+
Ok(any_new)
}