Files
Jonathan Miller 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
chore: rename Go module from git. to code.mokoconsulting.tech (#336)
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>
2026-05-31 10:28:25 -05:00

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)
}