mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-05 03:02:56 +00:00
upload
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user