<commit_before>//! Afterparty is a github webhook handler library for building custom integrations

#[macro_use]
extern crate log;
#[macro_use]
extern crate hyper;
extern crate crypto;
extern crate serde;
extern crate serde_json;

mod hook;
mod events;

pub use events::Event;
pub use hook::{AuthenticateHook, Hook};
use hyper::server::{Handler, Request, Response};
use std::collections::HashMap;
use std::io::Read;


/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

/// A delivery encodes all information about web hook request
#[derive(Debug)]
pub struct Delivery<'a> {
    pub id: &'a str,
    pub event: &'a str,
    pub payload: Event,
    pub unparsed_payload: &'a str,
    pub signature: Option<&'a str>,
}

impl<'a> Delivery<'a> {
    pub fn new(id: &'a str,
               event: &'a str,
               payload: &'a str,
               signature: Option<&'a str>)
               -> Option<Delivery<'a>> {
        match serde_json::from_str::<Event>(&payload) {
            Ok(parsed) => {
                Some(Delivery {
                    id: id,
                    event: event,
                    payload: parsed,
                    unparsed_payload: payload,
                    signature: signature,
                })
            }
            _ => None,
        }
    }
}

/// A hub is a registry of hooks
#[derive(Default)]
pub struct Hub {
    hooks: HashMap<String, Vec<Box<Hook>>>,
}

impl Hub {
    /// construct a new hub instance
    pub fn new() -> Hub {
        Hub { ..Default::default() }
    }

    /// adds a new web hook which will only be applied
    /// when a delivery is revcieved with a valid
    /// request signature
    pub fn handle_authenticated<H, S>(&mut self, event: &str, secret: S, hook: H)
        where H: Hook + 'static,
              S: Into<String>
    {
        self.handle(event, AuthenticateHook::new(secret, hook))
    }

    /// add a need hook to list of hooks
    /// interested in a given event
    pub fn handle<H>(&mut self, event: &str, hook: H)
        where H: Hook + 'static
    {
        self.hooks
            .entry(event.to_owned())
            .or_insert(vec![])
            .push(Box::new(hook));
    }

    /// get all interested hooks for a given event
    pub fn hooks(&self, event: &str) -> Option<Vec<&Box<Hook>>> {
        let explicit = self.hooks.get(event);
        let implicit = self.hooks.get("*");
        let combined = match (explicit, implicit) {
            (Some(ex), Some(im)) => {
                Some(ex.iter().chain(im.iter()).into_iter().collect::<Vec<_>>())
            }
            (Some(ex), _) => Some(ex.into_iter().collect::<Vec<_>>()),
            (_, Some(im)) => Some(im.into_iter().collect::<Vec<_>>()),
            _ => None,
        };
        combined

    }

    /// serially handles delivery by applying each
    /// interested hook
    pub fn deliver(&self, delivery: &Delivery) {
        if let Some(hooks) = self.hooks(delivery.event) {
            for hook in hooks {
                hook.handle(&delivery)
            }<commit_msg>spacing<commit_after>//! Afterparty is a github webhook handler library for building custom integrations

#[macro_use]
extern crate log;
#[macro_use]
extern crate hyper;
extern crate crypto;
extern crate serde;
extern crate serde_json;

mod hook;
mod events;

pub use events::Event;
pub use hook::{AuthenticateHook, Hook};
use hyper::server::{Handler, Request, Response};
use std::collections::HashMap;
use std::io::Read;

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

/// A delivery encodes all information about web hook request
#[derive(Debug)]
pub struct Delivery<'a> {
    pub id: &'a str,
    pub event: &'a str,
    pub payload: Event,
    pub unparsed_payload: &'a str,
    pub signature: Option<&'a str>,
}

impl<'a> Delivery<'a> {
    pub fn new(id: &'a str,
               event: &'a str,
               payload: &'a str,
               signature: Option<&'a str>)
               -> Option<Delivery<'a>> {
        match serde_json::from_str::<Event>(&payload) {
            Ok(parsed) => {
                Some(Delivery {
                    id: id,
                    event: event,
                    payload: parsed,
                    unparsed_payload: payload,
                    signature: signature,
                })
            }
            _ => None,
        }
    }
}

/// A hub is a registry of hooks
#[derive(Default)]
pub struct Hub {
    hooks: HashMap<String, Vec<Box<Hook>>>,
}

impl Hub {
    /// construct a new hub instance
    pub fn new() -> Hub {
        Hub { ..Default::default() }
    }

    /// adds a new web hook which will only be applied
    /// when a delivery is revcieved with a valid
    /// request signature
    pub fn handle_authenticated<H, S>(&mut self, event: &str, secret: S, hook: H)
        where H: Hook + 'static,
              S: Into<String>
    {
        self.handle(event, AuthenticateHook::new(secret, hook))
    }

    /// add a need hook to list of hooks
    /// interested in a given event
    pub fn handle<H>(&mut self, event: &str, hook: H)
        where H: Hook + 'static
    {
        self.hooks
            .entry(event.to_owned())
            .or_insert(vec![])
            .push(Box::new(hook));
    }

    /// get all interested hooks for a given event
    pub fn hooks(&self, event: &str) -> Option<Vec<&Box<Hook>>> {
        let explicit = self.hooks.get(event);
        let implicit = self.hooks.get("*");
        let combined = match (explicit, implicit) {
            (Some(ex), Some(im)) => {
                Some(ex.iter().chain(im.iter()).into_iter().collect::<Vec<_>>())
            }
            (Some(ex), _) => Some(ex.into_iter().collect::<Vec<_>>()),
            (_, Some(im)) => Some(im.into_iter().collect::<Vec<_>>()),
            _ => None,
        };
        combined
    }

    /// serially handles delivery by applying each
    /// interested hook
    pub fn deliver(&self, delivery: &Delivery) {
        if let Some(hooks) = self.hooks(delivery.event) {
            for hook in hooks {
                hook.handle(&delivery)
            }
{'fraction_non_alphanumeric': 0.14530659691950015, 'fraction_numerical': 0.0, 'mean_word_length': 2.153000458085204, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 73, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1291505', 'n_tokens_mistral': 2070, 'n_tokens_neox': 2053, 'n_words': 600}