Browse Source

Merge pull request #27 from matrix-org/kegan/github-starter-links

Add StarterLink as a field to the Github Service config
pull/29/head
Kegsay 9 years ago
committed by GitHub
parent
commit
69b9175348
  1. 27
      src/github.com/matrix-org/go-neb/matrix/types.go
  2. 27
      src/github.com/matrix-org/go-neb/realms/github/github.go
  3. 150
      src/github.com/matrix-org/go-neb/services/github/github.go

27
src/github.com/matrix-org/go-neb/matrix/types.go

@ -1,6 +1,7 @@
package matrix
import (
"encoding/json"
"html"
"regexp"
)
@ -114,3 +115,29 @@ func GetHTMLMessage(msgtype, htmlText string) HTMLMessage {
FormattedBody: htmlText,
}
}
// StarterLinkMessage represents a message with a starter_link custom data.
type StarterLinkMessage struct {
Body string
Link string
}
// MarshalJSON converts this message into actual event content JSON.
func (m StarterLinkMessage) MarshalJSON() ([]byte, error) {
var data map[string]string
if m.Link != "" {
data = map[string]string{
"org.matrix.neb.starter_link": m.Link,
}
}
msg := struct {
MsgType string `json:"msgtype"`
Body string `json:"body"`
Data map[string]string `json:"data,omitempty"`
}{
"m.notice", m.Body, data,
}
return json.Marshal(msg)
}

27
src/github.com/matrix-org/go-neb/realms/github/github.go

