extern crate serde_json;
use self::super::{Github, Result};
use std::fmt;
use std::collections::BTreeMap;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum WebHookContentType {
#[serde(rename = "json")]
Json,
#[serde(rename = "form")]
Form,
}
impl Default for WebHookContentType {
fn default() -> WebHookContentType {
WebHookContentType::Form
}
}
impl fmt::Display for WebHookContentType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
match *self {
WebHookContentType::Form => "form",
WebHookContentType::Json => "json",
})
}
}
pub struct Hooks<'a> {
github: &'a Github,
owner: String,
repo: String,
}
impl<'a> Hooks<'a> {
pub fn new<O, R>(github: &'a Github, owner: O, repo: R) -> Hooks<'a>
where O: Into<String>,
R: Into<String>
{
Hooks {
github: github,
owner: owner.into(),
repo: repo.into(),
}
}
pub fn list(&self) -> Result<Vec<Hook>> {
self.github.get(&format!("/repos/{}/{}/hooks", self.owner, self.repo))
}
pub fn create(&self, options: &HookCreateOptions) -> Result<Hook> {
let data = try!(serde_json::to_string(&options));
self.github.post::<Hook>(&format!("/repos/{}/{}/hooks", self.owner, self.repo),
data.as_bytes())
}
pub fn edit(&self, id: u64, options: &HookEditOptions) -> Result<Hook> {
let data = try!(serde_json::to_string(&options));
self.github.patch::<Hook>(&format!("/repos/{}/{}/hooks/{}", self.owner, self.repo, id),
data.as_bytes())
}
pub fn delete(&self, id: u64) -> Result<()> {
self.github.delete(&format!("/repos/{}/{}/hooks/{}", self.owner, self.repo, id))
}
}
#[derive(Debug, Serialize)]
pub struct HookCreateOptions {
name: String,
config: BTreeMap<String, ::serde_json::Value>,
events: Vec<String>,
active: bool,
}
impl HookCreateOptions {
pub fn builder<N>(name: N) -> HookCreateOptionsBuilder
where N: Into<String>
{
HookCreateOptionsBuilder::new(name)
}
pub fn web() -> HookCreateOptionsBuilder {
Self::builder("web")
}
}
#[derive(Default)]
pub struct HookCreateOptionsBuilder {
name: String,
config: BTreeMap<String, ::serde_json::Value>,
events: Vec<String>,
active: bool,
}
impl HookCreateOptionsBuilder {
pub fn new<N>(name: N) -> HookCreateOptionsBuilder
where N: Into<String>
{
HookCreateOptionsBuilder {
name: name.into(),
active: true,
..Default::default()
}
}
pub fn active(&mut self, active: bool) -> &mut Self {
self.active = active;
self
}
pub fn events<E>(&mut self, events: Vec<E>) -> &mut Self
where E: Into<String>
{
self.events = events.into_iter().map(|e| e.into()).collect::<Vec<_>>();
self
}
pub fn url<U>(&mut self, url: U) -> &mut Self
where U: Into<String>
{
self.config_entry("url".to_owned(), ::serde_json::Value::String(url.into()))
}
pub fn content_type(&mut self, content_type: WebHookContentType) -> &mut Self {
self.config_str_entry("content_type", content_type.to_string());
self
}
pub fn secret<S>(&mut self, sec: S) -> &mut Self
where S: Into<String>
{
self.config_str_entry("secret", sec);
self
}
pub fn config_str_entry<K, V>(&mut self, k: K, v: V) -> &mut Self
where K: Into<String>,
V: Into<String>
{
self.config_entry(k.into(), ::serde_json::Value::String(v.into()));
self
}
pub fn config_entry<N>(&mut self, name: N, value: ::serde_json::Value) -> &mut Self
where N: Into<String>
{
self.config.insert(name.into(), value);
self
}
pub fn build(&self) -> HookCreateOptions {
HookCreateOptions {
name: self.name.clone(),
config: self.config.clone(),
events: self.events.clone(),
active: self.active,
}
}
}
#[derive(Debug, Serialize)]
pub struct HookEditOptions {
config: BTreeMap<String, ::serde_json::Value>,
events: Vec<String>,
add_events: Vec<String>,
remove_events: Vec<String>,
active: bool,
}
impl HookEditOptions {
pub fn builder() -> HookEditOptionsBuilder {
HookEditOptionsBuilder::new()
}
}
#[derive(Default)]
pub struct HookEditOptionsBuilder {
config: BTreeMap<String, ::serde_json::Value>,
events: Vec<String>,
add_events: Vec<String>,
remove_events: Vec<String>,
active: bool,
}
impl HookEditOptionsBuilder {
pub fn new() -> HookEditOptionsBuilder {
HookEditOptionsBuilder { ..Default::default() }
}
pub fn active(&mut self, active: bool) -> &mut Self {
self.active = active;
self
}
pub fn events<E>(&mut self, events: Vec<E>) -> &mut Self
where E: Into<String>
{
self.events = events.into_iter().map(|e| e.into()).collect::<Vec<_>>();
self
}
pub fn url<U>(&mut self, url: U) -> &mut Self
where U: Into<String>
{
self.config_entry("url".to_owned(), ::serde_json::Value::String(url.into()))
}
pub fn content_type(&mut self, content_type: WebHookContentType) -> &mut Self {
self.config_str_entry("content_type", content_type.to_string());
self
}
pub fn secret<S>(&mut self, sec: S) -> &mut Self
where S: Into<String>
{
self.config_str_entry("secret", sec);
self
}
pub fn config_str_entry<K, V>(&mut self, k: K, v: V) -> &mut Self
where K: Into<String>,
V: Into<String>
{
self.config_entry(k.into(), ::serde_json::Value::String(v.into()));
self
}
pub fn config_entry<N>(&mut self, name: N, value: ::serde_json::Value) -> &mut Self
where N: Into<String>
{
self.config.insert(name.into(), value);
self
}
pub fn build(&self) -> HookEditOptions {
HookEditOptions {
config: self.config.clone(),
events: self.events.clone(),
add_events: self.add_events.clone(),
remove_events: self.remove_events.clone(),
active: self.active,
}
}
}
#[derive(Debug, Deserialize)]
pub struct Hook {
pub id: u64,
pub url: String,
pub test_url: String,
pub ping_url: String,
pub name: String,
pub events: Vec<String>,
pub config: ::serde_json::Value,
pub created_at: String,
pub updated_at: String,
pub active: bool,
}
impl Hook {
pub fn config_value(&self, name: &str) -> Option<&::serde_json::Value> {
self.config.pointer(&format!("/{}", name))
}
pub fn config_string(&self, name: &str) -> Option<String> {
self.config_value(name).and_then(|value| match *value {
::serde_json::Value::String(ref val) => Some(val.clone()),
_ => None,
})
}
pub fn url(&self) -> Option<String> {
self.config_string("url")
}
pub fn content_type(&self) -> Option<String> {
self.config_string("content_type")
}
}
#[cfg(test)]
mod tests {
use super::WebHookContentType;
#[test]
fn webhook_content_type_display() {
for (ct, expect) in vec![(WebHookContentType::Form, "form"),
(WebHookContentType::Json, "json")] {
assert_eq!(ct.to_string(), expect)
}
}
#[test]
fn webhook_content_type_default() {
let default: WebHookContentType = Default::default();
assert_eq!(default, WebHookContentType::Form)
}
}