mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
package services
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"fotbal-club/internal/config"
|
|
"fotbal-club/internal/models"
|
|
"fotbal-club/pkg/email"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// StartNewsletterScheduler starts a background job that sends automated newsletters.
|
|
// It can be configured via env NEWSLETTER_INTERVAL_HOURS and is guarded by config.NewsletterEnabled.
|
|
func StartNewsletterScheduler(db *gorm.DB, emailSvc email.EmailService) {
|
|
interval := 24 * time.Hour // default daily for demo; real use might be weekly
|
|
if v := os.Getenv("NEWSLETTER_INTERVAL_HOURS"); v != "" {
|
|
if h, err := time.ParseDuration(v + "h"); err == nil {
|
|
interval = h
|
|
}
|
|
}
|
|
|
|
// Run once on startup only if enabled
|
|
if config.AppConfig != nil && config.AppConfig.NewsletterEnabled {
|
|
go runNewsletterCycle(db, emailSvc)
|
|
} else {
|
|
log.Printf("[newsletter] scheduler is disabled at startup; waiting for enable toggle")
|
|
}
|
|
|
|
// Periodic ticker
|
|
go func() {
|
|
ticker := time.NewTicker(interval)
|
|
defer ticker.Stop()
|
|
for range ticker.C {
|
|
if config.AppConfig != nil && config.AppConfig.NewsletterEnabled {
|
|
runNewsletterCycle(db, emailSvc)
|
|
} else {
|
|
log.Printf("[newsletter] skipped cycle (disabled)")
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func runNewsletterCycle(db *gorm.DB, emailSvc email.EmailService) {
|
|
log.Printf("[newsletter] starting automated newsletter cycle")
|
|
cacheDir := filepath.Join("cache", "prefetch")
|
|
|
|
// Fetch subscribers in batches
|
|
var subs []models.NewsletterSubscription
|
|
if err := db.Find(&subs).Error; err != nil {
|
|
log.Printf("[newsletter] failed to load subscribers: %v", err)
|
|
return
|
|
}
|
|
|
|
for _, s := range subs {
|
|
if !s.IsActive {
|
|
continue
|
|
}
|
|
// Normalize preferences to new structure
|
|
ct := make([]string, 0, 4)
|
|
if v, ok := s.Preferences["blogs"].(bool); ok && v { ct = append(ct, "blogs") }
|
|
if v, ok := s.Preferences["events"].(bool); ok && v { ct = append(ct, "events") }
|
|
if v, ok := s.Preferences["matches"].(bool); ok && v { ct = append(ct, "matches") }
|
|
if v, ok := s.Preferences["scores"].(bool); ok && v { ct = append(ct, "scores") }
|
|
// Backward-compat: weekly implies blogs; matches implies matches
|
|
if v, ok := s.Preferences["weekly"].(bool); ok && v && !contains(ct, "blogs") { ct = append(ct, "blogs") }
|
|
if v, ok := s.Preferences["matches"].(bool); ok && v && !contains(ct, "matches") { ct = append(ct, "matches") }
|
|
|
|
// Optional competitions list if stored under key like competitions
|
|
comps := []string{}
|
|
if raw, ok := s.Preferences["competitions"].(string); ok && raw != "" {
|
|
// comma-separated codes
|
|
for _, p := range strings.Split(raw, ",") {
|
|
if v := strings.TrimSpace(p); v != "" { comps = append(comps, v) }
|
|
}
|
|
}
|
|
|
|
prefs := NewsletterPrefs{
|
|
Email: s.Email,
|
|
ContentTypes: ct,
|
|
Competitions: comps,
|
|
Frequency: "daily",
|
|
}
|
|
subj, content := BuildNewsletterDigest(cacheDir, prefs)
|
|
if strings.TrimSpace(content) == "" { continue }
|
|
|
|
data := &email.NewsletterData{
|
|
Subject: subj,
|
|
Content: content,
|
|
Recipients: []string{s.Email},
|
|
}
|
|
|
|
if err := emailSvc.SendNewsletter(data); err != nil {
|
|
log.Printf("[newsletter] failed to send to %s: %v", s.Email, err)
|
|
}
|
|
// small sleep to avoid hammering SMTP
|
|
time.Sleep(200 * time.Millisecond)
|
|
}
|
|
|
|
log.Printf("[newsletter] automated cycle finished")
|
|
}
|
|
|
|
func contains(list []string, v string) bool {
|
|
for _, x := range list {
|
|
if x == v {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|