diff --git a/go.mod b/go.mod index c2aac4f3c..20823a18f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/sprig/v3 v3.2.2 github.com/google/go-github/v41 v41.0.0 github.com/gorilla/mux v1.8.0 - github.com/mattermost/mattermost-plugin-api v0.1.3-0.20230323124751-86c7be7ffbac + github.com/mattermost/mattermost-plugin-api v0.1.3 // mmgoget: github.com/mattermost/mattermost-server/v6@v7.5.0 is replaced by -> github.com/mattermost/mattermost-server/v6@21aec2741b github.com/mattermost/mattermost-server/v6 v6.0.0-20221109191448-21aec2741bfe github.com/microcosm-cc/bluemonday v1.0.19 diff --git a/go.sum b/go.sum index e4f2757ae..7b2fea0ee 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= -github.com/mattermost/mattermost-plugin-api v0.1.3-0.20230323124751-86c7be7ffbac h1:fxdqYaw6wJfMSodMP0SNPm31r9kJ0NI8uQiWVpnj8F0= -github.com/mattermost/mattermost-plugin-api v0.1.3-0.20230323124751-86c7be7ffbac/go.mod h1:EON5x6XoqubANT9zYLuL+m42SijzpK/dDOuu76PGbSc= +github.com/mattermost/mattermost-plugin-api v0.1.3 h1:Z5KBAV/Lpsf1NleSRSeun3jPQOIvN3/G+Xw5DqB2rac= +github.com/mattermost/mattermost-plugin-api v0.1.3/go.mod h1:EON5x6XoqubANT9zYLuL+m42SijzpK/dDOuu76PGbSc= github.com/mattermost/mattermost-server/v6 v6.0.0-20221109191448-21aec2741bfe h1:9P759/e7xB3IQYo+6Ju9qsj3YUxpnPRXl2x+XFFsRIM= github.com/mattermost/mattermost-server/v6 v6.0.0-20221109191448-21aec2741bfe/go.mod h1:Eu6nct2XZRPlHHW4MfZtjli5bY7G9QomKcor/lm+0Sw= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= diff --git a/server/plugin/api.go b/server/plugin/api.go index 828d43747..97103c152 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -16,6 +16,7 @@ import ( "github.com/pkg/errors" "golang.org/x/oauth2" + pluginapi "github.com/mattermost/mattermost-plugin-api" "github.com/mattermost/mattermost-plugin-api/experimental/bot/logger" "github.com/mattermost/mattermost-plugin-api/experimental/flow" "github.com/mattermost/mattermost-server/v6/model" @@ -86,13 +87,13 @@ const ( func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) { b, err := json.Marshal(v) if err != nil { - p.API.LogWarn("Failed to marshal JSON response", "error", err.Error()) + p.client.Log.Warn("Failed to marshal JSON response", "error", err.Error()) w.WriteHeader(http.StatusInternalServerError) return } _, err = w.Write(b) if err != nil { - p.API.LogWarn("Failed to write JSON response", "error", err.Error()) + p.client.Log.Warn("Failed to write JSON response", "error", err.Error()) w.WriteHeader(http.StatusInternalServerError) return } @@ -101,7 +102,7 @@ func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) { func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *APIErrorResponse) { b, err := json.Marshal(apiErr) if err != nil { - p.API.LogWarn("Failed to marshal API error", "error", err.Error()) + p.client.Log.Warn("Failed to marshal API error", "error", err.Error()) w.WriteHeader(http.StatusInternalServerError) return } @@ -110,7 +111,7 @@ func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *APIErrorResponse) _, err = w.Write(b) if err != nil { - p.API.LogWarn("Failed to write JSON response", "error", err.Error()) + p.client.Log.Warn("Failed to write JSON response", "error", err.Error()) w.WriteHeader(http.StatusInternalServerError) return } @@ -158,7 +159,7 @@ func (p *Plugin) withRecovery(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if x := recover(); x != nil { - p.API.LogWarn("Recovered from a panic", + p.client.Log.Warn("Recovered from a panic", "url", r.URL.String(), "error", x, "stack", string(debug.Stack())) @@ -192,7 +193,7 @@ func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType) case ResponseTypePlain: http.Error(w, "Not authorized", http.StatusUnauthorized) default: - p.API.LogDebug("Unknown ResponseType detected") + p.client.Log.Debug("Unknown ResponseType detected") } return } @@ -286,14 +287,8 @@ func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http. PrivateAllowed: privateAllowed, } - stateBytes, err := json.Marshal(state) + _, err := p.client.KV.Set(githubOauthKey+state.Token, state, pluginapi.SetExpiry(TokenTTL)) if err != nil { - http.Error(w, "json marshal failed", http.StatusInternalServerError) - return - } - - appErr := p.API.KVSetWithExpiry(githubOauthKey+state.Token, stateBytes, TokenTTL) - if appErr != nil { http.Error(w, "error setting stored state", http.StatusBadRequest) return } @@ -347,27 +342,21 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter, stateToken := r.URL.Query().Get("state") - storedState, appErr := p.API.KVGet(githubOauthKey + stateToken) - if appErr != nil { - c.Log.Warnf("Failed to get state token", "error", appErr.Error()) - - rErr = errors.Wrap(appErr, "missing stored state") - http.Error(w, rErr.Error(), http.StatusBadRequest) - return - } var state OAuthState + err := p.client.KV.Get(githubOauthKey+stateToken, &state) + if err != nil { + c.Log.Warnf("Failed to get state token", "error", err.Error()) - if err := json.Unmarshal(storedState, &state); err != nil { - rErr = errors.Wrap(err, "json unmarshal failed") - http.Error(w, err.Error(), http.StatusBadRequest) + rErr = errors.Wrap(err, "missing stored state") + http.Error(w, rErr.Error(), http.StatusBadRequest) return } - appErr = p.API.KVDelete(githubOauthKey + stateToken) - if appErr != nil { - c.Log.WithError(appErr).Warnf("Failed to delete state token") + err = p.client.KV.Delete(githubOauthKey + stateToken) + if err != nil { + c.Log.WithError(err).Warnf("Failed to delete state token") - rErr = errors.Wrap(appErr, "error deleting stored state") + rErr = errors.Wrap(err, "error deleting stored state") http.Error(w, rErr.Error(), http.StatusBadRequest) return } @@ -483,7 +472,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter, config := p.getConfiguration() - p.API.PublishWebSocketEvent( + p.client.Frontend.PublishWebSocketEvent( wsEventConnect, map[string]interface{}{ "connected": true, @@ -621,7 +610,8 @@ func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request privateRepoStoreKey := info.UserID + githubPrivateRepoKey if config.EnablePrivateRepo && !info.AllowedPrivateRepos { - val, err := p.API.KVGet(privateRepoStoreKey) + var val []byte + err := p.client.KV.Get(privateRepoStoreKey, &val) if err != nil { c.Log.WithError(err).Warnf("Unable to get private repo key value") return @@ -635,7 +625,7 @@ func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request } else { p.CreateBotDMPost(info.UserID, fmt.Sprintf(message, "`/github connect private`."), "") } - err := p.API.KVSet(privateRepoStoreKey, []byte("1")) + _, err := p.client.KV.Set(privateRepoStoreKey, []byte("1")) if err != nil { c.Log.WithError(err).Warnf("Unable to set private repo key value") } @@ -852,7 +842,7 @@ func (p *Plugin) searchIssues(c *UserContext, w http.ResponseWriter, r *http.Req } func (p *Plugin) getPermaLink(postID string) string { - siteURL := *p.API.GetConfig().ServiceSettings.SiteURL + siteURL := *p.client.Configuration.GetConfig().ServiceSettings.SiteURL return fmt.Sprintf("%v/_redirect/pl/%v", siteURL, postID) } @@ -919,8 +909,8 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo) - post, appErr := p.API.GetPost(req.PostID) - if appErr != nil { + post, err := p.client.Post.GetPost(req.PostID) + if err != nil { p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + req.PostID, StatusCode: http.StatusInternalServerError}) return } @@ -968,8 +958,8 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht UserId: c.UserID, } - _, appErr = p.API.CreatePost(reply) - if appErr != nil { + err = p.client.Post.CreatePost(reply) + if err != nil { p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create notification post " + req.PostID, StatusCode: http.StatusInternalServerError}) return } @@ -1206,41 +1196,75 @@ func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Re p.writeJSON(w, allMilestones) } +func getRepositoryList(c context.Context, userName string, githubClient *github.Client, opt github.ListOptions) ([]*github.Repository, error) { + var allRepos []*github.Repository + for { + repos, resp, err := githubClient.Repositories.List(c, userName, &github.RepositoryListOptions{ListOptions: opt}) + if err != nil { + return nil, err + } + + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + + opt.Page = resp.NextPage + } + + return allRepos, nil +} + +func getRepositoryListByOrg(c context.Context, org string, githubClient *github.Client, opt github.ListOptions) ([]*github.Repository, int, error) { + var allRepos []*github.Repository + for { + repos, resp, err := githubClient.Repositories.ListByOrg(c, org, &github.RepositoryListByOrgOptions{Sort: "full_name", ListOptions: opt}) + if err != nil { + return nil, resp.StatusCode, err + } + + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + + return allRepos, http.StatusOK, nil +} + func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.Request) { githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo) org := p.getConfiguration().GitHubOrg var allRepos []*github.Repository + var err error + var statusCode int opt := github.ListOptions{PerPage: 50} if org == "" { - for { - repos, resp, err := githubClient.Repositories.List(c.Ctx, "", &github.RepositoryListOptions{ListOptions: opt}) - if err != nil { - c.Log.WithError(err).Warnf("Failed to list repositories") - p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError}) - return - } - allRepos = append(allRepos, repos...) - if resp.NextPage == 0 { - break - } - opt.Page = resp.NextPage + allRepos, err = getRepositoryList(c.Ctx, "", githubClient, opt) + if err != nil { + c.Log.WithError(err).Warnf("Failed to list repositories") + p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError}) + return } } else { - for { - repos, resp, err := githubClient.Repositories.ListByOrg(c.Ctx, org, &github.RepositoryListByOrgOptions{Sort: "full_name", ListOptions: opt}) - if err != nil { - c.Log.WithError(err).Warnf("Failed to list repositories by org") + allRepos, statusCode, err = getRepositoryListByOrg(c.Ctx, org, githubClient, opt) + if err != nil { + if statusCode == http.StatusNotFound { + allRepos, err = getRepositoryList(c.Ctx, org, githubClient, opt) + if err != nil { + c.Log.WithError(err).Warnf("Failed to list repositories") + p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError}) + return + } + } else { + c.Log.WithError(err).Warnf("Failed to list repositories") p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError}) return } - allRepos = append(allRepos, repos...) - if resp.NextPage == 0 { - break - } - opt.Page = resp.NextPage } } @@ -1275,6 +1299,7 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ // get data for the issue from the request body and fill IssueRequest object issue := &IssueRequest{} + if err := json.NewDecoder(r.Body).Decode(&issue); err != nil { c.Log.WithError(err).Warnf("Error decoding JSON body") p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object.", StatusCode: http.StatusBadRequest}) @@ -1300,9 +1325,9 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ var post *model.Post permalink := "" if issue.PostID != "" { - var appErr *model.AppError - post, appErr = p.API.GetPost(issue.PostID) - if appErr != nil { + var err error + post, err = p.client.Post.GetPost(issue.PostID) + if err != nil { p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + issue.PostID, StatusCode: http.StatusInternalServerError}) return } @@ -1340,8 +1365,8 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ } *ghIssue.Body = ghIssue.GetBody() + mmMessage - currentUser, appErr := p.API.GetUser(c.UserID) - if appErr != nil { + currentUser, err := p.client.User.Get(c.UserID) + if err != nil { p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError}) return } @@ -1390,12 +1415,12 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ } if post != nil { - _, appErr = p.API.CreatePost(reply) + err = p.client.Post.CreatePost(reply) } else { - p.API.SendEphemeralPost(c.UserID, reply) + p.client.Post.SendEphemeralPost(c.UserID, reply) } - if appErr != nil { - c.Log.WithError(appErr).Warnf("failed to create notification post") + if err != nil { + c.Log.WithError(err).Warnf("failed to create notification post") p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create notification post, postID: " + issue.PostID + ", channelID: " + channelID, StatusCode: http.StatusInternalServerError}) return } diff --git a/server/plugin/api_test.go b/server/plugin/api_test.go index 41d559ee6..c1e9ad81c 100644 --- a/server/plugin/api_test.go +++ b/server/plugin/api_test.go @@ -6,6 +6,7 @@ import ( "net/http/httptest" "testing" + pluginapi "github.com/mattermost/mattermost-plugin-api" "github.com/mattermost/mattermost-server/v6/plugin" "github.com/mattermost/mattermost-server/v6/plugin/plugintest" "github.com/stretchr/testify/mock" @@ -36,6 +37,7 @@ func TestWithRecovery(t *testing.T) { "error", "bad handler", "stack", mock.Anything) p.SetAPI(api) + p.client = pluginapi.NewClient(p.API, p.Driver) ph := panicHandler{} handler := p.withRecovery(ph) diff --git a/server/plugin/cluster.go b/server/plugin/cluster.go index 375f0ca41..f34b44bda 100644 --- a/server/plugin/cluster.go +++ b/server/plugin/cluster.go @@ -23,7 +23,7 @@ func (p *Plugin) sendOAuthCompleteEvent(event OAuthCompleteEvent) { func (p *Plugin) sendMessageToCluster(id string, v interface{}) { b, err := json.Marshal(v) if err != nil { - p.API.LogWarn("couldn't get JSON bytes from cluster message", + p.client.Log.Warn("couldn't get JSON bytes from cluster message", "id", id, "error", err, ) @@ -35,8 +35,8 @@ func (p *Plugin) sendMessageToCluster(id string, v interface{}) { SendType: model.PluginClusterEventSendTypeReliable, } - if err := p.API.PublishPluginClusterEvent(event, opts); err != nil { - p.API.LogWarn("error publishing cluster event", + if err := p.client.Cluster.PublishPluginEvent(event, opts); err != nil { + p.client.Log.Warn("error publishing cluster event", "id", id, "error", err, ) @@ -48,7 +48,7 @@ func (p *Plugin) HandleClusterEvent(ev model.PluginClusterEvent) { case webHookPingEventID: var event github.PingEvent if err := json.Unmarshal(ev.Data, &event); err != nil { - p.API.LogWarn("cannot unmarshal cluster event with GitHub ping event", "error", err) + p.client.Log.Warn("cannot unmarshal cluster event with GitHub ping event", "error", err) return } @@ -56,12 +56,12 @@ func (p *Plugin) HandleClusterEvent(ev model.PluginClusterEvent) { case oauthCompleteEventID: var event OAuthCompleteEvent if err := json.Unmarshal(ev.Data, &event); err != nil { - p.API.LogWarn("cannot unmarshal cluster event with OAuth complete event", "error", err) + p.client.Log.Warn("cannot unmarshal cluster event with OAuth complete event", "error", err) return } p.oauthBroker.publishOAuthComplete(event.UserID, event.Err, true) default: - p.API.LogWarn("unknown cluster event", "id", ev.Id) + p.client.Log.Warn("unknown cluster event", "id", ev.Id) } } diff --git a/server/plugin/command.go b/server/plugin/command.go index bb1549725..4e344da85 100644 --- a/server/plugin/command.go +++ b/server/plugin/command.go @@ -68,7 +68,7 @@ func validateFeatures(features []string) (bool, []string) { } func (p *Plugin) getCommand(config *Configuration) (*model.Command, error) { - iconData, err := command.GetIconData(p.API, "assets/icon-bg.svg") + iconData, err := command.GetIconData(&p.client.System, "assets/icon-bg.svg") if err != nil { return nil, errors.Wrap(err, "failed to get icon data") } @@ -90,11 +90,12 @@ func (p *Plugin) postCommandResponse(args *model.CommandArgs, text string) { RootId: args.RootId, Message: text, } - _ = p.API.SendEphemeralPost(args.UserId, post) + p.client.Post.SendEphemeralPost(args.UserId, post) } func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) []string { - mutedUsernameBytes, err := p.API.KVGet(userInfo.UserID + "-muted-users") + var mutedUsernameBytes []byte + err := p.client.KV.Get(userInfo.UserID+"-muted-users", &mutedUsernameBytes) if err != nil { return nil } @@ -145,9 +146,12 @@ func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInf } else { mutedUsers = username } - if err := p.API.KVSet(userInfo.UserID+"-muted-users", []byte(mutedUsers)); err != nil { + + _, err := p.client.KV.Set(userInfo.UserID+"-muted-users", []byte(mutedUsers)) + if err != nil { return "Error occurred saving list of muted users" } + return fmt.Sprintf("`%v`", username) + " is now muted. You'll no longer receive notifications for comments in your PRs and issues." } @@ -155,16 +159,21 @@ func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo mutedUsernames := p.getMutedUsernames(userInfo) userToMute := []string{username} newMutedList := arrayDifference(mutedUsernames, userToMute) - if err := p.API.KVSet(userInfo.UserID+"-muted-users", []byte(strings.Join(newMutedList, ","))); err != nil { + + _, err := p.client.KV.Set(userInfo.UserID+"-muted-users", []byte(strings.Join(newMutedList, ","))) + if err != nil { return "Error occurred unmuting users" } + return fmt.Sprintf("`%v`", username) + " is no longer muted" } func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *GitHubUserInfo) string { - if err := p.API.KVSet(userInfo.UserID+"-muted-users", []byte("")); err != nil { + _, err := p.client.KV.Set(userInfo.UserID+"-muted-users", []byte("")) + if err != nil { return "Error occurred unmuting users" } + return "Unmuted all users" } @@ -337,7 +346,7 @@ func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, ghRepo, _, err := githubClient.Repositories.Get(ctx, owner, repo) if err != nil { - p.API.LogWarn("Failed to fetch repository", "error", err.Error()) + p.client.Log.Warn("Failed to fetch repository", "error", err.Error()) } else if ghRepo != nil && ghRepo.GetPrivate() { msg += "\n\n**Warning:** You subscribed to a private repository. Anyone with access to this channel will be able to read the events getting posted here." } @@ -353,7 +362,7 @@ func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, p repo := parameters[0] if err := p.Unsubscribe(args.ChannelId, repo); err != nil { - p.API.LogWarn("Failed to unsubscribe", "repo", repo, "error", err.Error()) + p.client.Log.Warn("Failed to unsubscribe", "repo", repo, "error", err.Error()) return "Encountered an error trying to unsubscribe. Please try again." } @@ -370,7 +379,7 @@ func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string, text, err := p.GetToDo(context.Background(), userInfo.GitHubUsername, githubClient) if err != nil { - p.API.LogWarn("Failed get get Todos", "error", err.Error()) + p.client.Log.Warn("Failed get get Todos", "error", err.Error()) return "Encountered an error getting your to do items." } @@ -391,7 +400,7 @@ func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, u func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *GitHubUserInfo) string { message, err := renderTemplate("helpText", p.getConfiguration()) if err != nil { - p.API.LogWarn("Failed to render help template", "error", err.Error()) + p.client.Log.Warn("Failed to render help template", "error", err.Error()) return "Encountered an error posting help text." } @@ -438,15 +447,15 @@ func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, paramet if userInfo.Settings.Notifications { err := p.storeGitHubToUserIDMapping(userInfo.GitHubUsername, userInfo.UserID) if err != nil { - p.API.LogWarn("Failed to store GitHub to userID mapping", + p.client.Log.Warn("Failed to store GitHub to userID mapping", "userID", userInfo.UserID, "GitHub username", userInfo.GitHubUsername, "error", err.Error()) } } else { - err := p.API.KVDelete(userInfo.GitHubUsername + githubUsernameKey) + err := p.client.KV.Delete(userInfo.GitHubUsername + githubUsernameKey) if err != nil { - p.API.LogWarn("Failed to delete GitHub to userID mapping", + p.client.Log.Warn("Failed to delete GitHub to userID mapping", "userID", userInfo.UserID, "GitHub username", userInfo.GitHubUsername, "error", err.Error()) @@ -456,7 +465,7 @@ func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, paramet err := p.storeGitHubUserInfo(userInfo) if err != nil { - p.API.LogWarn("Failed to store github user info", "error", err.Error()) + p.client.Log.Warn("Failed to store github user info", "error", err.Error()) return "Failed to store settings" } @@ -484,7 +493,7 @@ func (p *Plugin) handleSetup(c *plugin.Context, args *model.CommandArgs, paramet userID := args.UserId isSysAdmin, err := p.isAuthorizedSysAdmin(userID) if err != nil { - p.API.LogWarn("Failed to check if user is System Admin", "error", err.Error()) + p.client.Log.Warn("Failed to check if user is System Admin", "error", err.Error()) return "Error checking user's permissions" } @@ -520,9 +529,9 @@ func (p *Plugin) handleSetup(c *plugin.Context, args *model.CommandArgs, paramet type CommandHandleFunc func(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string func (p *Plugin) isAuthorizedSysAdmin(userID string) (bool, error) { - user, appErr := p.API.GetUser(userID) - if appErr != nil { - return false, appErr + user, err := p.client.User.Get(userID) + if err != nil { + return false, err } if !strings.Contains(user.Roles, "system_admin") { return false, nil @@ -562,7 +571,7 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo switch { case err != nil: text = "Error checking user's permissions" - p.API.LogWarn(text, "error", err.Error()) + p.client.Log.Warn(text, "error", err.Error()) case isSysAdmin: text = fmt.Sprintf("Before using this plugin, you'll need to configure it by running `/github setup`: %s", validationErr.Error()) default: @@ -574,7 +583,7 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo } if action == "connect" { - siteURL := p.API.GetConfig().ServiceSettings.SiteURL + siteURL := p.client.Configuration.GetConfig().ServiceSettings.SiteURL if siteURL == nil { p.postCommandResponse(args, "Encountered an error connecting to GitHub.") return &model.CommandResponse{}, nil diff --git a/server/plugin/configuration.go b/server/plugin/configuration.go index 900275f47..d320c7dd2 100644 --- a/server/plugin/configuration.go +++ b/server/plugin/configuration.go @@ -7,6 +7,7 @@ import ( "reflect" "strings" + pluginapi "github.com/mattermost/mattermost-plugin-api" "github.com/mattermost/mattermost-plugin-api/experimental/telemetry" "github.com/mattermost/mattermost-server/v6/model" "github.com/pkg/errors" @@ -190,10 +191,15 @@ func (p *Plugin) setConfiguration(configuration *Configuration) { // OnConfigurationChange is invoked when configuration changes may have been made. func (p *Plugin) OnConfigurationChange() error { + if p.client == nil { + p.client = pluginapi.NewClient(p.API, p.Driver) + } + var configuration = new(Configuration) // Load the public configuration fields from the Mattermost server configuration. - if err := p.API.LoadPluginConfiguration(configuration); err != nil { + err := p.client.Configuration.LoadPluginConfiguration(configuration) + if err != nil { return errors.Wrap(err, "failed to load plugin configuration") } @@ -208,13 +214,13 @@ func (p *Plugin) OnConfigurationChange() error { return errors.Wrap(err, "failed to get command") } - err = p.API.RegisterCommand(command) + err = p.client.SlashCommand.Register(command) if err != nil { return errors.Wrap(err, "failed to register command") } // Some config changes require reloading tracking config if p.tracker != nil { - p.tracker.ReloadConfig(telemetry.NewTrackerConfig(p.API.GetConfig())) + p.tracker.ReloadConfig(telemetry.NewTrackerConfig(p.client.Configuration.GetConfig())) } return nil @@ -225,7 +231,7 @@ func (p *Plugin) sendWebsocketEventIfNeeded(oldConfig, newConfig *Configuration) // Hence, an unnecessary websocket event is sent. // Given that oldConfig is never nil, that case is hard to catch. if !reflect.DeepEqual(oldConfig.ClientConfiguration(), newConfig.ClientConfiguration()) { - p.API.PublishWebSocketEvent( + p.client.Frontend.PublishWebSocketEvent( WSEventConfigUpdate, newConfig.ClientConfiguration(), &model.WebsocketBroadcast{}, diff --git a/server/plugin/mm_34646_token_refresh.go b/server/plugin/mm_34646_token_refresh.go index d1c0a6df1..abedb363a 100644 --- a/server/plugin/mm_34646_token_refresh.go +++ b/server/plugin/mm_34646_token_refresh.go @@ -2,7 +2,6 @@ package plugin import ( "context" - "encoding/json" "time" "github.com/google/go-github/v41/github" @@ -20,9 +19,10 @@ func (p *Plugin) forceResetAllMM34646() error { ctx := context.Background() time.Sleep(delayToStart) - data, appErr := p.API.KVGet(mm34646DoneKey) - if appErr != nil { - return errors.Wrap(appErr, "failed check whether MM-34646 refresh is already done") + var data []byte + err := p.client.KV.Get(mm34646DoneKey, &data) + if err != nil { + return errors.Wrap(err, "failed check whether MM-34646 refresh is already done") } if len(data) > 0 { // Already done @@ -37,24 +37,21 @@ func (p *Plugin) forceResetAllMM34646() error { defer m.Unlock() for page := 0; ; page++ { - keys, appErr := p.API.KVList(page, pageSize) - if appErr != nil { - return appErr + var keys []string + keys, err = p.client.KV.ListKeys(page, pageSize) + if err != nil { + return err } for _, key := range keys { - data, appErr := p.API.KVGet(key) - if appErr != nil { - p.API.LogWarn("failed to inspect key", "key", key, "error", - appErr.Error()) - continue - } - tryInfo := GitHubUserInfo{} - err := json.Unmarshal(data, &tryInfo) + var tryInfo GitHubUserInfo + err = p.client.KV.Get(key, &tryInfo) if err != nil { - // too noisy to report + p.client.Log.Warn("failed to inspect key", "key", key, "error", + err.Error()) continue } + if tryInfo.MM34646ResetTokenDone { continue } @@ -65,14 +62,14 @@ func (p *Plugin) forceResetAllMM34646() error { info, errResp := p.getGitHubUserInfo(tryInfo.UserID) if errResp != nil { - p.API.LogWarn("failed to retrieve GitHubUserInfo", "key", key, "user_id", tryInfo.UserID, + p.client.Log.Warn("failed to retrieve GitHubUserInfo", "key", key, "user_id", tryInfo.UserID, "error", errResp.Error()) continue } _, err = p.forceResetUserTokenMM34646(ctx, config, info) if err != nil { - p.API.LogWarn("failed to reset GitHub user token", "key", key, "user_id", tryInfo.UserID, + p.client.Log.Warn("failed to reset GitHub user token", "key", key, "user_id", tryInfo.UserID, "error", err.Error()) continue } @@ -85,7 +82,11 @@ func (p *Plugin) forceResetAllMM34646() error { } } - _ = p.API.KVSet(mm34646DoneKey, []byte("done")) + _, err = p.client.KV.Set(mm34646DoneKey, []byte("done")) + if err != nil { + return err + } + return nil } @@ -113,7 +114,7 @@ func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configu if err != nil { return "", errors.Wrap(err, "failed to store updated GitHubUserInfo") } - p.API.LogDebug("Updated user access token for MM-34646", "user_id", info.UserID) + p.client.Log.Debug("Updated user access token for MM-34646", "user_id", info.UserID) return *a.Token, nil } diff --git a/server/plugin/permalinks.go b/server/plugin/permalinks.go index e0cc3a0dd..ae1914d40 100644 --- a/server/plugin/permalinks.go +++ b/server/plugin/permalinks.go @@ -96,7 +96,7 @@ func (p *Plugin) makeReplacements(msg string, replacements []replacement, ghClie r := replacements[i] // quick bailout if the commit hash is not proper. if _, err := hex.DecodeString(r.permalinkInfo.commit); err != nil { - p.API.LogWarn("Bad git commit hash in permalink", "error", err.Error(), "hash", r.permalinkInfo.commit) + p.client.Log.Warn("Bad git commit hash in permalink", "error", err.Error(), "hash", r.permalinkInfo.commit) continue } @@ -107,7 +107,7 @@ func (p *Plugin) makeReplacements(msg string, replacements []replacement, ghClie if config.EnableCodePreview != "privateAndPublic" { repo, _, err := ghClient.Repositories.Get(ctx, r.permalinkInfo.user, r.permalinkInfo.repo) if err != nil { - p.API.LogWarn("Error while fetching repository information", + p.client.Log.Warn("Error while fetching repository information", "error", err.Error(), "repo", r.permalinkInfo.repo, "user", r.permalinkInfo.user) @@ -127,17 +127,17 @@ func (p *Plugin) makeReplacements(msg string, replacements []replacement, ghClie fileContent, _, _, err := ghClient.Repositories.GetContents(ctx, r.permalinkInfo.user, r.permalinkInfo.repo, r.permalinkInfo.path, &opts) if err != nil { - p.API.LogWarn("Error while fetching file contents", "error", err.Error(), "path", r.permalinkInfo.path) + p.client.Log.Warn("Error while fetching file contents", "error", err.Error(), "path", r.permalinkInfo.path) continue } // this is not a file, ignore. if fileContent == nil { - p.API.LogWarn("Permalink is not a file", "file", r.permalinkInfo.path) + p.client.Log.Warn("Permalink is not a file", "file", r.permalinkInfo.path) continue } decoded, err := fileContent.GetContent() if err != nil { - p.API.LogWarn("Error while decoding file contents", "error", err.Error(), "path", r.permalinkInfo.path) + p.client.Log.Warn("Error while decoding file contents", "error", err.Error(), "path", r.permalinkInfo.path) continue } @@ -154,10 +154,10 @@ func (p *Plugin) makeReplacements(msg string, replacements []replacement, ghClie } lines, err := filterLines(decoded, start, end) if err != nil { - p.API.LogWarn("Error while filtering lines", "error", err.Error(), "path", r.permalinkInfo.path) + p.client.Log.Warn("Error while filtering lines", "error", err.Error(), "path", r.permalinkInfo.path) } if lines == "" { - p.API.LogWarn("Line numbers out of range. Skipping.", "file", r.permalinkInfo.path, "start", start, "end", end) + p.client.Log.Warn("Line numbers out of range. Skipping.", "file", r.permalinkInfo.path, "start", start, "end", end) continue } final := getCodeMarkdown(r.permalinkInfo.user, r.permalinkInfo.repo, r.permalinkInfo.path, r.word, lines, isTruncated) diff --git a/server/plugin/permalinks_test.go b/server/plugin/permalinks_test.go index 98b813526..e29ae2d43 100644 --- a/server/plugin/permalinks_test.go +++ b/server/plugin/permalinks_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/google/go-github/v41/github" + pluginapi "github.com/mattermost/mattermost-plugin-api" "github.com/mattermost/mattermost-server/v6/plugin/plugintest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -273,6 +274,7 @@ func TestMakeReplacements(t *testing.T) { mockPluginAPI.On("LogWarn", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything) mockPluginAPI.On("LogWarn", mock.Anything, mock.Anything) p.SetAPI(mockPluginAPI) + p.client = pluginapi.NewClient(p.API, p.Driver) tcs := []struct { name string diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go index 5e8414d5f..ec711017c 100644 --- a/server/plugin/plugin.go +++ b/server/plugin/plugin.go @@ -2,7 +2,6 @@ package plugin import ( "context" - "encoding/json" "fmt" "net/http" "net/url" @@ -164,7 +163,7 @@ func (p *Plugin) githubConnectToken(token oauth2.Token) *github.Client { client, err := GetGitHubClient(token, config) if err != nil { - p.API.LogWarn("Failed to create GitHub client", "error", err.Error()) + p.client.Log.Warn("Failed to create GitHub client", "error", err.Error()) return nil } @@ -200,7 +199,7 @@ func getGitHubClient(authenticatedClient *http.Client, config *Configuration) (* func (p *Plugin) setDefaultConfiguration() error { config := p.getConfiguration() - changed, err := config.setDefaults(pluginapi.IsCloud(p.API.GetLicense())) + changed, err := config.setDefaults(pluginapi.IsCloud(p.client.System.GetLicense())) if err != nil { return err } @@ -211,9 +210,9 @@ func (p *Plugin) setDefaultConfiguration() error { return err } - appErr := p.API.SavePluginConfig(configMap) - if appErr != nil { - return appErr + err = p.client.Configuration.SavePluginConfig(configMap) + if err != nil { + return err } } @@ -221,9 +220,11 @@ func (p *Plugin) setDefaultConfiguration() error { } func (p *Plugin) OnActivate() error { - p.client = pluginapi.NewClient(p.API, p.Driver) + if p.client == nil { + p.client = pluginapi.NewClient(p.API, p.Driver) + } - siteURL := p.API.GetConfig().ServiceSettings.SiteURL + siteURL := p.client.Configuration.GetConfig().ServiceSettings.SiteURL if siteURL == nil || *siteURL == "" { return errors.New("siteURL is not set. Please set it and restart the plugin") } @@ -265,7 +266,7 @@ func (p *Plugin) OnActivate() error { go func() { resetErr := p.forceResetAllMM34646() if resetErr != nil { - p.API.LogDebug("failed to reset user tokens", "error", resetErr.Error()) + p.client.Log.Debug("failed to reset user tokens", "error", resetErr.Error()) } }() return nil @@ -283,7 +284,7 @@ func (p *Plugin) OnDeactivate() error { func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo string, id float64, objectType string, ok bool) { post, err := p.client.Post.GetPost(reaction.PostId) if err != nil { - p.API.LogDebug("Error fetching post for reaction", "error", err.Error()) + p.client.Log.Debug("Error fetching post for reaction", "error", err.Error()) return org, repo, id, objectType, false } @@ -295,7 +296,7 @@ func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo st orgRepo := strings.Split(repo, "/") if len(orgRepo) != 2 { - p.API.LogDebug("Invalid organization repository") + p.client.Log.Debug("Invalid organization repository") return org, repo, id, objectType, false } @@ -319,7 +320,7 @@ func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo st func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reaction) { githubEmoji := p.emojiMap[reaction.EmojiName] if githubEmoji == "" { - p.API.LogWarn("Emoji is not supported by Github", "Emoji", reaction.EmojiName) + p.client.Log.Warn("Emoji is not supported by Github", "Emoji", reaction.EmojiName) return } @@ -331,7 +332,7 @@ func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reactio info, appErr := p.getGitHubUserInfo(reaction.UserId) if appErr != nil { if appErr.ID != apiErrorIDNotConnected { - p.API.LogDebug("Error in getting user info", "error", appErr.Error()) + p.client.Log.Debug("Error in getting user info", "error", appErr.Error()) } return } @@ -342,17 +343,17 @@ func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reactio switch objectType { case githubObjectTypeIssueComment: if _, _, err := ghClient.Reactions.CreateIssueCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil { - p.API.LogDebug("Error occurred while creating issue comment reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while creating issue comment reaction", "error", err.Error()) return } case githubObjectTypeIssue: if _, _, err := ghClient.Reactions.CreateIssueReaction(context.Background(), owner, repo, int(id), githubEmoji); err != nil { - p.API.LogDebug("Error occurred while creating issue reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while creating issue reaction", "error", err.Error()) return } case githubObjectTypePRReviewComment: if _, _, err := ghClient.Reactions.CreatePullRequestCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil { - p.API.LogDebug("Error occurred while creating PR review comment reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while creating PR review comment reaction", "error", err.Error()) return } default: @@ -363,7 +364,7 @@ func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reactio func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.Reaction) { githubEmoji := p.emojiMap[reaction.EmojiName] if githubEmoji == "" { - p.API.LogWarn("Emoji is not supported by Github", "Emoji", reaction.EmojiName) + p.client.Log.Warn("Emoji is not supported by Github", "Emoji", reaction.EmojiName) return } @@ -375,7 +376,7 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React info, appErr := p.getGitHubUserInfo(reaction.UserId) if appErr != nil { if appErr.ID != apiErrorIDNotConnected { - p.API.LogDebug("Error in getting user info", "error", appErr.Error()) + p.client.Log.Debug("Error in getting user info", "error", appErr.Error()) } return } @@ -387,14 +388,14 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React case githubObjectTypeIssueComment: reactions, _, err := ghClient.Reactions.ListIssueCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{}) if err != nil { - p.API.LogDebug("Error getting issue comment reaction list", "error", err.Error()) + p.client.Log.Debug("Error getting issue comment reaction list", "error", err.Error()) return } for _, reactionObj := range reactions { if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() { if _, err = ghClient.Reactions.DeleteIssueCommentReaction(context.Background(), owner, repo, int64(id), reactionObj.GetID()); err != nil { - p.API.LogDebug("Error occurred while removing issue comment reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while removing issue comment reaction", "error", err.Error()) } return } @@ -402,14 +403,14 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React case githubObjectTypeIssue: reactions, _, err := ghClient.Reactions.ListIssueReactions(context.Background(), owner, repo, int(id), &github.ListOptions{}) if err != nil { - p.API.LogDebug("Error getting issue reaction list", "error", err.Error()) + p.client.Log.Debug("Error getting issue reaction list", "error", err.Error()) return } for _, reactionObj := range reactions { if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() { if _, err = ghClient.Reactions.DeleteIssueReaction(context.Background(), owner, repo, int(id), reactionObj.GetID()); err != nil { - p.API.LogDebug("Error occurred while removing issue reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while removing issue reaction", "error", err.Error()) } return } @@ -417,14 +418,14 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React case githubObjectTypePRReviewComment: reactions, _, err := ghClient.Reactions.ListPullRequestCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{}) if err != nil { - p.API.LogDebug("Error getting PR review comment reaction list", "error", err.Error()) + p.client.Log.Debug("Error getting PR review comment reaction list", "error", err.Error()) return } for _, reactionObj := range reactions { if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() { if _, err = ghClient.Reactions.DeletePullRequestCommentReaction(context.Background(), owner, repo, int64(id), reactionObj.GetID()); err != nil { - p.API.LogDebug("Error occurred while removing PR review comment reaction", "error", err.Error()) + p.client.Log.Debug("Error occurred while removing PR review comment reaction", "error", err.Error()) } return } @@ -453,7 +454,7 @@ func (p *Plugin) OnPluginClusterEvent(c *plugin.Context, ev model.PluginClusterE // registerChimeraURL fetches the Chimera URL from server settings or env var and sets it in the plugin object. func (p *Plugin) registerChimeraURL() { - chimeraURLSetting := p.API.GetConfig().PluginSettings.ChimeraOAuthProxyURL + chimeraURLSetting := p.client.Configuration.GetConfig().PluginSettings.ChimeraOAuthProxyURL if chimeraURLSetting != nil { p.chimeraURL = *chimeraURLSetting } @@ -470,11 +471,9 @@ func (p *Plugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode return nil, "" } - client := pluginapi.NewClient(p.API, p.Driver) - - shouldProcessMessage, err := client.Post.ShouldProcessMessage(post) + shouldProcessMessage, err := p.client.Post.ShouldProcessMessage(post) if err != nil { - p.API.LogWarn("Error while checking if the message should be processed", "error", err.Error()) + p.client.Log.Warn("Error while checking if the message should be processed", "error", err.Error()) return nil, "" } @@ -486,7 +485,7 @@ func (p *Plugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode info, appErr := p.getGitHubUserInfo(post.UserId) if appErr != nil { if appErr.ID != apiErrorIDNotConnected { - p.API.LogWarn("Error in getting user info", "error", appErr.Message) + p.client.Log.Warn("Error in getting user info", "error", appErr.Message) } return nil, "" } @@ -509,7 +508,7 @@ func (p *Plugin) getOAuthConfig(privateAllowed bool) *oauth2.Config { scopes := []string{string(repo), string(github.ScopeNotifications), string(github.ScopeReadOrg), string(github.ScopeAdminOrgHook)} if config.UsePreregisteredApplication { - p.API.LogDebug("Using Chimera Proxy OAuth configuration") + p.client.Log.Debug("Using Chimera Proxy OAuth configuration") return p.getOAuthConfigForChimeraApp(scopes) } @@ -544,7 +543,7 @@ func (p *Plugin) getOAuthConfigForChimeraApp(scopes []string) *oauth2.Config { authURL.Path = path.Join(authURL.Path, "oauth", "authorize") tokenURL.Path = path.Join(tokenURL.Path, "oauth", "token") - redirectURL, _ := url.Parse(fmt.Sprintf("%s/plugins/github/oauth/complete", *p.API.GetConfig().ServiceSettings.SiteURL)) + redirectURL, _ := url.Parse(fmt.Sprintf("%s/plugins/github/oauth/complete", *p.client.Configuration.GetConfig().ServiceSettings.SiteURL)) return &oauth2.Config{ ClientID: "placeholder", @@ -588,12 +587,7 @@ func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error { info.Token.AccessToken = encryptedToken - jsonInfo, err := json.Marshal(info) - if err != nil { - return errors.Wrap(err, "error while converting user info to json") - } - - if err := p.API.KVSet(info.UserID+githubTokenKey, jsonInfo); err != nil { + if _, err := p.client.KV.Set(info.UserID+githubTokenKey, info); err != nil { return errors.Wrap(err, "error occurred while trying to store user info into KV store") } @@ -603,43 +597,45 @@ func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error { func (p *Plugin) getGitHubUserInfo(userID string) (*GitHubUserInfo, *APIErrorResponse) { config := p.getConfiguration() - var userInfo GitHubUserInfo - - infoBytes, appErr := p.API.KVGet(userID + githubTokenKey) - if appErr != nil || infoBytes == nil { - return nil, &APIErrorResponse{ID: apiErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest} + var userInfo *GitHubUserInfo + err := p.client.KV.Get(userID+githubTokenKey, &userInfo) + if err != nil { + return nil, &APIErrorResponse{ID: "", Message: "Unable to get user info.", StatusCode: http.StatusInternalServerError} } - - if err := json.Unmarshal(infoBytes, &userInfo); err != nil { - return nil, &APIErrorResponse{ID: "", Message: "Unable to parse token.", StatusCode: http.StatusInternalServerError} + if userInfo == nil { + return nil, &APIErrorResponse{ID: apiErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest} } unencryptedToken, err := decrypt([]byte(config.EncryptionKey), userInfo.Token.AccessToken) if err != nil { - p.API.LogWarn("Failed to decrypt access token", "error", err.Error()) + p.client.Log.Warn("Failed to decrypt access token", "error", err.Error()) return nil, &APIErrorResponse{ID: "", Message: "Unable to decrypt access token.", StatusCode: http.StatusInternalServerError} } userInfo.Token.AccessToken = unencryptedToken - return &userInfo, nil + return userInfo, nil } func (p *Plugin) storeGitHubToUserIDMapping(githubUsername, userID string) error { - if err := p.API.KVSet(githubUsername+githubUsernameKey, []byte(userID)); err != nil { - return errors.New("encountered error saving github username mapping") + _, err := p.client.KV.Set(githubUsername+githubUsernameKey, []byte(userID)) + if err != nil { + return errors.Wrap(err, "encountered error saving github username mapping") } + return nil } func (p *Plugin) getGitHubToUserIDMapping(githubUsername string) string { - userID, _ := p.API.KVGet(githubUsername + githubUsernameKey) - return string(userID) + var data []byte + _ = p.client.KV.Get(githubUsername+githubUsernameKey, data) + + return string(data) } // getGitHubToUsernameMapping maps a GitHub username to the corresponding Mattermost username, if any. func (p *Plugin) getGitHubToUsernameMapping(githubUsername string) string { - user, _ := p.API.GetUser(p.getGitHubToUserIDMapping(githubUsername)) + user, _ := p.client.User.Get(p.getGitHubToUserIDMapping(githubUsername)) if user == nil { return "" } @@ -653,29 +649,29 @@ func (p *Plugin) disconnectGitHubAccount(userID string) { return } - if appErr := p.API.KVDelete(userID + githubTokenKey); appErr != nil { - p.API.LogWarn("Failed to delete github token from KV store", "userID", userID, "error", appErr.Error()) + if err := p.client.KV.Delete(userID + githubTokenKey); err != nil { + p.client.Log.Warn("Failed to delete github token from KV store", "userID", userID, "error", err.Error()) } - if appErr := p.API.KVDelete(userInfo.GitHubUsername + githubUsernameKey); appErr != nil { - p.API.LogWarn("Failed to delete github token from KV store", "userID", userID, "error", appErr.Error()) + if err := p.client.KV.Delete(userInfo.GitHubUsername + githubUsernameKey); err != nil { + p.client.Log.Warn("Failed to delete github token from KV store", "userID", userID, "error", err.Error()) } - user, appErr := p.API.GetUser(userID) - if appErr != nil { - p.API.LogWarn("Failed to get user props", "userID", userID, "error", appErr.Error()) + user, err := p.client.User.Get(userID) + if err != nil { + p.client.Log.Warn("Failed to get user props", "userID", userID, "error", err.Error()) } else { _, ok := user.Props["git_user"] if ok { delete(user.Props, "git_user") - _, appErr := p.API.UpdateUser(user) - if appErr != nil { - p.API.LogWarn("Failed to get update user props", "userID", userID, "error", appErr.Error()) + err := p.client.User.Update(user) + if err != nil { + p.client.Log.Warn("Failed to get update user props", "userID", userID, "error", err.Error()) } } } - p.API.PublishWebSocketEvent( + p.client.Frontend.PublishWebSocketEvent( wsEventDisconnect, nil, &model.WebsocketBroadcast{UserId: userID}, @@ -683,7 +679,7 @@ func (p *Plugin) disconnectGitHubAccount(userID string) { } func (p *Plugin) openIssueCreateModal(userID string, channelID string, title string) { - p.API.PublishWebSocketEvent( + p.client.Frontend.PublishWebSocketEvent( wsEventCreateIssue, map[string]interface{}{ "title": title, @@ -696,9 +692,9 @@ func (p *Plugin) openIssueCreateModal(userID string, channelID string, title str // CreateBotDMPost posts a direct message using the bot account. // Any error are not returned and instead logged. func (p *Plugin) CreateBotDMPost(userID, message, postType string) { - channel, err := p.API.GetDirectChannel(userID, p.BotUserID) + channel, err := p.client.Channel.GetDirect(userID, p.BotUserID) if err != nil { - p.API.LogWarn("Couldn't get bot's DM channel", "userID", userID, "error", err.Error()) + p.client.Log.Warn("Couldn't get bot's DM channel", "userID", userID, "error", err.Error()) return } @@ -709,8 +705,8 @@ func (p *Plugin) CreateBotDMPost(userID, message, postType string) { Type: postType, } - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Failed to create DM post", "userID", userID, "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Failed to create DM post", "userID", userID, "post", post, "error", err.Error()) return } } @@ -728,7 +724,8 @@ func (p *Plugin) CheckIfDuplicateDailySummary(userID, text string) (bool, error) } func (p *Plugin) StoreDailySummaryText(userID, summaryText string) error { - if err := p.API.KVSet(userID+dailySummary, []byte(summaryText)); err != nil { + _, err := p.client.KV.Set(userID+dailySummary, []byte(summaryText)) + if err != nil { return err } @@ -736,7 +733,8 @@ func (p *Plugin) StoreDailySummaryText(userID, summaryText string) error { } func (p *Plugin) GetDailySummaryText(userID string) (string, error) { - summaryByte, err := p.API.KVGet(userID + dailySummary) + var summaryByte []byte + err := p.client.KV.Get(userID+dailySummary, summaryByte) if err != nil { return "", err } @@ -802,7 +800,7 @@ func (p *Plugin) GetToDo(ctx context.Context, username string, githubClient *git } if n.GetRepository() == nil { - p.API.LogWarn("Unable to get repository for notification in todo list. Skipping.") + p.client.Log.Warn("Unable to get repository for notification in todo list. Skipping.") continue } @@ -888,28 +886,28 @@ func (p *Plugin) HasUnreads(info *GitHubUserInfo) bool { query := getReviewSearchQuery(username, config.GitHubOrg) issues, _, err := githubClient.Search.Issues(ctx, query, &github.SearchOptions{}) if err != nil { - p.API.LogWarn("Failed to search for review", "query", query, "error", err.Error()) + p.client.Log.Warn("Failed to search for review", "query", query, "error", err.Error()) return false } query = getYourPrsSearchQuery(username, config.GitHubOrg) yourPrs, _, err := githubClient.Search.Issues(ctx, query, &github.SearchOptions{}) if err != nil { - p.API.LogWarn("Failed to search for PRs", "query", query, "error", "error", err.Error()) + p.client.Log.Warn("Failed to search for PRs", "query", query, "error", "error", err.Error()) return false } query = getYourAssigneeSearchQuery(username, config.GitHubOrg) yourAssignments, _, err := githubClient.Search.Issues(ctx, query, &github.SearchOptions{}) if err != nil { - p.API.LogWarn("Failed to search for assignments", "query", query, "error", "error", err.Error()) + p.client.Log.Warn("Failed to search for assignments", "query", query, "error", "error", err.Error()) return false } relevantNotifications := false notifications, _, err := githubClient.Activity.ListNotifications(ctx, &github.NotificationListOptions{}) if err != nil { - p.API.LogWarn("Failed to list notifications", "error", err.Error()) + p.client.Log.Warn("Failed to list notifications", "error", err.Error()) return false } @@ -919,7 +917,7 @@ func (p *Plugin) HasUnreads(info *GitHubUserInfo) bool { } if n.GetRepository() == nil { - p.API.LogWarn("Unable to get repository for notification in todo list. Skipping.") + p.client.Log.Warn("Unable to get repository for notification in todo list. Skipping.") continue } @@ -956,7 +954,7 @@ func (p *Plugin) isUserOrganizationMember(githubClient *github.Client, user *git isMember, _, err := githubClient.Organizations.IsMember(context.Background(), organization, *user.Login) if err != nil { - p.API.LogWarn("Failled to check if user is org member", "GitHub username", *user.Login, "error", err.Error()) + p.client.Log.Warn("Failled to check if user is org member", "GitHub username", *user.Login, "error", err.Error()) return false } @@ -971,7 +969,7 @@ func (p *Plugin) isOrganizationLocked() bool { } func (p *Plugin) sendRefreshEvent(userID string) { - p.API.PublishWebSocketEvent( + p.client.Frontend.PublishWebSocketEvent( wsEventRefresh, nil, &model.WebsocketBroadcast{UserId: userID}, @@ -988,7 +986,7 @@ func (p *Plugin) getUsername(mmUserID string) (string, error) { return "", apiEr } - user, appEr := p.API.GetUser(mmUserID) + user, appEr := p.client.User.Get(mmUserID) if appEr != nil { return "", appEr } diff --git a/server/plugin/subscriptions.go b/server/plugin/subscriptions.go index d5067fe65..fc5aef521 100644 --- a/server/plugin/subscriptions.go +++ b/server/plugin/subscriptions.go @@ -1,9 +1,7 @@ package plugin import ( - "bytes" "context" - "encoding/json" "fmt" "sort" "strconv" @@ -167,7 +165,7 @@ func (p *Plugin) Subscribe(ctx context.Context, githubClient *github.Client, use } if err != nil { - p.API.LogWarn("Failed to get repository or org for subscribe action", "error", err.Error()) + p.client.Log.Warn("Failed to get repository or org for subscribe action", "error", err.Error()) return errors.Errorf("Encountered an error subscribing to %s", fullNameFromOwnerAndRepo(owner, repo)) } @@ -257,31 +255,22 @@ func (p *Plugin) AddSubscription(repo string, sub *Subscription) error { func (p *Plugin) GetSubscriptions() (*Subscriptions, error) { var subscriptions *Subscriptions - value, appErr := p.API.KVGet(SubscriptionsKey) - if appErr != nil { - return nil, errors.Wrap(appErr, "could not get subscriptions from KVStore") + err := p.client.KV.Get(SubscriptionsKey, &subscriptions) + if err != nil { + return nil, errors.Wrap(err, "could not get subscriptions from KVStore") } - if value == nil { + // No subscriptions stored. + if subscriptions == nil { return &Subscriptions{Repositories: map[string][]*Subscription{}}, nil } - err := json.NewDecoder(bytes.NewReader(value)).Decode(&subscriptions) - if err != nil { - return nil, errors.Wrap(err, "could not properly decode subscriptions key") - } - return subscriptions, nil } func (p *Plugin) StoreSubscriptions(s *Subscriptions) error { - b, err := json.Marshal(s) - if err != nil { - return errors.Wrap(err, "error while converting subscriptions map to json") - } - - if appErr := p.API.KVSet(SubscriptionsKey, b); appErr != nil { - return errors.Wrap(appErr, "could not store subscriptions in KV store") + if _, err := p.client.KV.Set(SubscriptionsKey, s); err != nil { + return errors.Wrap(err, "could not store subscriptions in KV store") } return nil diff --git a/server/plugin/subscriptions_test.go b/server/plugin/subscriptions_test.go index a0fade47e..087261497 100644 --- a/server/plugin/subscriptions_test.go +++ b/server/plugin/subscriptions_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "testing" + pluginapi "github.com/mattermost/mattermost-plugin-api" "github.com/mattermost/mattermost-server/v6/plugin/plugintest" "github.com/stretchr/testify/assert" ) @@ -26,6 +27,7 @@ func pluginWithMockedSubs(subscriptions []*Subscription) *Plugin { jsn, _ := json.Marshal(subs) mockPluginAPI.On("KVGet", SubscriptionsKey).Return(jsn, nil) p.SetAPI(mockPluginAPI) + p.client = pluginapi.NewClient(p.API, p.Driver) return p } diff --git a/server/plugin/telemetry.go b/server/plugin/telemetry.go index a094a7c84..6216ff3fc 100644 --- a/server/plugin/telemetry.go +++ b/server/plugin/telemetry.go @@ -16,14 +16,14 @@ const ( func (p *Plugin) TrackEvent(event string, properties map[string]interface{}) { err := p.tracker.TrackEvent(event, properties) if err != nil { - p.API.LogDebug("Error sending telemetry event", "event", event, "error", err.Error()) + p.client.Log.Debug("Error sending telemetry event", "event", event, "error", err.Error()) } } func (p *Plugin) TrackUserEvent(event, userID string, properties map[string]interface{}) { err := p.tracker.TrackUserEvent(event, userID, properties) if err != nil { - p.API.LogDebug("Error sending user telemetry event", "event", event, "error", err.Error()) + p.client.Log.Debug("Error sending user telemetry event", "event", event, "error", err.Error()) } } @@ -32,7 +32,7 @@ func (p *Plugin) SendDailyTelemetry() { connectedUserCount, err := p.getConnectedUserCount() if err != nil { - p.API.LogWarn("Failed to get the number of connected users for telemetry", "error", err) + p.client.Log.Warn("Failed to get the number of connected users for telemetry", "error", err) } p.TrackEvent("stats", map[string]interface{}{ @@ -79,19 +79,19 @@ func (p *Plugin) initializeTelemetry() { // Telemetry client p.telemetryClient, err = telemetry.NewRudderClient() if err != nil { - p.API.LogWarn("Telemetry client not started", "error", err.Error()) + p.client.Log.Debug("Telemetry client not started", "error", err.Error()) return } // Get config values p.tracker = telemetry.NewTracker( p.telemetryClient, - p.API.GetDiagnosticId(), - p.API.GetServerVersion(), + p.client.System.GetDiagnosticID(), + p.client.System.GetServerVersion(), Manifest.Id, Manifest.Version, "github", - telemetry.NewTrackerConfig(p.API.GetConfig()), + telemetry.NewTrackerConfig(p.client.Configuration.GetConfig()), logger.New(p.API), ) } diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go index baab527db..1c8f117f4 100644 --- a/server/plugin/webhook.go +++ b/server/plugin/webhook.go @@ -192,7 +192,7 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { signature := r.Header.Get("X-Hub-Signature") valid, err := verifyWebhookSignature([]byte(config.WebhookSecret), signature, body) if err != nil { - p.API.LogWarn("Failed to verify webhook signature", "error", err.Error()) + p.client.Log.Warn("Failed to verify webhook signature", "error", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } @@ -204,19 +204,19 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { event, err := github.ParseWebHook(github.WebHookType(r), body) if err != nil { - p.API.LogDebug("GitHub webhook content type should be set to \"application/json\"", "error", err.Error()) + p.client.Log.Debug("GitHub webhook content type should be set to \"application/json\"", "error", err.Error()) http.Error(w, "wrong mime-type. should be \"application/json\"", http.StatusBadRequest) return } if config.EnableWebhookEventLogging { - bodyByte, appErr := json.Marshal(event) - if appErr != nil { - p.API.LogWarn("Error while Marshal Webhook Request", "error", appErr.Error()) + bodyByte, err := json.Marshal(event) + if err != nil { + p.client.Log.Warn("Error while Marshal Webhook Request", "error", err.Error()) http.Error(w, "Error while Marshal Webhook Request", http.StatusBadRequest) return } - p.API.LogDebug("Webhook Event Log", "event", string(bodyByte)) + p.client.Log.Debug("Webhook Event Log", "event", string(bodyByte)) } var repo *github.Repository @@ -317,7 +317,7 @@ func (p *Plugin) permissionToRepo(userID string, ownerAndRepo string) bool { if result, _, err := githubClient.Repositories.Get(ctx, owner, repo); result == nil || err != nil { if err != nil { - p.API.LogWarn("Failed fetch repository to check permission", "error", err.Error()) + p.client.Log.Warn("Failed fetch repository to check permission", "error", err.Error()) } return false } @@ -332,7 +332,7 @@ func (p *Plugin) excludeConfigOrgMember(user *github.User, subscription *Subscri info, err := p.getGitHubUserInfo(subscription.CreatorID) if err != nil { - p.API.LogWarn("Failed to exclude org member", "error", err.Message) + p.client.Log.Warn("Failed to exclude org member", "error", err.Message) return false } @@ -364,7 +364,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) { closedPRMessage, err := renderTemplate("closedPR", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -410,7 +410,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) { if label != "" && label == eventLabel { pullRequestLabelledMessage, err := renderTemplate("pullRequestLabelled", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -423,7 +423,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) { if action == actionOpened { newPRMessage, err := renderTemplate("newPR", GetEventWithRenderConfig(event, sub)) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -435,8 +435,8 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err := p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -459,7 +459,7 @@ func (p *Plugin) handlePRDescriptionMentionNotification(event *github.PullReques message, err := renderTemplate("pullRequestMentionNotification", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -489,15 +489,15 @@ func (p *Plugin) handlePRDescriptionMentionNotification(event *github.PullReques continue } - channel, err := p.API.GetDirectChannel(userID, p.BotUserID) + channel, err := p.client.Channel.GetDirect(userID, p.BotUserID) if err != nil { continue } post.ChannelId = channel.Id - if _, err = p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } p.sendRefreshEvent(userID) @@ -559,7 +559,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) { renderedMessage, err := renderTemplate(issueTemplate, GetEventWithRenderConfig(event, sub)) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } renderedMessage = p.sanitizeDescription(renderedMessage) @@ -597,8 +597,8 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -619,7 +619,7 @@ func (p *Plugin) postPushEvent(event *github.PushEvent) { pushedCommitsMessage, err := renderTemplate("pushedCommits", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -639,8 +639,8 @@ func (p *Plugin) postPushEvent(event *github.PushEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -660,7 +660,7 @@ func (p *Plugin) postCreateEvent(event *github.CreateEvent) { newCreateMessage, err := renderTemplate("newCreateMessage", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -680,8 +680,8 @@ func (p *Plugin) postCreateEvent(event *github.CreateEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -703,7 +703,7 @@ func (p *Plugin) postDeleteEvent(event *github.DeleteEvent) { newDeleteMessage, err := renderTemplate("newDeleteMessage", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -723,8 +723,8 @@ func (p *Plugin) postDeleteEvent(event *github.DeleteEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -744,7 +744,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) { message, err := renderTemplate("issueComment", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -793,14 +793,20 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) { post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } func (p *Plugin) senderMutedByReceiver(userID string, sender string) bool { - mutedUsernameBytes, _ := p.API.KVGet(userID + "-muted-users") + var mutedUsernameBytes []byte + err := p.client.KV.Get(userID+"-muted-users", &mutedUsernameBytes) + if err != nil { + p.client.Log.Warn("Failed to get muted users", "userID", userID) + return false + } + mutedUsernames := string(mutedUsernameBytes) return strings.Contains(mutedUsernames, sender) } @@ -823,13 +829,13 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent case "COMMENTED": case "CHANGES_REQUESTED": default: - p.API.LogDebug("Unhandled review state", "state", event.GetReview().GetState()) + p.client.Log.Debug("Unhandled review state", "state", event.GetReview().GetState()) return } newReviewMessage, err := renderTemplate("pullRequestReviewEvent", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -867,8 +873,8 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -883,7 +889,7 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi newReviewMessage, err := renderTemplate("newReviewComment", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -928,8 +934,8 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } } @@ -951,7 +957,7 @@ func (p *Plugin) handleCommentMentionNotification(event *github.IssueCommentEven message, err := renderTemplate("commentMentionNotification", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -996,14 +1002,14 @@ func (p *Plugin) handleCommentMentionNotification(event *github.IssueCommentEven continue } - channel, err := p.API.GetDirectChannel(userID, p.BotUserID) + channel, err := p.client.Channel.GetDirect(userID, p.BotUserID) if err != nil { continue } post.ChannelId = channel.Id - if _, err = p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error creating mention post", "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error creating mention post", "error", err.Error()) } p.sendRefreshEvent(userID) @@ -1042,18 +1048,18 @@ func (p *Plugin) handleCommentAuthorNotification(event *github.IssueCommentEvent case "issues": templateName = "commentAuthorIssueNotification" default: - p.API.LogDebug("Unhandled issue type", "type", splitURL[len(splitURL)-2]) + p.client.Log.Debug("Unhandled issue type", "type", splitURL[len(splitURL)-2]) return } if p.senderMutedByReceiver(authorUserID, event.GetSender().GetLogin()) { - p.API.LogDebug("Commenter is muted, skipping notification") + p.client.Log.Debug("Commenter is muted, skipping notification") return } message, err := renderTemplate(templateName, event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -1079,7 +1085,7 @@ func (p *Plugin) handleCommentAssigneeNotification(event *github.IssueCommentEve case "issues": templateName = "commentAssigneeIssueNotification" default: - p.API.LogDebug("Unhandled issue type", "Type", eventType) + p.client.Log.Debug("Unhandled issue type", "Type", eventType) return } @@ -1126,13 +1132,13 @@ func (p *Plugin) handleCommentAssigneeNotification(event *github.IssueCommentEve } if p.senderMutedByReceiver(assigneeID, event.GetSender().GetLogin()) { - p.API.LogDebug("Commenter is muted, skipping notification") + p.client.Log.Debug("Commenter is muted, skipping notification") continue } message, err := renderTemplate(template, event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) continue } p.CreateBotDMPost(assigneeID, message, "custom_git_assignee") @@ -1187,13 +1193,13 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) { assigneeUserID = "" } default: - p.API.LogDebug("Unhandled event action", "action", event.GetAction()) + p.client.Log.Debug("Unhandled event action", "action", event.GetAction()) return } message, err := renderTemplate("pullRequestNotification", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -1239,13 +1245,13 @@ func (p *Plugin) handleIssueNotification(event *github.IssuesEvent) { assigneeUserID = "" } default: - p.API.LogDebug("Unhandled event action", "action", event.GetAction()) + p.client.Log.Debug("Unhandled event action", "action", event.GetAction()) return } message, err := renderTemplate("issueNotification", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -1285,7 +1291,7 @@ func (p *Plugin) handlePullRequestReviewNotification(event *github.PullRequestRe message, err := renderTemplate("pullRequestReviewNotification", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -1304,7 +1310,7 @@ func (p *Plugin) postStarEvent(event *github.StarEvent) { newStarMessage, err := renderTemplate("newRepoStar", event) if err != nil { - p.API.LogWarn("Failed to render template", "error", err.Error()) + p.client.Log.Warn("Failed to render template", "error", err.Error()) return } @@ -1324,8 +1330,8 @@ func (p *Plugin) postStarEvent(event *github.StarEvent) { } post.ChannelId = sub.ChannelID - if _, err := p.API.CreatePost(post); err != nil { - p.API.LogWarn("Error webhook post", "post", post, "error", err.Error()) + if err = p.client.Post.CreatePost(post); err != nil { + p.client.Log.Warn("Error webhook post", "post", post, "error", err.Error()) } } }