Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(service): Add Meta Workplace #413

Closed
wants to merge 3 commits into from
Closed

feat(service): Add Meta Workplace #413

wants to merge 3 commits into from

Conversation

mrhillsman
Copy link

Signed-off-by: Melvin Hillsman mhillsma@redhat.com

Description

Add service for Meta Workplace

Motivation and Context

Hacktoberfest
Resolves #278

How Has This Been Tested?

A sample project was created locally for testing and a README.md file was added showing that code.

Screenshots / Output (if appropriate):

Types of changes

  • New feature (non-breaking change which adds functionality)
  • Documentation (no code change)

Checklist:

  • My code follows the code style of this project.
  • I have updated the documentation accordingly.
  • All new and existing tests passed.

Signed-off-by: Melvin Hillsman <mhillsma@redhat.com>
@codecov-commenter
Copy link

codecov-commenter commented Oct 10, 2022

Codecov Report

Base: 64.34% // Head: 58.69% // Decreases project coverage by -5.64% ⚠️

Coverage data is based on head (7653745) compared to base (ce792a2).
Patch coverage: 0.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #413      +/-   ##
==========================================
- Coverage   64.34%   58.69%   -5.65%     
==========================================
  Files          32       33       +1     
  Lines        1091     1196     +105     
==========================================
  Hits          702      702              
- Misses        324      429     +105     
  Partials       65       65              
Impacted Files Coverage Δ
service/metaworkplace/metaworkplace.go 0.00% <0.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

Comment on lines +53 to +57
#### Please consider the following:
* Meta Workplace service does not allow sending messages to group chats
* Meta Workplace service does not allow sending messages to group posts
* Meta Workplace service does not allow sending messages to users that are not already in a thread/chat with you
* Testing still needs to be added; the scenarios below will all fail. Those without a user/thread id should fail. Those
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mrhillsman,

first of all thank you for your efforts and the contribution. Really stoked to get this service in.

On first glance everything seems very well made and basically ready to merge. However, on second check I do have some smaller things and questions.

  1. Could you clarify why the service does not support the things you've listed here? This would help with setting future goals and todos for this service.

  2. Are you planning to implement the missing tests? As you've probably noticed (since you've added the go:generate directive) you can use make mock to generate a mock of this service that should help with testing. We're trying to achieve a high standard in quality with Notify and tests are defenitely a foundation for that. It would be very much appreciated!

Also, please check the linter errors and warnings. I'd ask you to fix those too. You can use make lint and make fmt to get them out of the way.

Thanks again for your efforts! Please let me know if anything needs clarification.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @nikoksr,

The items listed as not being supported are limitations on the Meta Workplace API not that they couldn't be implemented. Unfortunately I was not able to find a way to get group chat/posts and you can send a message to a user that is not already in a chat/thread; I probably just typed that in error.

I hope I can get time to work on the tests. Work got a bit busy right after I committed to at least getting the service implementation done but I hope to write the tests as well.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mrhillsman,

I'm so sorry for coming back this late to you. I did not get notified about your reply and just saw it now by accident!

Thank you for clarifying that. That sounds acceptable to me then. The package design you came up with seems to allow for future expansion and addition of the currently missing features, so I'm okay with leaving them out for now.

Let me know if there's anything I can do to help you out with! Appreciate your efforts a lot.


