Sync from /srv/compose/unified-media-manager
This commit is contained in:
103
internal/service/calendar.go
Normal file
103
internal/service/calendar.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/TopherMayor/unified-media-manager/internal/db"
|
||||
)
|
||||
|
||||
// CalendarEvent represents a single event on the calendar.
|
||||
type CalendarEvent struct {
|
||||
ID int64 `json:"id"`
|
||||
MediaType string `json:"media_type"`
|
||||
Title string `json:"title"`
|
||||
Date string `json:"date"`
|
||||
Year *int `json:"year,omitempty"`
|
||||
Status string `json:"status"`
|
||||
PosterURL string `json:"poster_url,omitempty"`
|
||||
}
|
||||
|
||||
// CalendarService queries monitored media by release date for calendar views.
|
||||
type CalendarService struct {
|
||||
db *db.DB
|
||||
}
|
||||
|
||||
// NewCalendarService creates a new CalendarService.
|
||||
func NewCalendarService(database *db.DB) *CalendarService {
|
||||
return &CalendarService{db: database}
|
||||
}
|
||||
|
||||
type posterImage struct {
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// EventsByMonth returns all monitored media with release dates in the given month.
|
||||
func (s *CalendarService) EventsByMonth(ctx context.Context, year int, month time.Month) ([]CalendarEvent, error) {
|
||||
startDate := time.Date(year, month, 1, 0, 0, 0, 0, time.UTC)
|
||||
endDate := startDate.AddDate(0, 1, 0).Add(-time.Nanosecond)
|
||||
|
||||
query := `SELECT id, media_type, title, release_date, year, status, images
|
||||
FROM media
|
||||
WHERE monitored = true AND deleted_at IS NULL
|
||||
AND release_date IS NOT NULL
|
||||
AND release_date BETWEEN $1 AND $2
|
||||
ORDER BY release_date`
|
||||
|
||||
rows, err := s.db.Pool.Query(ctx, query, startDate, endDate)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query calendar events: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var events []CalendarEvent
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
var mediaType, title, status string
|
||||
var releaseDate time.Time
|
||||
var yearVal *int
|
||||
var imagesJSON []byte
|
||||
|
||||
if err := rows.Scan(&id, &mediaType, &title, &releaseDate, &yearVal, &status, &imagesJSON); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
posterURL := extractPosterURL(imagesJSON)
|
||||
|
||||
events = append(events, CalendarEvent{
|
||||
ID: id,
|
||||
MediaType: mediaType,
|
||||
Title: title,
|
||||
Date: releaseDate.Format("2006-01-02"),
|
||||
Year: yearVal,
|
||||
Status: status,
|
||||
PosterURL: posterURL,
|
||||
})
|
||||
}
|
||||
|
||||
if events == nil {
|
||||
events = []CalendarEvent{}
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// extractPosterURL parses the images JSONB and returns the first poster URL.
|
||||
func extractPosterURL(imagesJSON []byte) string {
|
||||
if len(imagesJSON) == 0 {
|
||||
return ""
|
||||
}
|
||||
var images []posterImage
|
||||
if err := json.Unmarshal(imagesJSON, &images); err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, img := range images {
|
||||
if img.Type == "poster" && img.URL != "" {
|
||||
return img.URL
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user