From 23900f03500d3dea6fb39cadfb3214efa4fdc28e Mon Sep 17 00:00:00 2001 From: Martin Geno Date: Fri, 9 Jun 2017 10:55:47 +0200 Subject: [PATCH] Init --- .gitignore | 1 + cmd/hook2xmpp/main.go | 59 ++++++++++++++++++++ config/main.go | 46 +++++++++++++++ config_example.conf | 11 ++++ github/main.go | 126 ++++++++++++++++++++++++++++++++++++++++++ xmpp/main.go | 36 ++++++++++++ 6 files changed, 279 insertions(+) create mode 100644 .gitignore create mode 100644 cmd/hook2xmpp/main.go create mode 100644 config/main.go create mode 100644 config_example.conf create mode 100644 github/main.go create mode 100644 xmpp/main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..83274a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.conf diff --git a/cmd/hook2xmpp/main.go b/cmd/hook2xmpp/main.go new file mode 100644 index 0000000..fc3620f --- /dev/null +++ b/cmd/hook2xmpp/main.go @@ -0,0 +1,59 @@ +package main + +import ( + "flag" + "net/http" + "os" + "os/signal" + "syscall" + + "github.com/genofire/golang-lib/log" + "github.com/mattn/go-xmpp" + "github.com/pierrre/githubhook" + + configuration "github.com/genofire/hook2xmpp/config" + "github.com/genofire/hook2xmpp/github" + ownXMPP "github.com/genofire/hook2xmpp/xmpp" +) + +func main() { + configFile := "config.conf" + flag.StringVar(&configFile, "config", configFile, "path of configuration file") + flag.Parse() + + // load config + config := configuration.ReadConfigFile(configFile) + client, err := xmpp.NewClientNoTLS(config.XMPP.Host, config.XMPP.Username, config.XMPP.Password, config.XMPP.Debug) + if err != nil { + log.Log.Panic(err) + } + + log.Log.Infof("Started hock2xmpp with %s", client.JID()) + + client.SendHtml(xmpp.Chat{Remote: config.XMPP.StartupNotify, Type: "chat", Text: "Startup of hock2xmpp"}) + go ownXMPP.Start(client) + + githubHandler := github.NewHandler(client, config.Hooks) + handler := &githubhook.Handler{ + Delivery: githubHandler.Deliviery, + } + http.Handle("/github", handler) + + srv := &http.Server{ + Addr: config.WebserverBind, + } + go func() { + if err := srv.ListenAndServe(); err != nil { + panic(err) + } + }() + + // Wait for system signal + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + sig := <-sigs + + srv.Close() + + log.Log.Info("received", sig) +} diff --git a/config/main.go b/config/main.go new file mode 100644 index 0000000..737f732 --- /dev/null +++ b/config/main.go @@ -0,0 +1,46 @@ +package config + +import ( + "io/ioutil" + + "github.com/BurntSushi/toml" + + "github.com/genofire/golang-lib/log" +) + +type Config struct { + WebserverBind string `toml:"webserver_bind"` + + XMPP struct { + Host string `toml:"host"` + Username string `toml:"username"` + Password string `toml:"password"` + Debug bool `toml:"debug"` + StartupNotify string `toml:"startup_notify"` + } `toml:"xmpp"` + + Hooks []Hook `toml:"hooks"` +} + +type Hook struct { + NotifyUser []string `toml:"notify_user"` + NotifyMuc []string `toml:"notify_muc"` + + Type string `toml:"type"` + Github struct { + Project string `toml:"project"` + } `toml:"github"` +} + +func ReadConfigFile(path string) *Config { + config := &Config{} + file, err := ioutil.ReadFile(path) + if err != nil { + log.Log.Panic(err) + } + if err := toml.Unmarshal(file, config); err != nil { + log.Log.Panic(err) + } + + return config +} diff --git a/config_example.conf b/config_example.conf new file mode 100644 index 0000000..0532c7c --- /dev/null +++ b/config_example.conf @@ -0,0 +1,11 @@ +webserver_bind = ":8080" + +[xmpp] +host = "fireorbit.de" +username = "bot@fireorbit.de" +password = "example" +startup_notify = "geno@fireorbit.de" + +[[github.project]] +repository = "yanic" +notify_user = geno@fireorbit.de diff --git a/github/main.go b/github/main.go new file mode 100644 index 0000000..440ec69 --- /dev/null +++ b/github/main.go @@ -0,0 +1,126 @@ +package github + +import ( + "fmt" + "strings" + + "github.com/genofire/golang-lib/log" + "github.com/genofire/hook2xmpp/config" + xmpp "github.com/mattn/go-xmpp" + + ownXMPP "github.com/genofire/hook2xmpp/xmpp" +) + +type Handler struct { + client *xmpp.Client + hooks map[string]config.Hook +} + +func NewHandler(client *xmpp.Client, newHooks []config.Hook) *Handler { + hooks := make(map[string]config.Hook) + + for _, hook := range newHooks { + if hook.Type == "github" { + hooks[hook.Github.Project] = hook + } + } + return &Handler{ + client: client, + hooks: hooks, + } +} + +func (h *Handler) Deliviery(event string, deliveryID string, payloadOrigin interface{}) { + msg := PayloadToString(event, payloadOrigin) + payload := payloadOrigin.(map[string]interface{}) + repository := payload["repository"].(map[string]interface{}) + repoName := repository["full_name"].(string) + + hook, ok := h.hooks[repoName] + if !ok { + log.Log.Errorf("No hook found for: '%s'", repoName) + return + } + + ownXMPP.Notify(h.client, hook, msg) +} + +var eventMsg = map[string]string{ + "commit_comment_created": "Commit comment", + "status_error": "Commit status: error", + "status_failure": "Commit status: failure", + "status_pending": "Commit status: pending", + "status_success": "Commit status: success", + "create_branch": "Create branch", + "create_tag": "Create tag", + "delete_branch": "Delete branch", + "delete_tag": "Delete tag", + "issue_comment_created": "Issue comment", + "issue_comment_deleted": "Issue comment: deleted", + "issue_comment_edited": "Issue comment: edited", + "issue_assigned": "Issue: assigned", + "issue_closed": "Issue: closed", + "issue_edited": "Issue: edited", + "issue_labeled": "Issue: labeled", + "issue_opened": "Issue: opened", + "issue_reopened": "Issue: reopened", + "issue_unassigned": "Issue: unassigned", + "issue_unlabeled": "Issue: unlabeled", + "pr_review_created": "Pull request review comment", + "pr_review_deleted": "Pull request review comment: deleted", + "pr_review_edited": "Pull request review comment: edited", + "pr_assigned": "Pull request: assigned", + "pr_closed": "Pull request: closed", + "pr_edited": "Pull request: edited", + "pr_labeled": "Pull request: labeled", + "pr_opened": "Pull request: opened", + "pr_reopened": "Pull request: reopened", + "pr_synchronize": "Pull request: synchronize", + "pr_unassigned": "Pull request: unassigned", + "pr_unlabeled": "Pull request: unlabeled", + "push": "Push", + "release_published": "Release published", + "member_added": "Repo: added collaborator", + "team_add": "Repo: added to a team", + "fork": "Repo: forked", + "public": "Repo: made public", + "watch_started": "Repo: starred", + "gollum_created": "Wiki: created page", + "gollum_edited": "Wiki: edited page", +} + +func PayloadToString(event string, payloadOrigin interface{}) string { + payload := payloadOrigin.(map[string]interface{}) + + repository := payload["repository"].(map[string]interface{}) + repoName := repository["full_name"].(string) + + msg := fmt.Sprintf("[%s]", repoName) + + if event == "push" { + pusher := payload["pusher"].(map[string]interface{}) + commits := payload["commits"].([]interface{}) + added := 0 + removed := 0 + modified := 0 + for _, commitOrigin := range commits { + commit := commitOrigin.(map[string]interface{}) + added += len(commit["added"].([]interface{})) + removed += len(commit["removed"].([]interface{})) + modified += len(commit["modified"].([]interface{})) + } + msg = fmt.Sprintf("%s %s - pushed %d commit(s) to %s [+%d/-%d/\u00B1%d] \n %s", msg, pusher["name"], len(commits), strings.TrimLeft(payload["ref"].(string), "refs/heads/"), added, removed, modified, payload["compare"]) + } else if event == "issues" || event == "issue_comment" { + sender := payload["sender"].(map[string]interface{}) + issue := payload["issue"].(map[string]interface{}) + msg = fmt.Sprintf("%s %s - %s action #%f: %s \n %s", msg, sender["login"], payload["action"], issue["number"], issue["title"], issue["html_url"]) + } else { + sender := payload["sender"].(map[string]interface{}) + text := eventMsg[event] + if text == "" { + text = event + } + msg = fmt.Sprintf("%s %s - %s", msg, sender["login"], text) + } + return msg +} diff --git a/xmpp/main.go b/xmpp/main.go new file mode 100644 index 0000000..1068c35 --- /dev/null +++ b/xmpp/main.go @@ -0,0 +1,36 @@ +package xmpp + +import ( + "github.com/genofire/golang-lib/log" + "github.com/genofire/hook2xmpp/config" + + xmpp "github.com/mattn/go-xmpp" +) + +func Start(client *xmpp.Client) { + for { + m, err := client.Recv() + if err != nil { + continue + } + switch v := m.(type) { + case xmpp.Chat: + if v.Type == "chat" { + log.Log.Infof("from %s: %s", v.Remote, v.Text) + } + if v.Type == "groupchat" { + } + case xmpp.Presence: + // do nothing + } + } +} + +func Notify(client *xmpp.Client, hook config.Hook, msg string) { + for _, muc := range hook.NotifyMuc { + client.SendHtml(xmpp.Chat{Remote: muc, Type: "groupchat", Text: msg}) + } + for _, user := range hook.NotifyUser { + client.SendHtml(xmpp.Chat{Remote: user, Type: "chat", Text: msg}) + } +}