<s> import collections <EOL> import hashlib <EOL> import hmac <EOL> import logging <EOL> from flask import abort , request <EOL> class Webhook ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , app , endpoint = '<STR_LIT>' , secret = None ) : <EOL> app . add_url_rule ( endpoint , view_func = self . _postreceive , <EOL> methods = [ '<STR_LIT:POST>' ] ) <EOL> self . _hooks = collections . defaultdict ( list ) <EOL> self . _logger = logging . getLogger ( '<STR_LIT>' ) <EOL> self . _secret = secret <EOL> def hook ( self , event_type = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> def decorator ( func ) : <EOL> self . _hooks [ event_type ] . append ( func ) <EOL> return func <EOL> return decorator <EOL> def _get_digest ( self ) : <EOL> """<STR_LIT>""" <EOL> return hmac . new ( <EOL> self . _secret , request . data , hashlib . sha1 ) . hexdigest ( ) if self . _secret else None <EOL> def _postreceive ( self ) : <EOL> """<STR_LIT>""" <EOL> digest = self . _get_digest ( ) <EOL> if digest is not None : <EOL> sig_parts = _get_header ( '<STR_LIT>' ) . split ( '<STR_LIT:=>' , <NUM_LIT:1> ) <EOL> if ( len ( sig_parts ) < <NUM_LIT:2> or sig_parts [ <NUM_LIT:0> ] != '<STR_LIT>' <EOL> or not hmac . compare_digest ( sig_parts [ <NUM_LIT:1> ] , unicode ( digest ) ) ) : <EOL> abort ( <NUM_LIT> , '<STR_LIT>' ) <EOL> event_type = _get_header ( '<STR_LIT>' ) <EOL> data = request . get_json ( ) <EOL> if data is None : <EOL> abort ( <NUM_LIT> , '<STR_LIT>' ) <EOL> self . _logger . info ( <EOL> '<STR_LIT>' , _format_event ( event_type , data ) , _get_header ( '<STR_LIT>' ) ) <EOL> for hook in self . _hooks . get ( event_type , [ ] ) : <EOL> hook ( data ) <EOL> return '<STR_LIT>' , <NUM_LIT> <EOL> def _get_header ( key ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> return request . headers [ key ] <EOL> except KeyError : <EOL> abort ( <NUM_LIT> , '<STR_LIT>' + key ) <EOL> EVENT_DESCRIPTIONS = { <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT:status>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> } <EOL> def _format_event ( event_type , data ) : <EOL> try : <EOL> return EVENT_DESCRIPTIONS [ event_type ] . format ( ** data ) <EOL> except KeyError : <EOL> return event_type </s>
