Sync from /srv/compose/unified-media-manager

This commit is contained in:
Christopher Mayor
2026-04-24 10:45:19 -07:00
commit 7dbd00e537
132 changed files with 25394 additions and 0 deletions

View 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 ""
}