Github hook event listening with nitcorn.

Usage:

import github::hooks

# A simple hook listener that print received events in stdout.
class LogHookListener
   super HookListener

   # Use double dispatch to implement log behavior.
   redef fun apply_event(event) do event.log_event(self)
end

redef class GithubEvent
   # Log this event.
   #
   # Do nothing by default.
   fun log_event(l: LogHookListener) do end
end

redef class CommitCommentEvent

   redef fun log_event(l) do
       print "new comment on commit {comment.commit_id}"
   end
end

var api = new GithubAPI(get_github_oauth)
var listener = new LogHookListener(api, "127.0.0.1", 8080)

Introduced classes

abstract class HookListener

github :: HookListener

A nitcorn listener for Github hooks.

All class definitions

abstract class HookListener

github $ HookListener

A nitcorn listener for Github hooks.
package_diagram github::hooks hooks github::events events github::hooks->github::events nitcorn nitcorn github::hooks->nitcorn github::api api github::events->github::api ...github::api ... ...github::api->github::api ...nitcorn ... ...nitcorn->nitcorn a_star-m a_star-m a_star-m->github::hooks

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module api

github :: api

Nit object oriented interface to Github api.
module array

core :: array

This module introduces the standard array structure.
module base64

base64 :: base64

Offers the base 64 encoding and decoding algorithms
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module curl

curl :: curl

Data transfer powered by the native curl library
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

json :: error

Intro JsonParseError which is exposed by all JSON reading APIs
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module file_server

nitcorn :: file_server

Provides the FileServer action, which is a standard and minimal file server
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module http_errors

nitcorn :: http_errors

Offers ErrorTemplate to display error pages
module http_request

nitcorn :: http_request

Provides the HttpRequest class and services to create it
module http_request_buffer

nitcorn :: http_request_buffer

Http request parsing for buffered inputs.
module http_response

nitcorn :: http_response

Provides the HttpResponse class and http_status_codes
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module json

json :: json

Read and write JSON formatted text using the standard serialization services
module kernel

core :: kernel

Most basic classes and methods.
module libevent

libevent :: libevent

Low-level wrapper around the libevent library to manage events on file descriptors
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module md5

md5 :: md5

Native MD5 digest implementation as Text::md5
module media_types

nitcorn :: media_types

Services to identify Internet media types (or MIME types, Content-types)
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module native

core :: native

Native structures for text and bytes
module native_curl

curl :: native_curl

Binding of C libCurl which allow us to interact with network.
module numeric

core :: numeric

Advanced services for Numeric types
module parser_base

parser_base :: parser_base

Simple base for hand-made parsers of all kinds
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module reactor

nitcorn :: reactor

Core of the nitcorn project, provides HttpFactory and Action
module ropes

core :: ropes

Tree-based representation of a String.
module safe

serialization :: safe

Services for safer deserialization engines
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module serialization_read

json :: serialization_read

Services to read JSON: deserialize_json and JsonDeserializer
module serialization_write

json :: serialization_write

Services to write Nit objects to JSON strings: serialize_to_json and JsonSerializer
module server_config

nitcorn :: server_config

Classes and services to configure the server
module sessions

nitcorn :: sessions

Automated session management
module signal_handler

nitcorn :: signal_handler

Handle SIGINT and SIGTERM to close the server after all active events
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module static

json :: static

Static interface to read Nit objects from JSON strings
module stream

core :: stream

Input and output streams of characters
module template

template :: template

Basic template system
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module token

nitcorn :: token

Simple generate_token service, independent of the rest of the nitcorn framework
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O
module vararg_routes

nitcorn :: vararg_routes

Routes with parameters.

Parents

module events

github :: events

Events are emitted by Github Hooks.
module nitcorn

nitcorn :: nitcorn

The nitcorn Web server framework creates server-side Web apps in Nit

Children

module a_star-m

a_star-m

# Github hook event listening with `nitcorn`.
#
# Usage:
#
# ~~~
# import github::hooks
#
# # A simple hook listener that print received events in stdout.
# class LogHookListener
#    super HookListener
#
#    # Use double dispatch to implement log behavior.
#    redef fun apply_event(event) do event.log_event(self)
# end
#
# redef class GithubEvent
#    # Log this event.
#    #
#    # Do nothing by default.
#    fun log_event(l: LogHookListener) do end
# end
#
# redef class CommitCommentEvent
#
#    redef fun log_event(l) do
#        print "new comment on commit {comment.commit_id}"
#    end
# end
#
# var api = new GithubAPI(get_github_oauth)
# var listener = new LogHookListener(api, "127.0.0.1", 8080)
# # listener.listen # uncomment to start listening
# ~~~
module hooks

import events
import nitcorn

# A nitcorn listener for Github hooks.
abstract class HookListener

	# Api client used to perform Github API requests.
	var api: GithubAPI

	# Host to listen.
	var host: String

	# Port to listen.
	var port: Int

	# VirtualHost listened
	private var vh: VirtualHost is noinit

	init do
		vh = new VirtualHost("{host}:{port}")
		vh.routes.add new Route("/", new HookAction(self))
	end

	# Verbosity level (0: quiet, 1: debug).
	# Default: 0
	var verbosity = 0

	# Print `message` if `lvl` <= `verbosity`
	fun message(lvl: Int, message: String) do
		if lvl <= verbosity then print message
	end

	# Start listening and responding to event.
	fun listen do
		message(1, "Hook listening on {host}:{port}")
		var factory = new HttpFactory.and_libevent
		factory.config.virtual_hosts.add vh
		factory.run
	end

	# How to build events from received json objects.
	fun event_factory(kind: String, json: String): nullable GithubEvent do
		if kind == "commit_comment" then
			return api.deserialize(json).as(CommitCommentEvent)
		else if kind == "create" then
			return api.deserialize(json).as(CreateEvent)
		else if kind == "delete" then
			return api.deserialize(json).as(DeleteEvent)
		else if kind == "deployment" then
			return api.deserialize(json).as(DeploymentEvent)
		else if kind == "deployment_status" then
			return api.deserialize(json).as(DeploymentStatusEvent)
		else if kind == "fork" then
			return api.deserialize(json).as(ForkEvent)
		else if kind == "issues" then
			return api.deserialize(json).as(IssuesEvent)
		else if kind == "issue_comment" then
			return api.deserialize(json).as(IssueCommentEvent)
		else if kind == "member" then
			return api.deserialize(json).as(MemberEvent)
		else if kind == "pull_request" then
			return api.deserialize(json).as(PullRequestEvent)
		else if kind == "pull_request_review_comment" then
			return api.deserialize(json).as(PullRequestPullCommentEvent)
		else if kind == "push" then
			return api.deserialize(json).as(PushEvent)
		else if kind == "status" then
			return api.deserialize(json).as(StatusEvent)
		end
		return null
	end

	# What to do when we receive an event from a hook?
	fun apply_event(event: GithubEvent) is abstract
end

# A nitcorn action dedicated to GitHub hook listening.
private class HookAction
	super Action

	# Listener that contains this action.
	#
	# The `listener` is used for its `event_factory` method
	# and the `apply_event`.
	var listener: HookListener

	# Parse hook request then call `listener.apply_event`.
	redef fun answer(request, uri) do
		# get event type
		var kind = request.header.get_or_null("X-GitHub-Event")
		if kind == null then return new HttpResponse(403)
		# parse event
		var event = listener.event_factory(kind, request.body)
		if event == null then return new HttpResponse(403)
		listener.apply_event(event)
		return new HttpResponse(200)
	end
end
lib/github/hooks.nit:15,1--147,3