From e184a2a7c0b123c4ee2c02bf091e41007d45182a Mon Sep 17 00:00:00 2001 From: Nicolas Bock Date: Tue, 7 May 2024 09:00:38 -0600 Subject: [PATCH] [SET-627] Enable chatter This change adds a configuration option to post comments to a chatter object instead of a casecomment object. The feature is disabled by default and has to be explicitly enabled via the configuration file: ```yaml salesforce: enable-chatter: true ``` Closes: SET-627 Signed-off-by: Nicolas Bock --- cmd/monitor/main.go | 1 - pkg/common/salesforce.go | 29 +++++++++++++++++++++-------- pkg/config/config.go | 4 +++- pkg/config/config_test.go | 4 ++++ pkg/processor/processor.go | 13 ++++++++++--- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/cmd/monitor/main.go b/cmd/monitor/main.go index 79cb672..2e75b24 100644 --- a/cmd/monitor/main.go +++ b/cmd/monitor/main.go @@ -29,7 +29,6 @@ func init() { } func main() { - cfg, err := config.NewConfigFromFile(*configs) if err != nil { panic(err) diff --git a/pkg/common/salesforce.go b/pkg/common/salesforce.go index c0392ca..ceb594c 100644 --- a/pkg/common/salesforce.go +++ b/pkg/common/salesforce.go @@ -22,6 +22,7 @@ var ErrAuthentication = simpleforce.ErrAuthentication type SalesforceClient interface { GetCaseByNumber(number string) (*Case, error) PostComment(caseId, body string, isPublic bool) *simpleforce.SObject + PostChatter(caseId, body string, isPublic bool) *simpleforce.SObject Query(query string) (*simpleforce.QueryResult, error) SObject(objectName ...string) *simpleforce.SObject } @@ -42,14 +43,6 @@ type Case struct { Id, CaseNumber, AccountId, Customer string } -func (sf *BaseSalesforceClient) PostComment(caseId, body string, isPublic bool) *simpleforce.SObject { - return sf.SObject("CaseComment"). - Set("ParentId", caseId). - Set("CommentBody", html.UnescapeString(body)). - Set("IsPublished", isPublic). - Create() -} - func (sf *BaseSalesforceClient) GetCaseByNumber(number string) (*Case, error) { q := "SELECT Id,CaseNumber,AccountId FROM Case WHERE CaseNumber LIKE '%" + number + "%'" result, err := sf.Query(q) @@ -74,6 +67,26 @@ func (sf *BaseSalesforceClient) GetCaseByNumber(number string) (*Case, error) { return nil, ErrNoCaseFound{number} } +func (sf *BaseSalesforceClient) PostComment(caseId, body string, isPublic bool) *simpleforce.SObject { + return sf.SObject("CaseComment"). + Set("ParentId", caseId). + Set("CommentBody", html.UnescapeString(body)). + Set("IsPublished", isPublic). + Create() +} + +func (sf *BaseSalesforceClient) PostChatter(caseId, body string, isPublic bool) *simpleforce.SObject { + visibility := "InternalUsers" + if isPublic { + visibility = "AllUsers" + } + return sf.SObject("FeedItem"). + Set("ParentId", caseId). + Set("Body", body). + Set("Visibility", visibility). + Create() +} + func GetCaseNumberFromFilename(filename string) (string, error) { regex, err := regexp.Compile(`(\d{6,})`) if err != nil { diff --git a/pkg/config/config.go b/pkg/config/config.go index 5a1e889..c072d52 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -76,11 +76,13 @@ type SalesForce struct { Password string `yaml:"password"` SecurityToken string `yaml:"security-token"` MaxCommentLength int `yaml:"max-comment-length"` + EnableChatter bool `yaml:"enable-chatter"` } func NewSalesForce() SalesForce { return SalesForce{ MaxCommentLength: 4000 - 1000, // A very conservative buffer of max length per Salesforce comment (4000) without header text for comments + EnableChatter: false, } } @@ -129,8 +131,8 @@ func NewConfigFromFile(filePaths []string) (*Config, error) { if err := s.Snuffle(); err != nil { return nil, err - } + return &config, nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 19154cb..f50b4d1 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -88,6 +88,10 @@ func TestNewSalesforce(t *testing.T) { if salesforce.MaxCommentLength != 3000 { t.Errorf("Expected MaxCommentLength to be 3000, got '%d'", salesforce.MaxCommentLength) } + + if salesforce.EnableChatter { + t.Errorf("Expected EnableChatter to be false, got true") + } } func TestNewConfigFromFile(t *testing.T) { diff --git a/pkg/processor/processor.go b/pkg/processor/processor.go index 80ba643..9f5d642 100644 --- a/pkg/processor/processor.go +++ b/pkg/processor/processor.go @@ -17,6 +17,7 @@ import ( "github.com/flosch/pongo2/v4" "github.com/lileio/pubsub/v2" "github.com/lileio/pubsub/v2/middleware/defaults" + "github.com/simpleforce/simpleforce" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -455,7 +456,7 @@ func (p *Processor) BatchSalesforceComments(ctx *context.Context, interval time. return } - log.Infof("Found %d reports to be sent to salesforce", len(reports)) + log.Infof("Found %d reports to be sent to Salesforce", len(reports)) for _, report := range reports { if reportMap[report.Subscriber] == nil { reportMap[report.Subscriber] = make(map[string]map[string][]db.Report) @@ -507,8 +508,14 @@ func (p *Processor) BatchSalesforceComments(ctx *context.Context, interval time. if len(commentChunks) > 1 { chunkHeader = fmt.Sprintf("Split comment %d of %d\n\n", i+1, len(commentChunks)) } - comment := p.SalesforceClient.PostComment(caseId, - chunkHeader+chunk, subscriber.SFCommentIsPublic) + var comment *simpleforce.SObject + if p.Config.Salesforce.EnableChatter { + comment = p.SalesforceClient.PostChatter(caseId, + chunkHeader+chunk, subscriber.SFCommentIsPublic) + } else { + comment = p.SalesforceClient.PostComment(caseId, + chunkHeader+chunk, subscriber.SFCommentIsPublic) + } if comment == nil { log.Errorf("Failed to post comment to case id: %s", caseId) continue