comment_list_response = get_github(comment_list_url, etag) # If we got a 304, there are no new comments, so we're done with this commit if comment_list_response.status_code == 304: continue # Hopefully the status code is 200 otherwise, but if not bail on this commit if comment_list_response.status_code != 200: print("ERR: Received status code %s from github for %s" % (comment_list_response.status_code, comment_list_url), file=sys.stderr) continue comment_list = comment_list_response.json() # Iterate over the comments and look for the ones not yet emailed for comment in comment_list: if not comment_sent_coll.find_one({'comment.url': comment["url"]}): # Fake a commit_comment event handle_commit_comment({'comment': comment}) comment_sent_coll.insert({'comment': comment, 'last_sent': time.time()}) # Insert or update the comment list record if record: record['etag'] = comment_list_response.headers['etag'] record['comment_list'] = comment_list commit_comment_coll.save(record) else: commit_comment_coll.insert({'comment_list_url': comment_list_url, 'etag': comment_list_response.headers['etag'], 'comment_list': comment_list})
def application(environ, start_response): """ Entry point for mod_wsgi """ # We always respond with text/plain no matter what, so set that response_headers = [('Content-Type', 'text/plain')] # Check that all the necessary environment variables are set if 'GHEH_SMTP_SERVER' not in os.environ or \ 'GHEH_EMAIL_TO' not in os.environ or \ 'GHEH_EMAIL_FROM' not in os.environ or \ 'GHEH_DB_ENVVAR' not in os.environ or \ os.environ['GHEH_DB_ENVVAR'] not in os.environ or \ 'GHEH_DB_NAME' not in os.environ: print("Missing required environment variables", file=environ['wsgi.errors']) start_response('500 Internal Server Error', response_headers) return [b'Service not properly configured, please check that all mandatory environment variables are set'] # Check that this request is the right kind of thing: a POST of type # application/json with a known length if environ['REQUEST_METHOD'] != 'POST': start_response('405 Method Not Allowed', response_headers) return [b'Only POST messages are accepted'] if 'CONTENT_TYPE' not in environ or environ['CONTENT_TYPE'] != 'application/json': print("Invalid content-type %s" % environ.get('CONTENT_TYPE', None), file=environ['wsgi.errors']) start_response('415 Unsupported Media Type', response_headers) return [b'Requests must be of type application/json'] try: content_length = int(environ['CONTENT_LENGTH']) except (KeyError, ValueError): start_response('411 Length required', response_headers) return [b'Invalid content length'] # Look for the github headers if 'HTTP_X_GITHUB_EVENT' not in environ: print("Missing X-Github-Event", file=environ['wsgi.errors']) start_response('400 Bad Request', response_headers) return [b'Invalid event type'] event_type = environ['HTTP_X_GITHUB_EVENT'] # Read the post data # Errors will be automatically converted to a 500 post_data = environ['wsgi.input'].read(content_length) # If a secret was set, validate the post data if 'GHEH_GITHUB_SECRET' in os.environ: if 'HTTP_X_HUB_SIGNATURE' not in environ: print("Missing signature", file=environ['wsgi.errors']) start_response('401 Unauthorized', response_headers) return [b'Missing signature'] # Only sha1 is used currently if not environ['HTTP_X_HUB_SIGNATURE'].startswith('sha1='): print("Signature not sha1", file=environ['wsgi.errors']) start_response('401 Unauthorized', response_headers) return [b'Invalid signature'] digester = hmac.new(os.environ['GHEH_GITHUB_SECRET'].encode('utf-8'), msg=post_data, digestmod=hashlib.sha1) if 'sha1=' + digester.hexdigest() != environ['HTTP_X_HUB_SIGNATURE']: print("Signature mismatch", file=environ['wsgi.errors']) start_response('401 Unauthorized', response_headers) return [b'Invalid signature'] # Convert the post data to a string so we can start actually using it # JSON is required to be in utf-8, utf-16, or utf-32, but github only ever # uses utf-8, praise be, so just go ahead and assume that try: post_str = post_data.decode('utf-8') except UnicodeDecodeError: print("Unable to decode JSON", file=environ['wsgi.errors']) start_response('400 Bad Request', response_headers) return [b'Invalid data'] # Parse the post data try: event_data = json.loads(post_str) except ValueError: print("Unable to parse JSON", file=environ['wsgi.errors']) start_response('400 Bad Request', response_headers) return [b'Invalid data'] # Done with parsing the request, dispatch the data to the event handler if event_type == "pull_request": handle_pull_request(event_data) elif event_type == "issue_comment": handle_issue_comment(event_data) elif event_type == "pull_request_review_comment": handle_pull_request_review_comment(event_data) elif event_type == "commit_comment": handle_commit_comment(event_data) start_response('200 OK', response_headers) return [b'']