fursonabot/src/session/notifications.rs
asonix b365973fd2
Some checks failed
continuous-integration/drone/tag Build is failing
fursonabot
2022-12-30 17:27:42 -06:00

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
}
}