generated from mattermost/mattermost-plugin-starter-template
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Lev <[email protected]>
- Loading branch information
Showing
18 changed files
with
413 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. | ||
// See License for license information. | ||
|
||
package apps | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/hashicorp/go-multierror" | ||
|
||
"github.com/mattermost/mattermost-plugin-apps/utils" | ||
) | ||
|
||
// Timer s submitted by an app to the Timer API. It determines when | ||
// the app would like to be notified, and how these notifications | ||
// should be invoked. | ||
type Timer struct { | ||
// At is the unix time in milliseconds when the timer should be executed. | ||
At int64 `json:"at"` | ||
|
||
// Call is the (one-way) call to make upon the timers execution. | ||
Call Call `json:"call"` | ||
|
||
// ChannelID is a channel ID that is used for expansion of the Call (optional). | ||
ChannelID string `json:"channel_id,omitempty"` | ||
// TeamID is a team ID that is used for expansion of the Call (optional). | ||
TeamID string `json:"team_id,omitempty"` | ||
} | ||
|
||
func (t Timer) Validate() error { | ||
var result error | ||
emptyCall := Call{} | ||
if t.Call == emptyCall { | ||
result = multierror.Append(result, utils.NewInvalidError("call must not be empty")) | ||
} | ||
|
||
if t.At <= 0 { | ||
result = multierror.Append(result, utils.NewInvalidError("at must be positive")) | ||
} | ||
|
||
if time.Until(time.UnixMilli(t.At)) < 1*time.Second { | ||
result = multierror.Append(result, utils.NewInvalidError("at most be at least 1 second in the future")) | ||
} | ||
|
||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ require ( | |
github.com/gorilla/mux v1.8.0 | ||
github.com/hashicorp/go-getter v1.6.2 | ||
github.com/hashicorp/go-multierror v1.1.1 | ||
github.com/mattermost/mattermost-plugin-api v0.1.1 | ||
github.com/mattermost/mattermost-plugin-api v0.1.2-0.20221110071900-f8b73bc6795e | ||
// mmgoget: github.com/mattermost/mattermost-server/[email protected] is replaced by -> github.com/mattermost/mattermost-server/v6@ea08d47f60 | ||
github.com/mattermost/mattermost-server/v6 v6.0.0-20230113170349-ea08d47f6051 | ||
github.com/nicksnyder/go-i18n/v2 v2.2.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. | ||
// See License for license information. | ||
|
||
package appservices | ||
|
||
import ( | ||
"context" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/mattermost/mattermost-plugin-apps/apps" | ||
"github.com/mattermost/mattermost-plugin-apps/server/config" | ||
"github.com/mattermost/mattermost-plugin-apps/server/incoming" | ||
) | ||
|
||
type storedTimer struct { | ||
Call apps.Call `json:"call"` | ||
AppID apps.AppID `json:"app_id"` | ||
UserID string `json:"user_id"` | ||
ChannelID string `json:"channel_id,omitempty"` | ||
TeamID string `json:"team_id,omitempty"` | ||
} | ||
|
||
func (t storedTimer) Key(appID apps.AppID, at int64) string { | ||
return string(appID) + t.UserID + strconv.FormatInt(at, 10) | ||
} | ||
|
||
func (t storedTimer) Loggable() []interface{} { | ||
props := []interface{}{"user_id", t.UserID} | ||
props = append(props, "app_id", t.AppID) | ||
if t.ChannelID != "" { | ||
props = append(props, "call_team_id", t.TeamID) | ||
} | ||
if t.TeamID != "" { | ||
props = append(props, "call_channel_id", t.ChannelID) | ||
} | ||
return props | ||
} | ||
|
||
func (a *AppServices) CreateTimer(r *incoming.Request, t apps.Timer) error { | ||
err := r.Check( | ||
r.RequireActingUser, | ||
r.RequireSourceApp, | ||
t.Validate, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
st := storedTimer{ | ||
Call: t.Call, | ||
AppID: r.SourceAppID(), | ||
UserID: r.ActingUserID(), | ||
ChannelID: t.ChannelID, | ||
TeamID: t.TeamID, | ||
} | ||
|
||
_, err = a.scheduler.ScheduleOnce(st.Key(r.SourceAppID(), t.At), time.UnixMilli(t.At), st) | ||
if err != nil { | ||
return errors.Wrap(err, "faild to schedule timer job") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a *AppServices) ExecuteTimer(key string, props interface{}) { | ||
t, ok := props.(storedTimer) | ||
if !ok { | ||
a.log.Debugw("Timer contained unknown props. Inoring the timer.", "key", key, "props", props) | ||
return | ||
} | ||
|
||
r := a.caller.NewIncomingRequest() | ||
|
||
r.Log = r.Log.With(t) | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), config.RequestTimeout) | ||
defer cancel() | ||
r = r.WithCtx(ctx) | ||
|
||
r = r.WithDestination(t.AppID) | ||
r = r.WithActingUserID(t.UserID) | ||
|
||
context := &apps.Context{ | ||
UserAgentContext: apps.UserAgentContext{ | ||
AppID: t.AppID, | ||
TeamID: t.TeamID, | ||
ChannelID: t.ChannelID, | ||
}, | ||
} | ||
|
||
creq := apps.CallRequest{ | ||
Call: t.Call, | ||
Context: *context, | ||
} | ||
r.Log = r.Log.With(creq) | ||
_, cresp := a.caller.InvokeCall(r, creq) | ||
if cresp.Type == apps.CallResponseTypeError { | ||
if a.conf.Get().DeveloperMode { | ||
r.Log.WithError(cresp).Errorf("Timer execute failed") | ||
} | ||
return | ||
} | ||
r.Log = r.Log.With(cresp) | ||
|
||
r.Log.Debugf("Timer executed") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. | ||
// See License for license information. | ||
|
||
package httpin | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
|
||
"github.com/mattermost/mattermost-plugin-apps/apps" | ||
"github.com/mattermost/mattermost-plugin-apps/server/incoming" | ||
"github.com/mattermost/mattermost-plugin-apps/utils/httputils" | ||
) | ||
|
||
// CreateTimer create or updates a new statefull timer. | ||
// | ||
// Path: /api/v1/timer | ||
// Method: POST | ||
// Input: JSON {at, call, state} | ||
// Output: None | ||
func (s *Service) CreateTimer(r *incoming.Request, w http.ResponseWriter, req *http.Request) { | ||
var t apps.Timer | ||
|
||
err := json.NewDecoder(req.Body).Decode(&t) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
|
||
err = s.AppServices.CreateTimer(r, t) | ||
if err != nil { | ||
http.Error(w, err.Error(), httputils.ErrorToStatus(err)) | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.