use crate::error::HttpSnafu;
use crate::models::activity::Notification;
use crate::models::activity::ThreadSubscription;
use crate::models::{NotificationId, ThreadId};
use crate::Octocrab;
use crate::Page;
use http::Uri;
use snafu::ResultExt;
type DateTime = chrono::DateTime<chrono::Utc>;
pub struct NotificationsHandler<'octo> {
crab: &'octo Octocrab,
}
impl<'octo> NotificationsHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab) -> Self {
Self { crab }
}
pub async fn get(&self, id: NotificationId) -> crate::Result<Notification> {
let route = format!("/notifications/threads/{id}");
self.crab.get(route, None::<&()>).await
}
pub async fn mark_as_read(&self, id: NotificationId) -> crate::Result<()> {
let route = format!("/notifications/threads/{id}");
let uri = Uri::builder()
.path_and_query(route)
.build()
.context(HttpSnafu)?;
let response = self.crab._patch(uri, None::<&()>).await?;
crate::map_github_error(response).await.map(drop)
}
pub async fn mark_repo_as_read(
&self,
owner: impl AsRef<str>,
repo: impl AsRef<str>,
last_read_at: impl Into<Option<DateTime>>,
) -> crate::Result<()> {
#[derive(serde::Serialize)]
struct Inner {
last_read_at: DateTime,
}
let body = last_read_at
.into()
.map(|last_read_at| Inner { last_read_at });
let route = format!("/repos/{}/{}/notifications", owner.as_ref(), repo.as_ref());
let uri = Uri::builder()
.path_and_query(route)
.build()
.context(HttpSnafu)?;
let response = self.crab._put(uri, body.as_ref()).await?;
crate::map_github_error(response).await.map(drop)
}
pub async fn mark_all_as_read(
&self,
last_read_at: impl Into<Option<DateTime>>,
) -> crate::Result<()> {
#[derive(serde::Serialize)]
struct Inner {
last_read_at: DateTime,
}
let body = last_read_at
.into()
.map(|last_read_at| Inner { last_read_at });
let uri = Uri::builder()
.path_and_query("/notifications")
.build()
.context(HttpSnafu)?;
let response = self.crab._put(uri, body.as_ref()).await?;
crate::map_github_error(response).await.map(drop)
}
pub async fn get_thread_subscription(
&self,
thread: ThreadId,
) -> crate::Result<ThreadSubscription> {
let route = format!("/notifications/threads/{thread}/subscription");
self.crab.get(route, None::<&()>).await
}
pub async fn set_thread_subscription(
&self,
thread: ThreadId,
ignored: bool,
) -> crate::Result<ThreadSubscription> {
#[derive(serde::Serialize)]
struct Inner {
ignored: bool,
}
let route = format!("/notifications/threads/{thread}/subscription");
let body = Inner { ignored };
self.crab.put(route, Some(&body)).await
}
pub async fn delete_thread_subscription(&self, thread: ThreadId) -> crate::Result<()> {
let route = format!("/notifications/threads/{thread}/subscription");
let uri = Uri::builder()
.path_and_query(route)
.build()
.context(HttpSnafu)?;
let response = self.crab._delete(uri, None::<&()>).await?;
crate::map_github_error(response).await.map(drop)
}
pub fn list_for_repo(
&self,
owner: impl AsRef<str>,
repo: impl AsRef<str>,
) -> ListNotificationsBuilder<'octo> {
let route = format!("/repos/{}/{}/notifications", owner.as_ref(), repo.as_ref());
ListNotificationsBuilder::new(self.crab, route)
}
pub fn list(&self) -> ListNotificationsBuilder<'octo> {
ListNotificationsBuilder::new(self.crab, "/notifications".to_string())
}
}
#[derive(serde::Serialize)]
pub struct ListNotificationsBuilder<'octo> {
#[serde(skip)]
url: String,
#[serde(skip)]
crab: &'octo Octocrab,
#[serde(skip_serializing_if = "Option::is_none")]
all: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
participating: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
since: Option<chrono::DateTime<chrono::Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
before: Option<chrono::DateTime<chrono::Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u8>,
}
impl<'octo> ListNotificationsBuilder<'octo> {
fn new(crab: &'octo Octocrab, url: String) -> Self {
Self {
url,
crab,
all: None,
participating: None,
since: None,
before: None,
per_page: None,
page: None,
}
}
pub fn all(mut self, v: bool) -> Self {
self.all = Some(v);
self
}
pub fn participating(mut self, v: bool) -> Self {
self.participating = Some(v);
self
}
pub fn since(mut self, since: chrono::DateTime<chrono::Utc>) -> Self {
self.since = Some(since);
self
}
pub fn before(mut self, before: chrono::DateTime<chrono::Utc>) -> Self {
self.before = Some(before);
self
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}
pub fn page(mut self, page: impl Into<u8>) -> Self {
self.page = Some(page.into());
self
}
pub async fn send(self) -> crate::Result<Page<Notification>> {
self.crab.get(&self.url, Some(&self)).await
}
}