You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

github.go 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package httplistener
  2. import (
  3. "fmt"
  4. "github.com/irccloud/irccat/util"
  5. "github.com/spf13/viper"
  6. "gopkg.in/go-playground/webhooks.v5/github"
  7. "net/http"
  8. "strings"
  9. )
  10. func formatRef(ref string) string {
  11. parts := strings.Split(ref, "/")
  12. res := ""
  13. if parts[1] == "heads" {
  14. res = "branch "
  15. } else if parts[1] == "tags" {
  16. res = "tag "
  17. }
  18. return res + parts[2]
  19. }
  20. func handleRelease(payload github.ReleasePayload) ([]string, string, bool) {
  21. if payload.Action != "published" {
  22. return []string{""}, "", false
  23. }
  24. var release string
  25. if payload.Release.Name != nil {
  26. release = *payload.Release.Name
  27. }
  28. if release == "" {
  29. release = payload.Release.TagName
  30. }
  31. msg := fmt.Sprintf("[\x02%s\x0f] release \x02%s\x0f has been published by %s: %s",
  32. payload.Repository.Name, release, payload.Release.Author.Login, payload.Release.HTMLURL)
  33. return []string{msg}, payload.Repository.Name, true
  34. }
  35. func handlePush(payload github.PushPayload) ([]string, string, bool) {
  36. var msgs []string
  37. msgs = append(msgs, fmt.Sprintf("[\x02%s\x0f] %s pushed %d new commits to %s: %s",
  38. payload.Repository.Name, payload.Sender.Login, len(payload.Commits),
  39. formatRef(payload.Ref), payload.Compare))
  40. commits_shown := 0
  41. for _, commit := range payload.Commits {
  42. if commits_shown == 3 {
  43. break
  44. }
  45. if !commit.Distinct {
  46. continue
  47. }
  48. msgs = append(msgs, fmt.Sprintf("\t%s: %s", commit.Author.Username, commit.Message))
  49. commits_shown++
  50. }
  51. return msgs, payload.Repository.Name, true
  52. }
  53. func handleIssue(payload github.IssuesPayload) ([]string, string, bool) {
  54. msg := fmt.Sprintf("[\x02%s\x0f] %s ", payload.Repository.Name, payload.Sender.Login)
  55. issue_id := fmt.Sprintf("issue #%d", payload.Issue.Number)
  56. show := true
  57. switch payload.Action {
  58. case "opened":
  59. msg = msg + "opened " + issue_id
  60. case "closed":
  61. msg = msg + "closed " + issue_id
  62. default:
  63. // Don't know what to do with this, so don't show it
  64. show = false
  65. }
  66. msg = msg + fmt.Sprintf(": %s %s", payload.Issue.Title, payload.Issue.HTMLURL)
  67. return []string{msg}, payload.Repository.Name, show
  68. }
  69. func handleIssueComment(payload github.IssueCommentPayload) ([]string, string, bool) {
  70. if payload.Action != "created" {
  71. return []string{}, payload.Repository.Name, false
  72. }
  73. msg := fmt.Sprintf("[\x02%s\x0f] %s commented on issue %d: %s",
  74. payload.Repository.Name, payload.Comment.User.Login,
  75. payload.Issue.Number, util.Truncate(payload.Comment.Body, 150))
  76. return []string{msg}, payload.Repository.Name, true
  77. }
  78. func (hl *HTTPListener) githubHandler(w http.ResponseWriter, request *http.Request) {
  79. if request.Method != "POST" {
  80. http.NotFound(w, request)
  81. return
  82. }
  83. hook, err := github.New() // TODO: webhook secret
  84. if err != nil {
  85. return
  86. }
  87. // All valid events we want to receive need to be listed here.
  88. payload, err := hook.Parse(request,
  89. github.ReleaseEvent, github.PushEvent, github.IssuesEvent, github.IssueCommentEvent)
  90. if err != nil {
  91. log.Errorf("Error parsing github webhook: %s", err)
  92. return
  93. }
  94. msgs := []string{}
  95. repo := ""
  96. send := false
  97. switch payload.(type) {
  98. case github.ReleasePayload:
  99. msgs, repo, send = handleRelease(payload.(github.ReleasePayload))
  100. case github.PushPayload:
  101. msgs, repo, send = handlePush(payload.(github.PushPayload))
  102. case github.IssuesPayload:
  103. msgs, repo, send = handleIssue(payload.(github.IssuesPayload))
  104. case github.IssueCommentPayload:
  105. msgs, repo, send = handleIssueComment(payload.(github.IssueCommentPayload))
  106. }
  107. if send {
  108. repo = strings.ToLower(repo)
  109. channelKey := fmt.Sprintf("http.listeners.github.repositories.%s", repo)
  110. channel := viper.GetString(channelKey)
  111. if channel == "" {
  112. log.Infof("%s GitHub event for unrecognised repository %s", request.RemoteAddr, repo)
  113. return
  114. }
  115. log.Infof("%s [%s -> %s] GitHub event received", request.RemoteAddr, repo, channel)
  116. for _, msg := range msgs {
  117. hl.irc.Privmsgf(channel, msg)
  118. }
  119. }
  120. }