init
This commit is contained in:
131
internal/notify/notify.go
Normal file
131
internal/notify/notify.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ncore-hnr/internal/model"
|
||||
)
|
||||
|
||||
const manualNeededSubject = "nCore HnR manual work"
|
||||
|
||||
type Sender interface {
|
||||
SendManualNeeded(results []model.ActionResult) error
|
||||
}
|
||||
|
||||
type NotificationNTFY struct {
|
||||
URL string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
func (n NotificationNTFY) SendManualNeeded(results []model.ActionResult) error {
|
||||
body, ok := manualNeededText(results)
|
||||
if strings.TrimSpace(n.URL) == "" || !ok {
|
||||
return nil
|
||||
}
|
||||
client := n.HTTPClient
|
||||
if client == nil {
|
||||
client = &http.Client{Timeout: 15 * time.Second}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, n.URL, bytes.NewBufferString(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
|
||||
req.Header.Set("Title", manualNeededSubject)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return fmt.Errorf("notify returned %s", resp.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NotificationSMTP struct {
|
||||
Host string
|
||||
Port string
|
||||
Username string
|
||||
Password string
|
||||
From string
|
||||
To string
|
||||
}
|
||||
|
||||
func (s NotificationSMTP) SendManualNeeded(results []model.ActionResult) error {
|
||||
body, ok := manualNeededText(results)
|
||||
if strings.TrimSpace(s.Host) == "" || !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
host := strings.TrimSpace(s.Host)
|
||||
addr := net.JoinHostPort(host, strings.TrimSpace(s.Port))
|
||||
|
||||
from, err := mail.ParseAddress(strings.TrimSpace(s.From))
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse smtp from: %w", err)
|
||||
}
|
||||
recipients, err := mail.ParseAddressList(strings.TrimSpace(s.To))
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse smtp to: %w", err)
|
||||
}
|
||||
|
||||
to := make([]string, 0, len(recipients))
|
||||
for _, recipient := range recipients {
|
||||
to = append(to, recipient.Address)
|
||||
}
|
||||
|
||||
var auth smtp.Auth
|
||||
if strings.TrimSpace(s.Username) != "" || strings.TrimSpace(s.Password) != "" {
|
||||
auth = smtp.PlainAuth("", strings.TrimSpace(s.Username), strings.TrimSpace(s.Password), host)
|
||||
}
|
||||
|
||||
message := strings.Builder{}
|
||||
message.WriteString(fmt.Sprintf("From: %s\r\n", from.String()))
|
||||
message.WriteString(fmt.Sprintf("To: %s\r\n", formatAddressList(recipients)))
|
||||
message.WriteString(fmt.Sprintf("Subject: %s\r\n", manualNeededSubject))
|
||||
message.WriteString("MIME-Version: 1.0\r\n")
|
||||
message.WriteString("Content-Type: text/plain; charset=UTF-8\r\n")
|
||||
message.WriteString("\r\n")
|
||||
message.WriteString(body)
|
||||
|
||||
if err := smtp.SendMail(addr, auth, from.Address, to, []byte(message.String())); err != nil {
|
||||
return fmt.Errorf("send smtp notification: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func manualNeededText(results []model.ActionResult) (string, bool) {
|
||||
var body strings.Builder
|
||||
manualCount := 0
|
||||
body.WriteString("nCore HnR torrents need manual work:\n")
|
||||
for _, result := range results {
|
||||
if !result.ManualNeeded {
|
||||
continue
|
||||
}
|
||||
manualCount++
|
||||
body.WriteString(fmt.Sprintf("- %s", result.Torrent.Name))
|
||||
if result.QBit != nil {
|
||||
body.WriteString(fmt.Sprintf(" (qBit: %s, %.1f%%)", result.QBit.State, result.QBit.Progress*100))
|
||||
}
|
||||
body.WriteString("\n")
|
||||
}
|
||||
return body.String(), manualCount > 0
|
||||
}
|
||||
|
||||
func formatAddressList(addresses []*mail.Address) string {
|
||||
formatted := make([]string, 0, len(addresses))
|
||||
for _, address := range addresses {
|
||||
formatted = append(formatted, address.String())
|
||||
}
|
||||
return strings.Join(formatted, ", ")
|
||||
}
|
||||
Reference in New Issue
Block a user