@ -12,11 +12,13 @@ import (
"net/url"
)
type githubRealm struct {
// GithubRealm can handle OAuth processes with github.com
type GithubRealm struct {
id string
redirectURL string
ClientSecret string
ClientID string
StarterLink string
}
// GithubSession represents an authenticated github session
@ -50,23 +52,28 @@ func (s *GithubSession) ID() string {
return s.id
}
func (r *githubRealm) ID() string {
// ID returns the realm ID
func (r *GithubRealm) ID() string {
return r.id
}
func (r *githubRealm) Type() string {
// Type is github
func (r *GithubRealm) Type() string {
return "github"
}
func (r *githubRealm) Init() error {
// Init does nothing.
func (r *GithubRealm) Init() error {
return nil
}
func (r *githubRealm) Register() error {
// Register does nothing.
func (r *GithubRealm) Register() error {
return nil
}
func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) interface{} {
// RequestAuthSession generates an OAuth2 URL for this user to auth with github via.
func (r *GithubRealm) RequestAuthSession(userID string, req json.RawMessage) interface{} {
state, err := randomString(10)
if err != nil {
log.WithError(err).Print("Failed to generate state param")
@ -95,7 +102,8 @@ func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) int
}{u.String()}
}
func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request) {
// OnReceiveRedirect processes OAuth redirect requests from Github
func (r *GithubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request) {
// parse out params from the request
code := req.URL.Query().Get("code")
state := req.URL.Query().Get("state")
@ -153,7 +161,8 @@ func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request
w.Write([]byte("OK!"))
}
func (r *githubRealm) AuthSession(id, userID, realmID string) types.AuthSession {
// AuthSession returns a GithubSession for this user
func (r *GithubRealm) AuthSession(id, userID, realmID string) types.AuthSession {
return &GithubSession{
id: id,
userID: userID,
@ -180,6 +189,6 @@ func randomString(length int) (string, error) {
func init() {
types.RegisterAuthRealm(func(realmID, redirectURL string) types.AuthRealm {
return &githubRealm{id: realmID, redirectURL: redirectURL}
return &GithubRealm{id: realmID, redirectURL: redirectURL}
})
}

150
src/github.com/matrix-org/go-neb/services/github/github.go

@ -45,56 +45,95 @@ func (s *githubService) RoomIDs() []string {
}
return keys
}
func (s *githubService) cmdGithubCreate(roomID, userID string, args []string) (interface{}, error) {
cli := s.githubClientFor(userID, false)
if cli == nil {
r, err := database.GetServiceDB().LoadAuthRealm(s.RealmID)
if err != nil {
return nil, err
}
ghRealm, ok := r.(*realms.GithubRealm)
if !ok {
return nil, fmt.Errorf("Failed to cast realm %s into a GithubRealm", s.RealmID)
}
return matrix.StarterLinkMessage{
Body: "You need to OAuth with Github before you can create issues.",
Link: ghRealm.StarterLink,
}, nil
}
if len(args) < 2 {
return &matrix.TextMessage{"m.notice",
`Usage: !github create owner/repo "issue title" "description"`}, nil
}
var (
ownerRepo string
title *string
desc *string
)
ownerRepo = args[0]
o := strings.Split(ownerRepo, "/")
if len(o) != 2 {
return &matrix.TextMessage{"m.notice",
`Usage: !github create owner/repo "issue title" "description"`}, nil
}
if len(args) == 2 {
title = &args[1]
} else if len(args) == 3 {
title = &args[1]
desc = &args[2]
} else { // > 3 args is probably a title without quote marks
joinedTitle := strings.Join(args[1:], " ")
title = &joinedTitle
}
issue, res, err := cli.Issues.Create(o[0], o[1], &github.IssueRequest{
Title: title,
Body: desc,
})
if err != nil {
log.WithField("err", err).Print("Failed to create issue")
return nil, fmt.Errorf("Failed to create issue. HTTP %d", res.StatusCode)
}
return matrix.TextMessage{"m.notice", fmt.Sprintf("Created issue: %s", *issue.HTMLURL)}, nil
}
func (s *githubService) expandIssue(roomID, userID, matchingText string) interface{} {
cli := s.githubClientFor(userID, true)
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",
fmt.Sprintf("%s : %s", *i.HTMLURL, *i.Title),
}
}
func (s *githubService) Plugin(roomID string) plugin.Plugin {
return plugin.Plugin{
Commands: []plugin.Command{
plugin.Command{
Path: []string{"github", "create"},
Command: func(roomID, userID string, args []string) (interface{}, error) {
cli := s.githubClientFor(userID, false)
if cli == nil {
// TODO: send starter link
return &matrix.TextMessage{"m.notice",
userID + " : You have not linked your Github account."}, nil
}
if len(args) < 2 {
return &matrix.TextMessage{"m.notice",
`Usage: !github create owner/repo "issue title" "description"`}, nil
}
var (
ownerRepo string
title *string
desc *string
)
ownerRepo = args[0]
o := strings.Split(ownerRepo, "/")
if len(o) != 2 {
return &matrix.TextMessage{"m.notice",
`Usage: !github create owner/repo "issue title" "description"`}, nil
}
if len(args) == 2 {
title = &args[1]
} else if len(args) == 3 {
title = &args[1]
desc = &args[2]
} else { // > 3 args is probably a title without quote marks
joinedTitle := strings.Join(args[1:], " ")
title = &joinedTitle
}
issue, res, err := cli.Issues.Create(o[0], o[1], &github.IssueRequest{
Title: title,
Body: desc,
})
if err != nil {
log.WithField("err", err).Print("Failed to create issue")
return nil, fmt.Errorf("Failed to create issue. HTTP %d", res.StatusCode)
}
return matrix.TextMessage{"m.notice", fmt.Sprintf("Created issue: %s", *issue.HTMLURL)}, nil
return s.cmdGithubCreate(roomID, userID, args)
},
},
},
@ -102,28 +141,7 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin {
plugin.Expansion{
Regexp: ownerRepoIssueRegex,
Expand: func(roomID, userID, matchingText string) interface{} {
cli := s.githubClientFor(userID, true)
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",
fmt.Sprintf("%s : %s", *i.HTMLURL, *i.Title),
}
return s.expandIssue(roomID, userID, matchingText)
},
},
},

Loading…
Cancel
Save