Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions server/plugin/graphql/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,52 @@

return nil
}

type changeUserStatusMutation struct {
ChangeUserStatus struct {
Status struct {
Message githubv4.String
Emoji githubv4.String
}
} `graphql:"changeUserStatus(input: $input)"`
}

func (c *Client) UpdateUserStatus(ctx context.Context, emoji, message string, busy bool) (string, error) {
var mutation changeUserStatusMutation
input := githubv4.ChangeUserStatusInput{
Emoji: githubv4.NewString(githubv4.String(emoji)),

Check failure on line 80 in server/plugin/graphql/client.go

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

File is not properly formatted (gofmt)

Choose a reason for hiding this comment

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

The CI failure happened here earlier because the file wasn’t gofmt formatted. Please make sure this whole struct literal is formatted (run gofmt -w).

Message: githubv4.NewString(githubv4.String(message)),
LimitedAvailability: githubv4.NewBoolean(githubv4.Boolean(busy)),
}

err := c.client.Mutate(ctx, &mutation, input, nil)
if err != nil {
return "", err

Choose a reason for hiding this comment

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

Consider wrapping for more traceability:
// return "", fmt.Errorf("UpdateUserStatus mutate failed: %w", err)

}

return string(mutation.ChangeUserStatus.Status.Message), nil
}

type getUserStatusQuery struct {
User struct {
Status struct {
Message githubv4.String
Emoji githubv4.String
LimitedAvailability githubv4.Boolean
}
} `graphql:"user(login: $login)"`
}

func (c *Client) GetUserStatus(ctx context.Context, login string) (string, string, bool, error) {
var query getUserStatusQuery
variables := map[string]interface{}{
"login": githubv4.String(login),
}

err := c.client.Query(ctx, &query, variables)
if err != nil {
return "", "", false, err
}

return string(query.User.Status.Message), string(query.User.Status.Emoji), bool(query.User.Status.LimitedAvailability), nil
}
62 changes: 62 additions & 0 deletions server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,12 @@ type UserSettings struct {
Notifications bool `json:"notifications"`
}

type GithubStatus struct {
Message string `json:"message"`
Emoji string `json:"emoji"`
Busy bool `json:"busy"`
}

func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error {
config := p.getConfiguration()

Expand Down Expand Up @@ -1192,3 +1198,59 @@ func (p *Plugin) handleRevokedToken(info *GitHubUserInfo) {
p.disconnectGitHubAccount(info.UserID)
p.CreateBotDMPost(info.UserID, "Your Github account was disconnected due to an invalid or revoked authorization token. Reconnect your account using the `/github connect` command.", "custom_git_revoked_token")
}

func (p *Plugin) UserStatusHasChanged(c *plugin.Context, userStatus *model.Status) {
userInfo, apiErr := p.getGitHubUserInfo(userStatus.UserId)
if apiErr != nil {
return
}

if userStatus.Status == "ooo" {
graphQLClient := p.graphQLConnect(userInfo)
message, emoji, busy, err := graphQLClient.GetUserStatus(context.Background(), userInfo.GitHubUsername)
Copy link
Member

Choose a reason for hiding this comment

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

Can you check here if the Github status is already "out of office" and not overwrite it if true. I don't think we want to clobber a manually set OoO on the Github side.

if err != nil {
p.client.Log.Error("failed to get user status", "error", err)
return
}

githubStatus := &GithubStatus{
Message: message,
Emoji: emoji,
Busy: busy,
}

githubStatusJSON, err := json.Marshal(githubStatus)
if err != nil {
p.client.Log.Error("failed to marshal github status", "error", err)
return
}

p.store.Set(userInfo.UserID+"_github_status", githubStatusJSON)

_, err = graphQLClient.UpdateUserStatus(context.Background(), ":house_with_garden:", "Out of office", true)
if err != nil {
p.client.Log.Error("failed to update user status", "error", err)
return
}

p.CreateBotDMPost(userInfo.UserID, "Your GitHub status has been updated to Out of office.", "custom_git_ooo_ephemeral")
Copy link
Member

Choose a reason for hiding this comment

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

This post type is not actually ephemeral.

} else {
var oldStatus []byte
if err := p.store.Get(userInfo.UserID+"_github_status", &oldStatus); err == nil && len(oldStatus) > 0 {
var githubStatus GithubStatus
if err := json.Unmarshal(oldStatus, &githubStatus); err != nil {
p.client.Log.Error("failed to unmarshal github status", "error", err)
return
}

graphQLClient := p.graphQLConnect(userInfo)
_, err := graphQLClient.UpdateUserStatus(context.Background(), githubStatus.Emoji, githubStatus.Message, githubStatus.Busy)
if err != nil {
p.client.Log.Error("failed to update user status", "error", err)
return
}
p.store.Delete(userInfo.UserID + "_github_status")
Copy link
Member

Choose a reason for hiding this comment

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

@akshat-khosya this is cool feature. One minor issue I see is that a user's status will be left in the KV store if they disconnect their account while in "ooo" status. Can you add something to clear a user's status in the KV store when their account is disconnected?

p.CreateBotDMPost(userInfo.UserID, "Your GitHub status has been restored.", "custom_git_ooo_ephemeral")
}
}
}
Loading