From 79d7db4fab1d90691331e522ea019d4be62b21a5 Mon Sep 17 00:00:00 2001 From: James Salter Date: Wed, 18 Aug 2021 15:11:09 +0100 Subject: [PATCH 01/11] Fix m.room.bot.options never being received by go-neb --- clients/clients.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/clients/clients.go b/clients/clients.go index 0e5816c..9934559 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -16,6 +16,7 @@ import ( shellwords "github.com/mattn/go-shellwords" log "github.com/sirupsen/logrus" "maunium.net/go/mautrix" + "maunium.net/go/mautrix/event" mevt "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -344,6 +345,15 @@ func (c *Clients) initClient(botClient *BotClient) error { botClient.verificationSAS = &sync.Map{} syncer := client.Syncer.(*mautrix.DefaultSyncer) + syncer.ParseErrorHandler = func(evt *event.Event, err error) bool { + // Events of type m.room.bot.options will be flagged as errors as this isn't an event type + // recognised by the Syncer, but we need to process them so the bot can accept options + // through this event (see onBotOptionsEvent) + if evt.Type.Type == "m.room.bot.options" { + return true + } + return false + } nebStore := &matrix.NEBStore{ InMemoryStore: *mautrix.NewInMemoryStore(), @@ -366,7 +376,7 @@ func (c *Clients) initClient(botClient *BotClient) error { c.onMessageEvent(botClient, event) }) - syncer.OnEventType(mevt.Type{Type: "m.room.bot.options", Class: mevt.UnknownEventType}, func(_ mautrix.EventSource, event *mevt.Event) { + syncer.OnEventType(mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType}, func(_ mautrix.EventSource, event *mevt.Event) { c.onBotOptionsEvent(botClient.Client, event) }) From 5f955cd38000bddb0bdd98d9966603b8db50d63c Mon Sep 17 00:00:00 2001 From: James Salter Date: Wed, 18 Aug 2021 15:11:44 +0100 Subject: [PATCH 02/11] Add support for new_issue_labels in github m.room.bot.options --- services/github/github.go | 68 ++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/services/github/github.go b/services/github/github.go index 91b1515..42a5acb 100644 --- a/services/github/github.go +++ b/services/github/github.go @@ -7,6 +7,7 @@ package github import ( "context" "database/sql" + "errors" "fmt" "regexp" "strconv" @@ -50,17 +51,20 @@ var ownerRepoRegex = regexp.MustCompile(`^([A-z0-9-_.]+)/([A-z0-9-_.]+)$`) // // Before you can set up a Github Service, you need to set up a Github Realm. // -// You can set a "default repository" for a Matrix room by sending a `m.room.bot.options` state event +// You can set optional config for a Matrix room by sending a `m.room.bot.options` state event // which has the following `content`: // // { // "github": { -// "default_repo": "owner/repo" +// // The default repository to use for this room; this allows "owner/repo" to be omitted +// // when creating/expanding issues. +// "default_repo": "owner/repo", +// +// // Comma-separated Github labels to attach to any issue created by this bot in this room. +// "new_issue_labels": "bot-label-1, bot-label-2" // } // } // -// This will allow the "owner/repo" to be omitted when creating/expanding issues. -// // Example request: // { // "RealmID": "github-realm-id" @@ -203,9 +207,12 @@ func (s *Service) cmdGithubCreate(roomID id.RoomID, userID id.UserID, args []str title = &joinedTitle } + labels := s.newIssueLabels(roomID) + issue, res, err := cli.Issues.Create(context.Background(), ownerRepoGroups[1], ownerRepoGroups[2], &gogithub.IssueRequest{ - Title: title, - Body: desc, + Title: title, + Body: desc, + Labels: &labels, }) if err != nil { log.WithField("err", err).Print("Failed to create issue") @@ -735,24 +742,37 @@ func (s *Service) Register(oldService types.Service, client types.MatrixClient) return nil } -// defaultRepo returns the default repo for the given room, or an empty string. -func (s *Service) defaultRepo(roomID id.RoomID) string { - logger := log.WithFields(log.Fields{ - "room_id": roomID, - "bot_user_id": s.ServiceUserID(), - }) +func (s *Service) loadBotOptions(roomID id.RoomID, logger *log.Entry) (result map[string]interface{}, err error) { opts, err := database.GetServiceDB().LoadBotOptions(s.ServiceUserID(), roomID) if err != nil { - if err != sql.ErrNoRows { - logger.WithError(err).Error("Failed to load bot options") + if err == sql.ErrNoRows { + logger.Info("no bot options") + return make(map[string]interface{}), nil + } else { + err := errors.New("Failed to load bot options") + logger.WithError(err).Error(err) + return nil, err } - return "" } // Expect opts to look like: // { github: { default_repo: $OWNER_REPO } } ghOpts, ok := opts.Options["github"].(map[string]interface{}) if !ok { - logger.WithField("options", opts.Options).Error("Failed to cast bot options as github options") + err = fmt.Errorf("Failed to cast bot options as github options") + logger.WithField("options", opts.Options).Error(err) + return nil, err + } + return ghOpts, nil +} + +// defaultRepo returns the default repo for the given room, or an empty string. +func (s *Service) defaultRepo(roomID id.RoomID) string { + logger := log.WithFields(log.Fields{ + "room_id": roomID, + "bot_user_id": s.ServiceUserID(), + }) + ghOpts, err := s.loadBotOptions(roomID, logger) + if err != nil { return "" } defaultRepo, ok := ghOpts["default_repo"].(string) @@ -765,6 +785,22 @@ func (s *Service) defaultRepo(roomID id.RoomID) string { return defaultRepo } +func (s *Service) newIssueLabels(roomID id.RoomID) []string { + logger := log.WithFields(log.Fields{ + "room_id": roomID, + "bot_user_id": s.ServiceUserID(), + }) + ghOpts, err := s.loadBotOptions(roomID, logger) + if err != nil { + return make([]string, 0) + } + newIssueLabels, ok := ghOpts["new_issue_labels"].(string) + if !ok { + return make([]string, 0) + } + return strings.Split(newIssueLabels, ",") +} + func (s *Service) githubClientFor(userID id.UserID, allowUnauth bool) *gogithub.Client { token, err := getTokenForUser(s.RealmID, userID) if err != nil { From 4ffce3b22bd410e63d4e82858b66b2e51bcf2161 Mon Sep 17 00:00:00 2001 From: James Salter Date: Wed, 18 Aug 2021 15:31:50 +0100 Subject: [PATCH 03/11] fix lint --- clients/clients.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/clients/clients.go b/clients/clients.go index 9934559..8889c67 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -16,7 +16,6 @@ import ( shellwords "github.com/mattn/go-shellwords" log "github.com/sirupsen/logrus" "maunium.net/go/mautrix" - "maunium.net/go/mautrix/event" mevt "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -345,14 +344,11 @@ func (c *Clients) initClient(botClient *BotClient) error { botClient.verificationSAS = &sync.Map{} syncer := client.Syncer.(*mautrix.DefaultSyncer) - syncer.ParseErrorHandler = func(evt *event.Event, err error) bool { + syncer.ParseErrorHandler = func(evt *mevt.Event, err error) bool { // Events of type m.room.bot.options will be flagged as errors as this isn't an event type // recognised by the Syncer, but we need to process them so the bot can accept options // through this event (see onBotOptionsEvent) - if evt.Type.Type == "m.room.bot.options" { - return true - } - return false + return evt.Type.Type == "m.room.bot.options" } nebStore := &matrix.NEBStore{ From 1e63241a2554c03c8c6af566e9d1588cbabaa5ff Mon Sep 17 00:00:00 2001 From: James Salter Date: Wed, 18 Aug 2021 18:05:51 +0100 Subject: [PATCH 04/11] Use array of strings to spec labels --- services/github/github.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/github/github.go b/services/github/github.go index 42a5acb..cccb634 100644 --- a/services/github/github.go +++ b/services/github/github.go @@ -60,8 +60,8 @@ var ownerRepoRegex = regexp.MustCompile(`^([A-z0-9-_.]+)/([A-z0-9-_.]+)$`) // // when creating/expanding issues. // "default_repo": "owner/repo", // -// // Comma-separated Github labels to attach to any issue created by this bot in this room. -// "new_issue_labels": "bot-label-1, bot-label-2" +// // Array of Github labels to attach to any issue created by this bot in this room. +// "new_issue_labels": ["bot-label-1", "bot-label-2"] // } // } // @@ -794,11 +794,15 @@ func (s *Service) newIssueLabels(roomID id.RoomID) []string { if err != nil { return make([]string, 0) } - newIssueLabels, ok := ghOpts["new_issue_labels"].(string) + newIssueLabels, ok := ghOpts["new_issue_labels"].([]interface{}) if !ok { return make([]string, 0) } - return strings.Split(newIssueLabels, ",") + newIssueLabelsUnboxed := make([]string, 0) + for _, s := range newIssueLabels { + newIssueLabelsUnboxed = append(newIssueLabelsUnboxed, s.(string)) + } + return newIssueLabelsUnboxed } func (s *Service) githubClientFor(userID id.UserID, allowUnauth bool) *gogithub.Client { From 79af91a0d64ec3c099c507e862e3fe3c79383ba3 Mon Sep 17 00:00:00 2001 From: James Salter Date: Wed, 18 Aug 2021 18:18:53 +0100 Subject: [PATCH 05/11] Ammend comment with new type --- services/github/github.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/github/github.go b/services/github/github.go index cccb634..85f4c2a 100644 --- a/services/github/github.go +++ b/services/github/github.go @@ -755,7 +755,12 @@ func (s *Service) loadBotOptions(roomID id.RoomID, logger *log.Entry) (result ma } } // Expect opts to look like: - // { github: { default_repo: $OWNER_REPO } } + // { + // github: { + // default_repo: $OWNER_REPO, + // new_issue_labels: [ "label1", .. ] + // } + // } ghOpts, ok := opts.Options["github"].(map[string]interface{}) if !ok { err = fmt.Errorf("Failed to cast bot options as github options") From 072a0ad609cd2b3d713157f9a3e3cc8664547850 Mon Sep 17 00:00:00 2001 From: James Salter Date: Thu, 19 Aug 2021 09:25:29 +0100 Subject: [PATCH 06/11] Add m.room.bot.options to mautrix's typemap, rather than handling it in ParseErrorHandler --- clients/clients.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clients/clients.go b/clients/clients.go index 8889c67..a8d0df3 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -328,6 +328,13 @@ func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { } } +type BotOptionsContent struct { + Github struct { + DefaultRepo string `json:"default_repo,omitempty"` + NewIssueLabels string `json:"new_issue_labels,omitempty"` + } +} + func (c *Clients) initClient(botClient *BotClient) error { config := botClient.config client, err := mautrix.NewClient(config.HomeserverURL, config.UserID, config.AccessToken) @@ -344,12 +351,10 @@ func (c *Clients) initClient(botClient *BotClient) error { botClient.verificationSAS = &sync.Map{} syncer := client.Syncer.(*mautrix.DefaultSyncer) - syncer.ParseErrorHandler = func(evt *mevt.Event, err error) bool { - // Events of type m.room.bot.options will be flagged as errors as this isn't an event type - // recognised by the Syncer, but we need to process them so the bot can accept options - // through this event (see onBotOptionsEvent) - return evt.Type.Type == "m.room.bot.options" - } + + // Add m.room.bot.options to mautrix's TypeMap so that it parses it as a valid event + var StateBotOptions = mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType} + mevt.TypeMap[StateBotOptions] = reflect.TypeOf(&BotOptionsContent{}) nebStore := &matrix.NEBStore{ InMemoryStore: *mautrix.NewInMemoryStore(), From 37cde99914ad7cef378cc78927efd14d64f449a1 Mon Sep 17 00:00:00 2001 From: James Salter Date: Thu, 19 Aug 2021 11:28:09 +0100 Subject: [PATCH 07/11] Fix schema definition --- clients/clients.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clients/clients.go b/clients/clients.go index a8d0df3..e11d10b 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -330,9 +330,9 @@ func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { type BotOptionsContent struct { Github struct { - DefaultRepo string `json:"default_repo,omitempty"` - NewIssueLabels string `json:"new_issue_labels,omitempty"` - } + DefaultRepo string `json:"default_repo,omitempty"` + NewIssueLabels []string `json:"new_issue_labels,omitempty"` + } `json:"github"` } func (c *Clients) initClient(botClient *BotClient) error { From 13d63a93c07ef690368e7d457822d9c1d106db95 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Apr 2022 14:41:00 +0100 Subject: [PATCH 08/11] Improve typing --- clients/clients.go | 23 ++++++++++++++--------- services/github/github.go | 5 +++++ types/service.go | 7 ++++++- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/clients/clients.go b/clients/clients.go index e11d10b..46b5bbf 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -2,6 +2,7 @@ package clients import ( "database/sql" + "encoding/json" "fmt" "net/http" "reflect" @@ -287,11 +288,22 @@ func (c *Clients) onBotOptionsEvent(client *mautrix.Client, event *mevt.Event) { return } // these options fully clobber what was there previously. + + var options types.BotOptionsContent + if err := json.Unmarshal(event.Content.VeryRaw, &options); err != nil { + log.WithFields(log.Fields{ + log.ErrorKey: err, + "room_id": event.RoomID, + "bot_user_id": client.UserID, + "set_by_user_id": event.Sender, + }).Error("Failed to parse bot options") + } + opts := types.BotOptions{ UserID: client.UserID, RoomID: event.RoomID, SetByUserID: event.Sender, - Options: event.Content.Raw, + Options: options, } if _, err := c.db.StoreBotOptions(opts); err != nil { log.WithFields(log.Fields{ @@ -328,13 +340,6 @@ func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { } } -type BotOptionsContent struct { - Github struct { - DefaultRepo string `json:"default_repo,omitempty"` - NewIssueLabels []string `json:"new_issue_labels,omitempty"` - } `json:"github"` -} - func (c *Clients) initClient(botClient *BotClient) error { config := botClient.config client, err := mautrix.NewClient(config.HomeserverURL, config.UserID, config.AccessToken) @@ -354,7 +359,7 @@ func (c *Clients) initClient(botClient *BotClient) error { // Add m.room.bot.options to mautrix's TypeMap so that it parses it as a valid event var StateBotOptions = mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType} - mevt.TypeMap[StateBotOptions] = reflect.TypeOf(&BotOptionsContent{}) + mevt.TypeMap[StateBotOptions] = reflect.TypeOf(&types.BotOptionsContent{}) nebStore := &matrix.NEBStore{ InMemoryStore: *mautrix.NewInMemoryStore(), diff --git a/services/github/github.go b/services/github/github.go index 85f4c2a..ae71aac 100644 --- a/services/github/github.go +++ b/services/github/github.go @@ -76,6 +76,11 @@ type Service struct { RealmID string } +type Options struct { + DefaultRepo string `json:"default_repo,omitempty"` + NewIssueLabels []string `json:"new_issue_labels,omitempty"` +} + func (s *Service) requireGithubClientFor(userID id.UserID) (cli *gogithub.Client, resp interface{}, err error) { cli = s.githubClientFor(userID, false) if cli == nil { diff --git a/types/service.go b/types/service.go index 5f208d0..f567e20 100644 --- a/types/service.go +++ b/types/service.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "github.com/matrix-org/go-neb/services/github" "net/http" "strings" "time" @@ -13,12 +14,16 @@ import ( "maunium.net/go/mautrix/id" ) +type BotOptionsContent struct { + Github github.Options `json:"github"` +} + // BotOptions for a given bot user in a given room type BotOptions struct { RoomID id.RoomID UserID id.UserID SetByUserID id.UserID - Options map[string]interface{} + Options BotOptionsContent } // Poller represents a thing which can poll. Services should implement this method signature to support polling. From decec2d4db67b7b3389416e42b00a63e4f4d47ee Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Apr 2022 14:53:50 +0100 Subject: [PATCH 09/11] Update golang.org/x/sys to fix Darwin builds --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 32aa1eb..8daa9d5 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d + golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v2 v2.3.0 maunium.net/go/mautrix v0.9.12 diff --git a/go.sum b/go.sum index 2eec917..a9af9f4 100644 --- a/go.sum +++ b/go.sum @@ -143,6 +143,8 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 64843499e9c9a0566f6d86c6ec2095deb829db16 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Apr 2022 16:01:08 +0100 Subject: [PATCH 10/11] Iterate PR to leverage the library better --- clients/clients.go | 21 ++++-------- services/github/github.go | 71 +++++++++++---------------------------- types/service.go | 10 ++++-- 3 files changed, 32 insertions(+), 70 deletions(-) diff --git a/clients/clients.go b/clients/clients.go index 46b5bbf..79dc37b 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -2,7 +2,6 @@ package clients import ( "database/sql" - "encoding/json" "fmt" "net/http" "reflect" @@ -289,21 +288,11 @@ func (c *Clients) onBotOptionsEvent(client *mautrix.Client, event *mevt.Event) { } // these options fully clobber what was there previously. - var options types.BotOptionsContent - if err := json.Unmarshal(event.Content.VeryRaw, &options); err != nil { - log.WithFields(log.Fields{ - log.ErrorKey: err, - "room_id": event.RoomID, - "bot_user_id": client.UserID, - "set_by_user_id": event.Sender, - }).Error("Failed to parse bot options") - } - opts := types.BotOptions{ UserID: client.UserID, RoomID: event.RoomID, SetByUserID: event.Sender, - Options: options, + Options: event.Content.Parsed.(*types.BotOptionsContent), } if _, err := c.db.StoreBotOptions(opts); err != nil { log.WithFields(log.Fields{ @@ -340,6 +329,8 @@ func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { } } +var StateBotOptionsEvent = mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType} + func (c *Clients) initClient(botClient *BotClient) error { config := botClient.config client, err := mautrix.NewClient(config.HomeserverURL, config.UserID, config.AccessToken) @@ -356,10 +347,10 @@ func (c *Clients) initClient(botClient *BotClient) error { botClient.verificationSAS = &sync.Map{} syncer := client.Syncer.(*mautrix.DefaultSyncer) + syncer.ParseEventContent = true // Add m.room.bot.options to mautrix's TypeMap so that it parses it as a valid event - var StateBotOptions = mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType} - mevt.TypeMap[StateBotOptions] = reflect.TypeOf(&types.BotOptionsContent{}) + mevt.TypeMap[StateBotOptionsEvent] = reflect.TypeOf(types.BotOptionsContent{}) nebStore := &matrix.NEBStore{ InMemoryStore: *mautrix.NewInMemoryStore(), @@ -382,7 +373,7 @@ func (c *Clients) initClient(botClient *BotClient) error { c.onMessageEvent(botClient, event) }) - syncer.OnEventType(mevt.Type{Type: "m.room.bot.options", Class: mevt.StateEventType}, func(_ mautrix.EventSource, event *mevt.Event) { + syncer.OnEventType(StateBotOptionsEvent, func(_ mautrix.EventSource, event *mevt.Event) { c.onBotOptionsEvent(botClient.Client, event) }) diff --git a/services/github/github.go b/services/github/github.go index ae71aac..772c362 100644 --- a/services/github/github.go +++ b/services/github/github.go @@ -76,11 +76,6 @@ type Service struct { RealmID string } -type Options struct { - DefaultRepo string `json:"default_repo,omitempty"` - NewIssueLabels []string `json:"new_issue_labels,omitempty"` -} - func (s *Service) requireGithubClientFor(userID id.UserID) (cli *gogithub.Client, resp interface{}, err error) { cli = s.githubClientFor(userID, false) if cli == nil { @@ -176,9 +171,18 @@ func (s *Service) cmdGithubCreate(roomID id.RoomID, userID id.UserID, args []str // Look for a default if the first arg doesn't look like an owner/repo ownerRepoGroups := ownerRepoRegex.FindStringSubmatch(args[0]) + logger := log.WithFields(log.Fields{ + "room_id": roomID, + "bot_user_id": s.ServiceUserID(), + }) + options, err := s.loadBotOptions(roomID, logger) + if err != nil { + return nil, err + } + if len(ownerRepoGroups) == 0 { // look for a default repo - defaultRepo := s.defaultRepo(roomID) + defaultRepo := options.DefaultRepo if defaultRepo == "" { return &mevt.MessageEventContent{ MsgType: mevt.MsgNotice, @@ -212,12 +216,10 @@ func (s *Service) cmdGithubCreate(roomID id.RoomID, userID id.UserID, args []str title = &joinedTitle } - labels := s.newIssueLabels(roomID) - issue, res, err := cli.Issues.Create(context.Background(), ownerRepoGroups[1], ownerRepoGroups[2], &gogithub.IssueRequest{ Title: title, Body: desc, - Labels: &labels, + Labels: &options.NewIssueLabels, }) if err != nil { log.WithField("err", err).Print("Failed to create issue") @@ -747,16 +749,16 @@ func (s *Service) Register(oldService types.Service, client types.MatrixClient) return nil } -func (s *Service) loadBotOptions(roomID id.RoomID, logger *log.Entry) (result map[string]interface{}, err error) { +func (s *Service) loadBotOptions(roomID id.RoomID, logger *log.Entry) (result types.GithubOptions, err error) { opts, err := database.GetServiceDB().LoadBotOptions(s.ServiceUserID(), roomID) if err != nil { if err == sql.ErrNoRows { - logger.Info("no bot options") - return make(map[string]interface{}), nil + logger.Info("no bot options specified - using defaults") + return types.GithubOptions{}, nil } else { err := errors.New("Failed to load bot options") logger.WithError(err).Error(err) - return nil, err + return types.GithubOptions{}, err } } // Expect opts to look like: @@ -766,13 +768,7 @@ func (s *Service) loadBotOptions(roomID id.RoomID, logger *log.Entry) (result ma // new_issue_labels: [ "label1", .. ] // } // } - ghOpts, ok := opts.Options["github"].(map[string]interface{}) - if !ok { - err = fmt.Errorf("Failed to cast bot options as github options") - logger.WithField("options", opts.Options).Error(err) - return nil, err - } - return ghOpts, nil + return opts.Options.Github, nil } // defaultRepo returns the default repo for the given room, or an empty string. @@ -781,38 +777,9 @@ func (s *Service) defaultRepo(roomID id.RoomID) string { "room_id": roomID, "bot_user_id": s.ServiceUserID(), }) - ghOpts, err := s.loadBotOptions(roomID, logger) - if err != nil { - return "" - } - defaultRepo, ok := ghOpts["default_repo"].(string) - if !ok { - logger.WithField("default_repo", ghOpts["default_repo"]).Error( - "Failed to cast default repo as a string", - ) - return "" - } - return defaultRepo -} - -func (s *Service) newIssueLabels(roomID id.RoomID) []string { - logger := log.WithFields(log.Fields{ - "room_id": roomID, - "bot_user_id": s.ServiceUserID(), - }) - ghOpts, err := s.loadBotOptions(roomID, logger) - if err != nil { - return make([]string, 0) - } - newIssueLabels, ok := ghOpts["new_issue_labels"].([]interface{}) - if !ok { - return make([]string, 0) - } - newIssueLabelsUnboxed := make([]string, 0) - for _, s := range newIssueLabels { - newIssueLabelsUnboxed = append(newIssueLabelsUnboxed, s.(string)) - } - return newIssueLabelsUnboxed + // ignore any errors, we treat it the same as no options and log inside the method + ghOpts, _ := s.loadBotOptions(roomID, logger) + return ghOpts.DefaultRepo } func (s *Service) githubClientFor(userID id.UserID, allowUnauth bool) *gogithub.Client { diff --git a/types/service.go b/types/service.go index f567e20..7726017 100644 --- a/types/service.go +++ b/types/service.go @@ -4,7 +4,6 @@ import ( "encoding/base64" "encoding/json" "errors" - "github.com/matrix-org/go-neb/services/github" "net/http" "strings" "time" @@ -14,8 +13,13 @@ import ( "maunium.net/go/mautrix/id" ) +type GithubOptions struct { + DefaultRepo string `json:"default_repo,omitempty"` + NewIssueLabels []string `json:"new_issue_labels,omitempty"` +} + type BotOptionsContent struct { - Github github.Options `json:"github"` + Github GithubOptions `json:"github"` } // BotOptions for a given bot user in a given room @@ -23,7 +27,7 @@ type BotOptions struct { RoomID id.RoomID UserID id.UserID SetByUserID id.UserID - Options BotOptionsContent + Options *BotOptionsContent } // Poller represents a thing which can poll. Services should implement this method signature to support polling. From 4230799e79742071b7e2f2994fe013cda882d863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadeusz=20So=C5=9Bnierz?= Date: Wed, 13 Apr 2022 15:52:28 +0200 Subject: [PATCH 11/11] Bump Go version in Github CI --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c4eaedb..68b0634 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,7 +23,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: '~1.16.4' + go-version: '~1.18.0' - name: Install libolm run: sudo apt-get -y install libolm3 libolm-dev - name: Install linters