Skip to content

Commit

Permalink
Rename messages to notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
MDrakos committed Nov 21, 2024
1 parent fac37eb commit fbec1ec
Show file tree
Hide file tree
Showing 15 changed files with 687 additions and 1,107 deletions.
4 changes: 2 additions & 2 deletions cmd/state-svc/gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ model:

# gqlgen will search for any type names in the schema in these go packages
# if they match it will use them, otherwise it will generate them.
autobind:
- "github.com/ActiveState/cli/internal/graph"
# autobind:
# - "github.com/ActiveState/cli/internal/graph"

# This section declares type mapping between the GraphQL and go type systems
#
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package messages
package notifications

import (
"regexp"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package messages
package notifications

import (
"encoding/json"
Expand All @@ -25,15 +25,15 @@ import (

const ConfigKeyLastReport = "messages.last_reported"

type Messages struct {
type Notifications struct {
cfg *config.Instance
auth *auth.Auth
baseParams *ConditionParams
poll *poller.Poller
checkMutex sync.Mutex
}

func New(cfg *config.Instance, auth *auth.Auth) (*Messages, error) {
func New(cfg *config.Instance, auth *auth.Auth) (*Notifications, error) {
osVersion, err := sysinfo.OSVersion()
if err != nil {
return nil, errs.Wrap(err, "Could not get OS version")
Expand All @@ -52,7 +52,7 @@ func New(cfg *config.Instance, auth *auth.Auth) (*Messages, error) {
return resp, err
})

return &Messages{
return &Notifications{
baseParams: &ConditionParams{
OS: sysinfo.OS().String(),
OSVersion: NewVersionFromSysinfo(osVersion),
Expand All @@ -65,22 +65,22 @@ func New(cfg *config.Instance, auth *auth.Auth) (*Messages, error) {
}, nil
}

func (m *Messages) Close() error {
func (m *Notifications) Close() error {
m.poll.Close()
return nil
}

func (m *Messages) Check(command string, flags []string) ([]*graph.MessageInfo, error) {
// Prevent multiple checks at the same time, which could lead to the same message showing multiple times
func (m *Notifications) Check(command string, flags []string) ([]*graph.NotificationInfo, error) {
// Prevent multiple checks at the same time, which could lead to the same notification showing multiple times
m.checkMutex.Lock()
defer m.checkMutex.Unlock()

cacheValue := m.poll.ValueFromCache()
if cacheValue == nil {
return []*graph.MessageInfo{}, nil
return []*graph.NotificationInfo{}, nil
}

allMessages, ok := cacheValue.([]*graph.MessageInfo)
allNotifications, ok := cacheValue.([]*graph.NotificationInfo)
if !ok {
return nil, errs.New("cacheValue has unexpected type: %T", cacheValue)
}
Expand All @@ -95,38 +95,38 @@ func (m *Messages) Check(command string, flags []string) ([]*graph.MessageInfo,
conditionParams.UserID = id.String()
}

logging.Debug("Checking %d messages with params: %#v", len(allMessages), conditionParams)
logging.Debug("Checking %d notifications with params: %#v", len(allNotifications), conditionParams)

lastReportMap := m.cfg.GetStringMap(ConfigKeyLastReport)
msgs, err := check(&conditionParams, allMessages, lastReportMap, time.Now())
msgs, err := check(&conditionParams, allNotifications, lastReportMap, time.Now())
if err != nil {
return nil, errs.Wrap(err, "Could not check messages")
}
for _, msg := range msgs {
lastReportMap[msg.ID] = time.Now().Format(time.RFC3339)
}
if err := m.cfg.Set(ConfigKeyLastReport, lastReportMap); err != nil {
return nil, errs.Wrap(err, "Could not save last reported messages")
return nil, errs.Wrap(err, "Could not save last reported notifications")
}

return msgs, nil
}

func messageInDateRange(message *graph.MessageInfo, baseTime time.Time) (bool, error) {
if message.StartDate != "" {
startDate, err := time.Parse(time.RFC3339, message.StartDate)
func notificationInDateRange(notification *graph.NotificationInfo, baseTime time.Time) (bool, error) {
if notification.StartDate != "" {
startDate, err := time.Parse(time.RFC3339, notification.StartDate)
if err != nil {
return false, errs.Wrap(err, "Could not parse start date for message %s", message.ID)
return false, errs.Wrap(err, "Could not parse start date for notification %s", notification.ID)
}
if baseTime.Before(startDate) {
return false, nil
}
}

if message.EndDate != "" {
endDate, err := time.Parse(time.RFC3339, message.EndDate)
if notification.EndDate != "" {
endDate, err := time.Parse(time.RFC3339, notification.EndDate)
if err != nil {
return false, errs.Wrap(err, "Could not parse end date for message %s", message.ID)
return false, errs.Wrap(err, "Could not parse end date for notification %s", notification.ID)
}
if baseTime.After(endDate) {
return false, nil
Expand All @@ -136,73 +136,73 @@ func messageInDateRange(message *graph.MessageInfo, baseTime time.Time) (bool, e
return true, nil
}

func check(params *ConditionParams, messages []*graph.MessageInfo, lastReportMap map[string]interface{}, baseTime time.Time) ([]*graph.MessageInfo, error) {
func check(params *ConditionParams, notifications []*graph.NotificationInfo, lastReportMap map[string]interface{}, baseTime time.Time) ([]*graph.NotificationInfo, error) {
funcMap := conditionFuncMap()
filteredMessages := []*graph.MessageInfo{}
for _, message := range messages {
logging.Debug("Checking message %s", message.ID)
filteredNotifications := []*graph.NotificationInfo{}
for _, notification := range notifications {
logging.Debug("Checking notification %s", notification.ID)

// Ensure we don't show the same message too often
if lastReport, ok := lastReportMap[message.ID]; ok {
if lastReport, ok := lastReportMap[notification.ID]; ok {
lr, ok := lastReport.(string)
if !ok {
return nil, errs.New("Could not get last reported time for message %s as it's not a string: %T", message.ID, lastReport)
return nil, errs.New("Could not get last reported time for notification %s as it's not a string: %T", notification.ID, lastReport)
}
lastReportTime, err := time.Parse(time.RFC3339, lr)
if err != nil {
return nil, errs.New("Could not parse last reported time for message %s as it's not a valid RFC3339 value: %v", message.ID, lastReport)
return nil, errs.New("Could not parse last reported time for notification %s as it's not a valid RFC3339 value: %v", notification.ID, lastReport)
}

lastReportTimeAgo := baseTime.Sub(lastReportTime)
showMessage, err := repeatValid(message.Repeat, lastReportTimeAgo)
showNotification, err := repeatValid(notification.Repeat, lastReportTimeAgo)
if err != nil {
return nil, errs.Wrap(err, "Could not validate repeat for message %s", message.ID)
return nil, errs.Wrap(err, "Could not validate repeat for notification %s", notification.ID)
}

if !showMessage {
logging.Debug("Skipping message %s as it was shown %s ago", message.ID, lastReportTimeAgo)
if !showNotification {
logging.Debug("Skipping notification %s as it was shown %s ago", notification.ID, lastReportTimeAgo)
continue
}
}

// Check if message is within date range
inRange, err := messageInDateRange(message, baseTime)
inRange, err := notificationInDateRange(notification, baseTime)
if err != nil {
logging.Warning("Could not check if message %s is in date range: %v", message.ID, err)
logging.Warning("Could not check if notification %s is in date range: %v", notification.ID, err)
continue
}
if !inRange {
logging.Debug("Skipping message %s as it is outside of its date range", message.ID)
logging.Debug("Skipping notification %s as it is outside of its date range", notification.ID)
continue
}

// Validate the conditional
if message.Condition != "" {
result, err := strutils.ParseTemplate(fmt.Sprintf(`{{%s}}`, message.Condition), params, funcMap)
if notification.Condition != "" {
result, err := strutils.ParseTemplate(fmt.Sprintf(`{{%s}}`, notification.Condition), params, funcMap)
if err != nil {
logging.Warning("Could not parse condition template for message %s: %v", message.ID, err)
logging.Warning("Could not parse condition template for notification %s: %v", notification.ID, err)
continue
}
if result == "true" {
logging.Debug("Including message %s as condition %s evaluated to %s", message.ID, message.Condition, result)
filteredMessages = append(filteredMessages, message)
logging.Debug("Including notification %s as condition %s evaluated to %s", notification.ID, notification.Condition, result)
filteredNotifications = append(filteredNotifications, notification)
} else {
logging.Debug("Skipping message %s as condition %s evaluated to %s", message.ID, message.Condition, result)
logging.Debug("Skipping notification %s as condition %s evaluated to %s", notification.ID, notification.Condition, result)
}
} else {
logging.Debug("Including message %s as it has no condition", message.ID)
filteredMessages = append(filteredMessages, message)
logging.Debug("Including notification %s as it has no condition", notification.ID)
filteredNotifications = append(filteredNotifications, notification)
}
}

return filteredMessages, nil
return filteredNotifications, nil
}

func fetch() ([]*graph.MessageInfo, error) {
func fetch() ([]*graph.NotificationInfo, error) {
var body []byte
var err error

if v := os.Getenv(constants.MessagesOverrideEnvVarName); v != "" {
if v := os.Getenv(constants.NotificationsOverrideEnvVarName); v != "" {
body, err = fileutils.ReadFile(v)
if err != nil {
return nil, errs.Wrap(err, "Could not read messages override file")
Expand All @@ -214,40 +214,40 @@ func fetch() ([]*graph.MessageInfo, error) {
}
}

var messages []*graph.MessageInfo
if err := json.Unmarshal(body, &messages); err != nil {
var notifications []*graph.NotificationInfo
if err := json.Unmarshal(body, &notifications); err != nil {
return nil, errs.Wrap(err, "Could not unmarshall messages information")
}

// Set defaults
for _, message := range messages {
if message.Placement == "" {
message.Placement = graph.MessagePlacementTypeBeforeCmd
for _, notification := range notifications {
if notification.Placement == "" {
notification.Placement = graph.NotificationPlacementTypeBeforeCmd
}
if message.Interrupt == "" {
message.Interrupt = graph.MessageInterruptTypeDisabled
if notification.Interrupt == "" {
notification.Interrupt = graph.NotificationInterruptTypeDisabled
}
if message.Repeat == "" {
message.Repeat = graph.MessageRepeatTypeDisabled
if notification.Repeat == "" {
notification.Repeat = graph.NotificationRepeatTypeDisabled
}
}

return messages, nil
return notifications, nil
}

func repeatValid(repeatType graph.MessageRepeatType, lastReportTimeAgo time.Duration) (bool, error) {
func repeatValid(repeatType graph.NotificationRepeatType, lastReportTimeAgo time.Duration) (bool, error) {
switch repeatType {
case graph.MessageRepeatTypeConstantly:
case graph.NotificationRepeatTypeConstantly:
return true, nil
case graph.MessageRepeatTypeDisabled:
case graph.NotificationRepeatTypeDisabled:
return false, nil
case graph.MessageRepeatTypeHourly:
case graph.NotificationRepeatTypeHourly:
return lastReportTimeAgo >= time.Hour, nil
case graph.MessageRepeatTypeDaily:
case graph.NotificationRepeatTypeDaily:
return lastReportTimeAgo >= 24*time.Hour, nil
case graph.MessageRepeatTypeWeekly:
case graph.NotificationRepeatTypeWeekly:
return lastReportTimeAgo >= 7*24*time.Hour, nil
case graph.MessageRepeatTypeMonthly:
case graph.NotificationRepeatTypeMonthly:
return lastReportTimeAgo >= 30*24*time.Hour, nil
default:
return false, errs.New("Unknown repeat type: %s", repeatType)
Expand Down
Loading

0 comments on commit fbec1ec

Please sign in to comment.