const (
// ENDPOINT is the base URL of the Workplace API to send messages.
ENDPOINT = "https://graph.facebook.com/me/messages"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ENDPOINT = "https://graph.facebook.com/me/messages"
endpoint = "https://graph.facebook.com/me/messages"

Let's follow the common naming conventions for constants in Go here.


err := serviceConfig.ValidateConfig()
if err != nil {
log.Fatalf("failed to validate Meta Workplace service configuration: %v", err)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.Fatalf("failed to validate Meta Workplace service configuration: %v", err)
return nil, errors.Wrap(err, "validate config")

Following common practice of the Notify codebase here.

Comment on lines +50 to +52
client: &http.Client{
Timeout: 10 * time.Second,
},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a requirement but it would be nice tfor the HTTP client to be configurable by the user. A sane default like you chose plus a MetaWorkplaceService.WithHTTPClient(client *http.Client) method would be preferable. I do understand however, that your time is limited, so I don't see this as a hard requirement.

//
//go:generate mockery --name=metaWorkplaceService --output=. --case=underscore --inpackage
type metaWorkplaceService interface {
send(payload interface{}) *MetaWorkplaceResponse
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
send(payload interface{}) *MetaWorkplaceResponse
send(payload any) *MetaWorkplaceResponse


data, err = io.ReadAll(res.Body)
if err != nil {
log.Printf("failed to read response body: %v", err)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.Printf("failed to read response body: %v", err)
return nil, errors.Wrap(err, "read response body")


err = json.Unmarshal(data, &response)
if err != nil {
log.Printf("failed to unmarshal response body: %v", err)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.Printf("failed to unmarshal response body: %v", err)
return nil, errors.Wrap(err, "unmarshal response body")

Comment on lines +125 to +142
if len(mw.threadIDs) != 0 {
for _, threadID := range mw.threadIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceThreadPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceThread{ThreadID: threadID},
}
err := mw.send(payload)
if err.Error != nil {
log.Printf("%+v\n", err.Error)
return errors.New("failed to send message to Workplace thread: " + threadID)
}
}
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(mw.threadIDs) != 0 {
for _, threadID := range mw.threadIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceThreadPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceThread{ThreadID: threadID},
}
err := mw.send(payload)
if err.Error != nil {
log.Printf("%+v\n", err.Error)
return errors.New("failed to send message to Workplace thread: " + threadID)
}
}
}
}
for _, threadID := range mw.threadIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceThreadPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceThread{ThreadID: threadID},
}
resp, err := mw.send(payload)
if err != nil {
return nil, errors.Wrapf(err, "send message to thread %q: %+v", threadID, resp)
}
if resp.Error != nil {
return nil, errors.Errorf("send message to thread %q: %+v", threadID, resp)
}
}
}

The length check here is obsolete here since an empty slice would result in a skipped loop execution body. Also, applying the error handling changes that would come implicitly with the expanded send method.

Comment on lines +144 to +164
if len(mw.userIDs) != 0 {
for _, userID := range mw.userIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceUserPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceUsers{UserIDs: []string{userID}},
}
err := mw.send(payload)
if err.Error != nil {
log.Printf("%+v\n", err.Error)
return errors.New("failed to send message to Workplace user: " + userID)
}

// Capture the thread ID for the user and add it to the thread ID list. Subsequent
// messages will be sent to the thread instead of creating a new thread for the user.
mw.threadIDs = append(mw.threadIDs, err.ThreadKey)
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(mw.userIDs) != 0 {
for _, userID := range mw.userIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceUserPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceUsers{UserIDs: []string{userID}},
}
err := mw.send(payload)
if err.Error != nil {
log.Printf("%+v\n", err.Error)
return errors.New("failed to send message to Workplace user: " + userID)
}
// Capture the thread ID for the user and add it to the thread ID list. Subsequent
// messages will be sent to the thread instead of creating a new thread for the user.
mw.threadIDs = append(mw.threadIDs, err.ThreadKey)
}
}
for _, userID := range mw.userIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
payload := metaWorkplaceUserPayload{
Message: metaWorkplaceMessage{Text: message},
Recipient: metaWorkplaceUsers{UserIDs: []string{userID}},
}
resp, err := mw.send(payload)
if err != nil {
return nil, errors.Wrapf(err, "send message to user %q: %+v", userID, resp)
}
if resp == nil {
continue // All following actions require a non-nil response
}
if resp.Error != nil {
return nil, errors.Errorf("send message to user %q: %+v", userID, resp)
}
// Capture the thread ID for the user and add it to the thread ID list. Subsequent
// messages will be sent to the thread instead of creating a new thread for the user.
mw.threadIDs = append(mw.threadIDs, resp.ThreadKey)
}
}

}

// Clear the user ID list. Subsequent messages will be sent to the thread instead of creating a new thread for the user.
mw.userIDs = []string{}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
mw.userIDs = []string{}
mw.userIDs = make([]string, 0)

Let's also free up the allocated memory here.

@nikoksr nikoksr changed the title Add Meta Workplace service feat(service): Add Meta Workplace Oct 20, 2022
@mrhillsman mrhillsman closed this by deleting the head repository May 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(service): Add workplace chat
3 participants