mirror of
https://github.com/mattermost/focalboard.git
synced 2025-02-01 19:14:35 +02:00
Post message channel change (#3717)
* initial implementation * checking changes * use boards bot * update mocks * linter fixes * linter fixes * clean up * revert manifest change * another lint fix * use common error Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
parent
27a4da126d
commit
0403c22f3c
@ -12,17 +12,9 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/permissions"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
|
||||
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
botUsername = "boards"
|
||||
botDisplayname = "Boards"
|
||||
botDescription = "Created by Boards plugin."
|
||||
)
|
||||
|
||||
type notifyBackendParams struct {
|
||||
cfg *config.Configuration
|
||||
servicesAPI model.ServicesAPI
|
||||
@ -71,15 +63,11 @@ func createSubscriptionsNotifyBackend(params notifyBackendParams) (*notifysubscr
|
||||
}
|
||||
|
||||
func createDelivery(servicesAPI model.ServicesAPI, serverRoot string) (*plugindelivery.PluginDelivery, error) {
|
||||
bot := &mm_model.Bot{
|
||||
Username: botUsername,
|
||||
DisplayName: botDisplayname,
|
||||
Description: botDescription,
|
||||
OwnerId: model.SystemUserID,
|
||||
}
|
||||
bot := model.FocalboardBot
|
||||
|
||||
botID, err := servicesAPI.EnsureBot(bot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure %s bot: %w", botDisplayname, err)
|
||||
return nil, fmt.Errorf("failed to ensure %s bot: %w", bot.DisplayName, err)
|
||||
}
|
||||
|
||||
return plugindelivery.New(botID, serverRoot, servicesAPI), nil
|
||||
|
@ -20,6 +20,9 @@ var (
|
||||
ErrInsufficientLicense = errors.New("appropriate license required")
|
||||
)
|
||||
|
||||
const linkBoardMessage = "@%s linked Board [%s](%s) with this channel"
|
||||
const unlinkBoardMessage = "@%s unlinked Board [%s](%s) with this channel"
|
||||
|
||||
func (a *App) GetBoard(boardID string) (*model.Board, error) {
|
||||
board, err := a.store.GetBoard(boardID)
|
||||
if model.IsErrNotFound(err) {
|
||||
@ -302,18 +305,54 @@ func (a *App) CreateBoard(board *model.Board, userID string, addMember bool) (*m
|
||||
|
||||
func (a *App) PatchBoard(patch *model.BoardPatch, boardID, userID string) (*model.Board, error) {
|
||||
var oldMembers []*model.BoardMember
|
||||
var oldChannelID string
|
||||
if patch.ChannelID != nil && *patch.ChannelID == "" {
|
||||
var err error
|
||||
oldMembers, err = a.GetMembersForBoard(boardID)
|
||||
if err != nil {
|
||||
a.logger.Error("Unable to get the board members", mlog.Err(err))
|
||||
}
|
||||
board, err := a.store.GetBoard(boardID)
|
||||
if model.IsErrNotFound(err) {
|
||||
return nil, model.NewErrNotFound(boardID)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldChannelID = board.ChannelID
|
||||
}
|
||||
updatedBoard, err := a.store.PatchBoard(boardID, patch, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if patch.ChannelID != nil {
|
||||
var username string
|
||||
user, err := a.store.GetUserByID(userID)
|
||||
if err != nil {
|
||||
a.logger.Error("Unable to get the board updater", mlog.Err(err))
|
||||
username = "unknown"
|
||||
} else {
|
||||
username = user.Username
|
||||
}
|
||||
|
||||
boardLink := utils.MakeBoardLink(a.config.ServerRoot, updatedBoard.TeamID, updatedBoard.ID)
|
||||
if *patch.ChannelID != "" {
|
||||
// TODO: this needs translated when available on the server
|
||||
message := fmt.Sprintf(linkBoardMessage, username, updatedBoard.Title, boardLink)
|
||||
err := a.store.PostMessage(message, "", *patch.ChannelID)
|
||||
if err != nil {
|
||||
a.logger.Error("Unable to post the link message to channel", mlog.Err(err))
|
||||
}
|
||||
} else if *patch.ChannelID == "" {
|
||||
message := fmt.Sprintf(unlinkBoardMessage, username, updatedBoard.Title, boardLink)
|
||||
err := a.store.PostMessage(message, "", oldChannelID)
|
||||
if err != nil {
|
||||
a.logger.Error("Unable to post the link message to channel", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.blockChangeNotifier.Enqueue(func() error {
|
||||
a.wsAdapter.BroadcastBoardChange(updatedBoard.TeamID, updatedBoard)
|
||||
if patch.ChannelID != nil && *patch.ChannelID != "" {
|
||||
|
@ -14,6 +14,19 @@ import (
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
botUsername = "boards"
|
||||
botDisplayname = "Boards"
|
||||
botDescription = "Created by Boards plugin."
|
||||
)
|
||||
|
||||
var FocalboardBot = &mm_model.Bot{
|
||||
Username: botUsername,
|
||||
DisplayName: botDisplayname,
|
||||
Description: botDescription,
|
||||
OwnerId: SystemUserID,
|
||||
}
|
||||
|
||||
type ServicesAPI interface {
|
||||
// Channels service
|
||||
GetDirectChannel(userID1, userID2 string) (*mm_model.Channel, error)
|
||||
|
@ -18,10 +18,7 @@ import (
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
)
|
||||
|
||||
var systemsBot = &mmModel.Bot{
|
||||
Username: mmModel.BotSystemBotUsername,
|
||||
DisplayName: "System",
|
||||
}
|
||||
var boardsBotID string
|
||||
|
||||
// servicesAPI is the interface required my the MattermostAuthLayer to interact with
|
||||
// the mattermost-server. You can use plugin-api or product-api adapter implementations.
|
||||
@ -852,18 +849,18 @@ func (s *MattermostAuthLayer) GetChannel(teamID, channelID string) (*mmModel.Cha
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) getSystemBotID() (string, error) {
|
||||
botID, err := s.servicesAPI.EnsureBot(systemsBot)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to ensure system bot", mlog.String("username", systemsBot.Username), mlog.Err(err))
|
||||
func (s *MattermostAuthLayer) getBoardsBotID() (string, error) {
|
||||
if boardsBotID == "" {
|
||||
var err error
|
||||
boardsBotID, err = s.servicesAPI.EnsureBot(model.FocalboardBot)
|
||||
s.logger.Error("failed to ensure boards bot", mlog.Err(err))
|
||||
return "", err
|
||||
}
|
||||
|
||||
return botID, nil
|
||||
return boardsBotID, nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) SendMessage(message, postType string, receipts []string) error {
|
||||
botID, err := s.getSystemBotID()
|
||||
botID, err := s.getBoardsBotID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -880,14 +877,7 @@ func (s *MattermostAuthLayer) SendMessage(message, postType string, receipts []s
|
||||
continue
|
||||
}
|
||||
|
||||
post := &mmModel.Post{
|
||||
Message: message,
|
||||
UserId: botID,
|
||||
ChannelId: channel.Id,
|
||||
Type: postType,
|
||||
}
|
||||
|
||||
if _, err := s.servicesAPI.CreatePost(post); err != nil {
|
||||
if err := s.PostMessage(message, postType, channel.Id); err != nil {
|
||||
s.logger.Error(
|
||||
"failed to send message to receipt from SendMessage",
|
||||
mlog.String("receipt", receipt),
|
||||
@ -896,7 +886,28 @@ func (s *MattermostAuthLayer) SendMessage(message, postType string, receipts []s
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) PostMessage(message, postType, channelID string) error {
|
||||
botID, err := s.getBoardsBotID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
post := &mmModel.Post{
|
||||
Message: message,
|
||||
UserId: botID,
|
||||
ChannelId: channelID,
|
||||
Type: postType,
|
||||
}
|
||||
|
||||
if _, err := s.servicesAPI.CreatePost(post); err != nil {
|
||||
s.logger.Error(
|
||||
"failed to send message to receipt from PostMessage",
|
||||
mlog.Err(err),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1251,6 +1251,20 @@ func (mr *MockStoreMockRecorder) PatchUserProps(arg0, arg1 interface{}) *gomock.
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchUserProps", reflect.TypeOf((*MockStore)(nil).PatchUserProps), arg0, arg1)
|
||||
}
|
||||
|
||||
// PostMessage mocks base method.
|
||||
func (m *MockStore) PostMessage(arg0, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostMessage", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PostMessage indicates an expected call of PostMessage.
|
||||
func (mr *MockStoreMockRecorder) PostMessage(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostMessage", reflect.TypeOf((*MockStore)(nil).PostMessage), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// RefreshSession mocks base method.
|
||||
func (m *MockStore) RefreshSession(arg0 *model.Session) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -707,6 +707,11 @@ func (s *SQLStore) PatchUserProps(userID string, patch model.UserPropPatch) erro
|
||||
|
||||
}
|
||||
|
||||
func (s *SQLStore) PostMessage(message string, postType string, channelID string) error {
|
||||
return s.postMessage(s.db, message, postType, channelID)
|
||||
|
||||
}
|
||||
|
||||
func (s *SQLStore) RefreshSession(session *model.Session) error {
|
||||
return s.refreshSession(s.db, session)
|
||||
|
||||
|
@ -279,6 +279,10 @@ func (s *SQLStore) sendMessage(db sq.BaseRunner, message, postType string, recei
|
||||
return errUnsupportedOperation
|
||||
}
|
||||
|
||||
func (s *SQLStore) postMessage(db sq.BaseRunner, message, postType string, channel string) error {
|
||||
return errUnsupportedOperation
|
||||
}
|
||||
|
||||
func (s *SQLStore) getUserTimezone(_ sq.BaseRunner, _ string) (string, error) {
|
||||
return "", errUnsupportedOperation
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ type Store interface {
|
||||
GetCloudLimits() (*mmModel.ProductLimits, error)
|
||||
SearchUserChannels(teamID, userID, query string) ([]*mmModel.Channel, error)
|
||||
GetChannel(teamID, channelID string) (*mmModel.Channel, error)
|
||||
PostMessage(message, postType, channelID string) error
|
||||
SendMessage(message, postType string, receipts []string) error
|
||||
|
||||
// Insights
|
||||
|
Loading…
x
Reference in New Issue
Block a user