9a5720e8ad
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Full namespace migration: update the Go module path and all import statements from git.mokoconsulting.tech to code.mokoconsulting.tech. Also updates all URL references in templates, workflows, configs, tests, and documentation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package mailer
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
|
|
sender_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/mailer/sender"
|
|
)
|
|
|
|
// SendUpdateNotification emails the admin and sends ntfy push when a new MokoGitea version is available.
|
|
func SendUpdateNotification(version, channel, releaseURL, dockerImage string) {
|
|
subject := fmt.Sprintf("[MokoGitea] Update available: %s (%s)", version, channel)
|
|
|
|
body := fmt.Sprintf(`MokoGitea Update Available
|
|
|
|
A new version is available on the %s channel.
|
|
|
|
Version: %s
|
|
Channel: %s
|
|
Current: %s`, channel, version, channel, setting.AppVer)
|
|
|
|
if releaseURL != "" {
|
|
body += fmt.Sprintf("\nRelease: %s", releaseURL)
|
|
}
|
|
if dockerImage != "" {
|
|
body += fmt.Sprintf("\nDocker: docker pull %s", dockerImage)
|
|
}
|
|
|
|
body += fmt.Sprintf("\n\nUpdate the channel in Site Administration > Dashboard.\n\n— %s", setting.AppName)
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|