100 lines
2.2 KiB
Rust
100 lines
2.2 KiB
Rust
use crate::{error::AnyError, session::Session};
|
|
use reqwest::{header::LINK, Response};
|
|
|
|
pub(crate) struct NotificationsSince<'a> {
|
|
pub(super) session: &'a Session,
|
|
pub(super) current: Page,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
#[serde(rename_all = "lowercase")]
|
|
enum MentionType {
|
|
Mention,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, serde::Deserialize, serde::Serialize)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub(crate) enum Visibility {
|
|
Public,
|
|
Unlisted,
|
|
Private,
|
|
Direct,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
pub(crate) struct Mention {
|
|
id: String,
|
|
#[serde(rename = "type")]
|
|
_ty: MentionType,
|
|
pub(crate) status: Status,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
pub(crate) struct Status {
|
|
pub(super) id: String,
|
|
content: String,
|
|
pub(super) visibility: Visibility,
|
|
account: Account,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
pub(crate) struct Account {
|
|
acct: String,
|
|
}
|
|
|
|
pub(super) struct Page {
|
|
items: Vec<Mention>,
|
|
prev_link: Option<url::Url>,
|
|
}
|
|
|
|
impl Page {
|
|
pub(super) async fn try_from_response(response: Response) -> Result<Self, AnyError> {
|
|
let prev_link = if let Some(link) = response
|
|
.headers()
|
|
.get(LINK)
|
|
.and_then(|link| link.to_str().ok())
|
|
{
|
|
let links = parse_link_header::parse_with_rel(link)?;
|
|
links.get("prev").and_then(|link| link.raw_uri.parse().ok())
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let items: Vec<Mention> = response.json().await?;
|
|
|
|
Ok(Self { prev_link, items })
|
|
}
|
|
}
|
|
|
|
impl<'a> NotificationsSince<'a> {
|
|
pub(crate) async fn next(&mut self) -> Result<Option<Mention>, AnyError> {
|
|
loop {
|
|
if let Some(item) = self.current.items.pop() {
|
|
return Ok(Some(item));
|
|
}
|
|
|
|
let Some(url) = &self.current.prev_link else { break; };
|
|
|
|
let response = self.session.get(url).send().await?;
|
|
|
|
self.current = Page::try_from_response(response).await?;
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
impl Mention {
|
|
pub(crate) fn id(&self) -> &str {
|
|
&self.id
|
|
}
|
|
|
|
pub(crate) fn content(&self) -> &str {
|
|
&self.status.content
|
|
}
|
|
|
|
pub(crate) fn account(&self) -> &str {
|
|
&self.status.account.acct
|
|
}
|
|
}
|