diff --git a/services/mailer/mail_update.go b/services/mailer/mail_update.go index 1b35106589..eb41a10b23 100644 --- a/services/mailer/mail_update.go +++ b/services/mailer/mail_update.go @@ -4,8 +4,11 @@ package mailer import ( + "bytes" "context" "fmt" + "io" + "net/http" user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user" "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log" @@ -13,19 +16,8 @@ import ( sender_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/mailer/sender" ) -// SendUpdateNotification emails all admin users when a new MokoGitea version is available. +// SendUpdateNotification emails the admin and sends ntfy push when a new MokoGitea version is available. func SendUpdateNotification(version, channel, releaseURL, dockerImage string) { - if setting.MailService == nil { - log.Debug("Update notification skipped: mail service not configured") - return - } - - admin, err := user_model.GetAdminUser(context.Background()) - if err != nil { - log.Error("SendUpdateNotification: GetAdminUser: %v", err) - return - } - subject := fmt.Sprintf("[MokoGitea] Update available: %s (%s)", version, channel) body := fmt.Sprintf(`MokoGitea Update Available @@ -45,9 +37,57 @@ Current: %s`, channel, version, channel, setting.AppVer) body += fmt.Sprintf("\n\nUpdate the channel in Site Administration > Dashboard.\n\n— %s", setting.AppName) - msg := sender_service.NewMessage(admin.EmailTo(), subject, body) - msg.Info = "Update notification" + // Send email to admin + if setting.MailService != nil { + admin, err := user_model.GetAdminUser(context.Background()) + if err != nil { + log.Error("SendUpdateNotification: GetAdminUser: %v", err) + } else { + msg := sender_service.NewMessage(admin.EmailTo(), subject, body) + msg.Info = "Update notification" + SendAsync(msg) + log.Info("Update email sent to %s for version %s [%s]", admin.Email, version, channel) + } + } - SendAsync(msg) - log.Info("Update notification sent to %s for version %s [%s]", admin.Email, version, channel) + // Send ntfy push notification + if setting.Ntfy.Enabled && setting.Ntfy.ServerURL != "" { + sendNtfyNotification(subject, body, releaseURL) + } +} + +func sendNtfyNotification(title, body, clickURL string) { + url := fmt.Sprintf("%s/%s", setting.Ntfy.ServerURL, setting.Ntfy.DefaultTopic) + + req, err := http.NewRequest("POST", url, bytes.NewBufferString(body)) + if err != nil { + log.Error("ntfy: create request: %v", err) + return + } + + req.Header.Set("Title", title) + req.Header.Set("Priority", "high") + req.Header.Set("Tags", "arrow_up,mokogitea") + if clickURL != "" { + req.Header.Set("Click", clickURL) + } + if setting.Ntfy.Token != "" { + req.Header.Set("Authorization", "Bearer "+setting.Ntfy.Token) + } + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Error("ntfy: send notification: %v", err) + return + } + defer resp.Body.Close() + io.Copy(io.Discard, resp.Body) + + if resp.StatusCode >= 300 { + log.Error("ntfy: unexpected status %d", resp.StatusCode) + return + } + + log.Info("ntfy: update notification sent to %s/%s", setting.Ntfy.ServerURL, setting.Ntfy.DefaultTopic) }