# This file is part of NIT ( http://www.nitlanguage.org ). # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # 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.sha}" # 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. 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: JsonObject): GithubEvent do if kind == "commit_comment" then return new CommitCommentEvent.from_json(api, json) else if kind == "create" then return new CreateEvent.from_json(api, json) else if kind == "delete" then return new DeleteEvent.from_json(api, json) else if kind == "deployment" then return new DeploymentEvent.from_json(api, json) else if kind == "deployment_status" then return new DeploymentStatusEvent.from_json(api, json) else if kind == "fork" then return new ForkEvent.from_json(api, json) else if kind == "issues" then return new IssuesEvent.from_json(api, json) else if kind == "issue_comment" then return new IssueCommentEvent.from_json(api, json) else if kind == "member" then return new MemberEvent.from_json(api, json) else if kind == "pull_request" then return new PullRequestEvent.from_json(api, json) else if kind == "pull_request_review_comment" then return new PullRequestReviewCommentEvent.from_json(api, json) else if kind == "push" then return new PushEvent.from_json(api, json) else if kind == "status" then return new StatusEvent.from_json(api, json) else return new GithubEvent.from_json(api, json) end 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) # get POST object var obj = request.body.parse_json if not obj isa JsonObject then return new HttpResponse(403) # parse event var event = listener.event_factory(kind, obj) listener.apply_event(event) return new HttpResponse(200) end end