func (gc *Client) ParseHook(body []byte, event string) (*scm.Hook, error) {
	payload := new(PushHook)
	if err := json.Unmarshal(body, payload); err != nil {
		return nil, err
	}
	hook := &scm.Hook{
		Author:   payload.Sender.Login,
		Branch:   strings.Replace(payload.Ref, "refs/heads/", "", -1),
		CloneURL: payload.Repo.CloneURL,
		Commit:   payload.Head.ID,
		Event:    event,
	}
	return hook, nil
}
ParseHook parses the contents of a webhook to build useful data
package github
import (
	"bytes"
	"fmt"
	"reflect"
	"strings"
	"encoding/json"
	"github.com/Sirupsen/logrus"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"github.com/AcalephStorage/kontinuous/scm"
)
type Client struct {
	token string
}
func (gc *Client) client() *github.Client {
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: gc.token},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	return github.NewClient(tc)
}
func (gc *Client) CreateHook(owner, repo, callback string, events []string) error {
	hook := &github.Hook{
		Events: events,
		Name:   github.String("web"),
		Config: map[string]interface{}{
			"url":          callback,
			"content_type": "json",
		},
	}
	if _, _, err := gc.client().Repositories.CreateHook(owner, repo, hook); err != nil {
		return err
	}
	return nil
}
func (gc *Client) CreateKey(owner, repo, key, title string) error {
	deployKey := &github.Key{
		Key:   github.String(key),
		Title: github.String(title),
	}
	if _, _, err := gc.client().Repositories.CreateKey(owner, repo, deployKey); err != nil {
		return err
	}
	return nil
}
func (gc *Client) CreateStatus(owner, repo, ref string, stageID int, stageName, state string) error {
	context := fmt.Sprintf("kontinuous:%d", stageID)
	status := &github.RepoStatus{
		State:       &state,
		Description: &stageName,
		Context:     &context,
	}
	if _, _, err := gc.client().Repositories.CreateStatus(owner, repo, ref, status); err != nil {
		return err
	}
	return nil
}
func (gc *Client) GetFileContent(owner, repo, path, ref string) ([]byte, bool) {
	file, _, _, err := gc.client().Repositories.GetContents(owner,
		repo,
		path,
		&github.RepositoryContentGetOptions{ref})
	if err != nil {
		return nil, false
	}
	decoded, err := file.Decode()
	if err != nil {
		return nil, false
	}
	return decoded, true
}
func (gc *Client) GetContents(owner, repo, path, ref string) (*scm.RepositoryContent, bool) {
	file, _, _, err := gc.client().Repositories.GetContents(owner,
		repo,
		path,
		&github.RepositoryContentGetOptions{ref})
	if err != nil {
		return nil, false
	}
	return &scm.RepositoryContent{
		Content: file.Content,
		SHA:     file.SHA,
	}, true
}
func (gc *Client) GetDirectoryContent(owner, repo, path, ref string) ([]interface{}, bool) {
	_, dircontents, _, err := gc.client().Repositories.GetContents(owner,
		repo,
		path,
		&github.RepositoryContentGetOptions{ref})
	if err != nil || len(dircontents) == 0 {
		return nil, false
	}
	contents := make([]interface{}, 0)
	for _, content := range dircontents {
		buf := bytes.Buffer{}
		val := reflect.ValueOf(content.Path)
		v := reflect.Indirect(val)
		fmt.Fprintf(&buf, `%s`, v)
		contentPath := buf.String()
		decoded, ok := gc.GetFileContent(owner, repo, contentPath, ref)
		if !ok {
			continue
		}
		contents = append(contents, decoded)
	}
	return contents, true
}
func (gc *Client) CreateFile(owner, repo, path, message, branch string, content []byte) (*scm.RepositoryContent, error) {
	if len(message) == 0 {
		message = fmt.Sprintf("Create %s", path)
	}
	resp, _, err := gc.client().Repositories.CreateFile(owner,
		repo,
		path,
		&github.RepositoryContentFileOptions{
			Message: &message,
			Content: content,
			Branch:  &branch,
		})
	if err != nil {
		return nil, err
	}
	return &scm.RepositoryContent{SHA: resp.Content.SHA}, nil
}
func (gc *Client) UpdateFile(owner, repo, path, blob, message, branch string, content []byte) (*scm.RepositoryContent, error) {
	if len(message) == 0 {
		message = fmt.Sprintf("Update %s", path)
	}
	resp, _, err := gc.client().Repositories.UpdateFile(owner,
		repo,
		path,
		&github.RepositoryContentFileOptions{
			Message: &message,
			Content: content,
			SHA:     &blob,
			Branch:  &branch,
		})
	if err != nil {
		return nil, err
	}
	return &scm.RepositoryContent{SHA: resp.Content.SHA}, nil
}
func (gc *Client) GetRepository(owner, name string) (*scm.Repository, bool) {
	data, _, err := gc.client().Repositories.Get(owner, name)
	if err != nil {
		return nil, false
	}
	repo := &scm.Repository{
		ID:            *data.ID,
		Owner:         *data.Owner.Login,
		Name:          *data.Name,
		FullName:      *data.FullName,
		Avatar:        *data.Owner.AvatarURL,
		CloneURL:      *data.CloneURL,
		Permissions:   *data.Permissions,
		DefaultBranch: *data.DefaultBranch,
	}
	return repo, true
}
func (gc *Client) ListRepositories(user string) (repos []*scm.Repository, err error) {
	opts := new(github.RepositoryListOptions)
	opts.PerPage = 100
	opts.Page = 1
	for opts.Page > 0 {
		list, res, err := gc.client().Repositories.List(user, opts)
		if err != nil {
			return nil, err
		}
		for _, repo := range list {
			repos = append(repos, &scm.Repository{
				ID:            *repo.ID,
				Owner:         *repo.Owner.Login,
				Name:          *repo.Name,
				FullName:      *repo.FullName,
				Avatar:        *repo.Owner.AvatarURL,
				DefaultBranch: *repo.DefaultBranch,
			})
		}
		opts.Page = res.NextPage
	}
	return repos, nil
}