-
-
Notifications
You must be signed in to change notification settings - Fork 274
/
notify.go
140 lines (126 loc) Β· 4.09 KB
/
notify.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package updates
import (
"fmt"
"sync/atomic"
"time"
"github.com/safing/portbase/notifications"
)
const (
updateFailed = "updates:failed"
updateSuccess = "updates:success"
updateSuccessPending = "updates:success-pending"
updateSuccessDownloaded = "updates:success-downloaded"
failedUpdateNotifyDurationThreshold = 24 * time.Hour
failedUpdateNotifyCountThreshold = 3
)
var updateFailedCnt = new(atomic.Int32)
func notifyUpdateSuccess(forced bool) {
updateFailedCnt.Store(0)
module.Resolve(updateFailed)
updateState := registry.GetState().Updates
flavor := updateSuccess
switch {
case len(updateState.PendingDownload) > 0:
// Show notification if there are pending downloads.
flavor = updateSuccessPending
case updateState.LastDownloadAt != nil &&
time.Since(*updateState.LastDownloadAt) < time.Minute:
// Show notification if we downloaded something within the last minute.
flavor = updateSuccessDownloaded
case forced:
// Always show notification if update was manually triggered.
default:
// Otherwise, the update was uneventful. Do not show notification.
return
}
switch flavor {
case updateSuccess:
notifications.Notify(¬ifications.Notification{
EventID: updateSuccess,
Type: notifications.Info,
Title: "Portmaster Is Up-To-Date",
Message: "Portmaster successfully checked for updates. Everything is up to date. Most updates are applied automatically. You will be notified of important updates that need restarting.",
Expires: time.Now().Add(1 * time.Minute).Unix(),
AvailableActions: []*notifications.Action{
{
ID: "ack",
Text: "OK",
},
},
})
case updateSuccessPending:
notifications.Notify(¬ifications.Notification{
EventID: updateSuccess,
Type: notifications.Info,
Title: fmt.Sprintf("%d Updates Available", len(updateState.PendingDownload)),
Message: fmt.Sprintf(
`%d updates are available for download. Press "Download Now" or check for updates later to download and automatically apply all pending updates. You will be notified of important updates that need restarting.`,
len(updateState.PendingDownload),
),
AvailableActions: []*notifications.Action{
{
ID: "ack",
Text: "OK",
},
{
ID: "download",
Text: "Download Now",
Type: notifications.ActionTypeWebhook,
Payload: ¬ifications.ActionTypeWebhookPayload{
URL: apiPathCheckForUpdates,
ResultAction: "display",
},
},
},
})
case updateSuccessDownloaded:
notifications.Notify(¬ifications.Notification{
EventID: updateSuccess,
Type: notifications.Info,
Title: fmt.Sprintf("%d Updates Applied", len(updateState.LastDownload)),
Message: fmt.Sprintf(
`%d updates were downloaded and applied. You will be notified of important updates that need restarting.`,
len(updateState.LastDownload),
),
Expires: time.Now().Add(1 * time.Minute).Unix(),
AvailableActions: []*notifications.Action{
{
ID: "ack",
Text: "OK",
},
},
})
}
}
func notifyUpdateCheckFailed(forced bool, err error) {
failedCnt := updateFailedCnt.Add(1)
lastSuccess := registry.GetState().Updates.LastSuccessAt
switch {
case forced:
// Always show notification if update was manually triggered.
case failedCnt < failedUpdateNotifyCountThreshold:
// Not failed often enough for notification.
return
case lastSuccess == nil:
// No recorded successful update.
case time.Now().Add(-failedUpdateNotifyDurationThreshold).Before(*lastSuccess):
// Failed too recently for notification.
return
}
notifications.NotifyWarn(
updateFailed,
"Update Check Failed",
fmt.Sprintf(
"Portmaster failed to check for updates. This might be a temporary issue of your device, your network or the update servers. The Portmaster will automatically try again later. The error was: %s",
err,
),
notifications.Action{
Text: "Try Again Now",
Type: notifications.ActionTypeWebhook,
Payload: ¬ifications.ActionTypeWebhookPayload{
URL: apiPathCheckForUpdates,
ResultAction: "display",
},
},
).AttachToModule(module)
}