extern crate serde_json;
use std::collections::HashMap;
use futures::future;
use hyper::client::connect::Connect;
use url::form_urlencoded;
use users::User;
use Future;
use Github;
pub struct Notifications<C>
where
C: Clone + Connect + 'static,
{
github: Github<C>,
}
impl<C: Clone + Connect + 'static> Notifications<C> {
#[doc(hidden)]
pub fn new(github: Github<C>) -> Self {
Self { github }
}
pub fn list(&self, options: &ThreadListOptions) -> Future<Vec<Thread>> {
let mut uri = vec!["/notifications".into()];
if let Some(query) = options.serialize() {
uri.push(query);
}
self.github.get(&uri.join("?"))
}
pub fn list_for_repo<O, R>(
&self,
owner: O,
repo: R,
options: &ThreadListOptions,
) -> Future<Vec<Thread>>
where
O: Into<String>,
R: Into<String>,
{
let mut uri = vec![format!(
"/repos/{}/{}/notifications",
owner.into(),
repo.into()
)];
if let Some(query) = options.serialize() {
uri.push(query);
}
self.github.get(&uri.join("?"))
}
pub fn mark_as_read<S>(&self, last_read_at: S) -> Future<()>
where
S: Into<Option<String>>,
{
let url = match last_read_at.into() {
Some(last_read_at) => format!(
"/notifications?{}",
form_urlencoded::Serializer::new(String::new())
.append_pair("last_read_at", &last_read_at)
.finish()
),
None => String::from("/notifications"),
};
self.github.put_no_response(&url, Vec::new())
}
pub fn mark_as_read_for_repo<O, R, S>(&self, owner: O, repo: R, last_read_at: S) -> Future<()>
where
O: Into<String>,
R: Into<String>,
S: Into<Option<String>>,
{
let path = match last_read_at.into() {
Some(last_read_at) => format!(
"/notifications?{}",
form_urlencoded::Serializer::new(String::new())
.append_pair("last_read_at", &last_read_at)
.finish()
),
None => String::from("/notifications"),
};
self.github.put_no_response(
&format!("/repos/{}/{}{}", owner.into(), repo.into(), path),
Vec::new(),
)
}
pub fn get_thread<S>(&self, id: S) -> Future<Thread>
where
S: Into<String>,
{
self.github
.get(&format!("/notifications/threads/{}", id.into()))
}
pub fn mark_thread_as_read<S>(&self, id: S) -> Future<()>
where
S: Into<String>,
{
self.github
.patch_no_response(&format!("/notifications/threads/{}", id.into()), Vec::new())
}
pub fn get_subscription<S>(&self, id: S) -> Future<Subscription>
where
S: Into<String>,
{
self.github.get(&format!(
"/notifications/threads/{}/subscription",
id.into(),
))
}
pub fn subscribe<S>(&self, id: S) -> Future<Subscription>
where
S: Into<String>,
{
let mut map = HashMap::new();
map.insert("subscribed", true);
self.github.put(
&format!("/notifications/threads/{}/subscription", id.into()),
json!(map),
)
}
pub fn unsubscribe<S>(&self, id: S) -> Future<Subscription>
where
S: Into<String>,
{
let mut map = HashMap::new();
map.insert("ignored", true);
self.github.put(
&format!("/notifications/threads/{}/subscription", id.into()),
json!(map),
)
}
pub fn delete_subscription<S>(&self, id: S) -> Future<()>
where
S: Into<String>,
{
self.github.delete(&format!(
"/notifications/threads/{}/subscription",
id.into()
))
}
}
#[derive(Debug, Deserialize)]
pub struct Thread {
pub id: String,
pub unread: bool,
pub updated_at: String,
pub last_read_at: Option<String>,
pub reason: String,
pub subject: Subject,
pub repository: Repository,
pub url: String,
pub subscription_url: String,
}
#[derive(Default)]
pub struct ThreadListOptions {
params: HashMap<&'static str, String>,
}
impl ThreadListOptions {
pub fn builder() -> ThreadListOptionsBuilder {
ThreadListOptionsBuilder::default()
}
pub fn serialize(&self) -> Option<String> {
if self.params.is_empty() {
None
} else {
let encoded: String = form_urlencoded::Serializer::new(String::new())
.extend_pairs(&self.params)
.finish();
Some(encoded)
}
}
}
#[derive(Default)]
pub struct ThreadListOptionsBuilder(ThreadListOptions);
impl ThreadListOptionsBuilder {
pub fn all(&mut self, all: bool) -> &mut Self {
self.0.params.insert("all", all.to_string());
self
}
pub fn participating(&mut self, val: bool) -> &mut Self {
self.0.params.insert("participating", val.to_string());
self
}
pub fn since<T>(&mut self, since: T) -> &mut Self
where
T: Into<String>,
{
self.0.params.insert("since", since.into());
self
}
pub fn before<T>(&mut self, before: T) -> &mut Self
where
T: Into<String>,
{
self.0.params.insert("before", before.into());
self
}
pub fn build(&self) -> ThreadListOptions {
ThreadListOptions {
params: self.0.params.clone(),
}
}
}
#[derive(Debug, Deserialize)]
pub struct Subject {
title: String,
url: String,
latest_comment_url: String,
#[serde(rename = "type")]
kind: String,
}
#[derive(Debug, Deserialize)]
pub struct Repository {
pub id: u32,
pub node_id: String,
pub name: String,
pub full_name: String,
pub owner: User,
pub html_url: String,
}
#[derive(Debug, Deserialize)]
pub struct Subscription {
pub subscribed: bool,
pub ignored: bool,
pub reason: String,
pub created_at: String,
pub url: String,
pub thread_url: String,
}