diff --git a/src/github.com/matrix-org/go-neb/services/github/github.go b/src/github.com/matrix-org/go-neb/services/github/github.go index 8c20fab..6222e02 100644 --- a/src/github.com/matrix-org/go-neb/services/github/github.go +++ b/src/github.com/matrix-org/go-neb/services/github/github.go @@ -1,13 +1,22 @@ package services import ( + "fmt" + log "github.com/Sirupsen/logrus" + "github.com/google/go-github/github" "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" + "golang.org/x/oauth2" "regexp" + "strconv" "strings" ) +// Matches alphanumeric then a /, then more alphanumeric then a #, then a number. +// E.g. owner/repo#11 (issue/PR numbers) - Captured groups for owner/repo/number +const ownerRepoIssueRegex = "([A-z0-9-_]+)/([A-z0-9-_]+)#([0-9]+)" + type githubService struct { id string UserID string @@ -30,14 +39,29 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin { }, Expansions: []plugin.Expansion{ plugin.Expansion{ - // E.g. owner/repo#11 (issue/PR numbers) - Regexp: regexp.MustCompile("[A-z0-9-_]+/[A-z0-9-_]+#[0-9]+"), + Regexp: regexp.MustCompile(ownerRepoIssueRegex), Expand: func(roomID, matchingText string) interface{} { - // get the issue/PR number - repoAndNum := strings.Split(matchingText, "#") + cli := githubClient("") + owner, repo, num, err := ownerRepoNumberFromText(matchingText) + if err != nil { + log.WithError(err).WithField("text", matchingText).Print( + "Failed to extract owner,repo,number from matched string") + return nil + } + + i, _, err := cli.Issues.Get(owner, repo, num) + if err != nil { + log.WithError(err).WithFields(log.Fields{ + "owner": owner, + "repo": repo, + "number": num, + }).Print("Failed to fetch issue") + return nil + } + return &matrix.TextMessage{ "m.notice", - "Repo: " + repoAndNum[0] + " Num: " + repoAndNum[1], + fmt.Sprintf("%s : %s", *i.HTMLURL, *i.Title), } }, }, @@ -45,6 +69,34 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin { } } +func githubClient(token string) *github.Client { + var tokenSource oauth2.TokenSource + if token != "" { + tokenSource = oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token}, + ) + } + httpCli := oauth2.NewClient(oauth2.NoContext, tokenSource) + return github.NewClient(httpCli) +} + +// ownerRepoNumberFromText parses a GH issue string that looks like 'owner/repo#11' +// into its constituient parts. Returns: owner, repo, issue#. +func ownerRepoNumberFromText(ownerRepoNumberText string) (string, string, int, error) { + // TODO: cache this? + re := regexp.MustCompile(ownerRepoIssueRegex) + // [full_string, owner, repo, issue_number] + groups := re.FindStringSubmatch(ownerRepoNumberText) + if len(groups) != 4 { + return "", "", 0, fmt.Errorf("No match found for '%s'", ownerRepoNumberText) + } + num, err := strconv.Atoi(groups[3]) + if err != nil { + return "", "", 0, err + } + return groups[1], groups[2], num, nil +} + func init() { database.RegisterService(func(serviceID string) database.Service { return &githubService{id: serviceID}