Files
av1dae/internal/metadata/metadata.go
T

160 lines
3.6 KiB
Go

package metadata
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strings"
"time"
"videnc-vibe/pkg/types"
)
const (
omdbAPIURL = "https://www.omdbapi.com/"
tvmazeAPIURL = "https://api.tvmaze.com/"
)
var (
imdbRegex = regexp.MustCompile(`tt(\d+)`)
tvmRegex = regexp.MustCompile(`(?i)tvm(\d+)`)
seRegex = regexp.MustCompile(`(?i)s(\d+)e(\d+)`)
)
type OMDbResponse struct {
Title string `json:"Title"`
Year string `json:"Released"`
IMDBID string `json:"imdbID"`
Response string `json:"Response"`
Error string `json:"Error"`
}
type TVMazeShowResponse struct {
Name string `json:"name"`
Extern struct {
IMDB string `json:"imdb"`
} `json:"externals"`
}
type TVMazeEpisode struct {
Name string `json:"name"`
Season int `json:"season"`
Number int `json:"number"`
Airdate string `json:"airdate"`
Show TVMazeShowResponse `json:"show"`
}
type Client struct {
omdbAPIKey string
httpClient *http.Client
}
func NewClient(apiKey string) *Client {
return &Client{
omdbAPIKey: apiKey,
httpClient: &http.Client{Timeout: 10 * time.Second},
}
}
func ParseFilename(filename string) (isSeries bool, imdbID, tvmazeID, season, episode string) {
filename = strings.TrimSuffix(filename, ".mkv")
seMatch := seRegex.FindStringSubmatch(filename)
tvmMatch := tvmRegex.FindStringSubmatch(filename)
imdbMatch := imdbRegex.FindStringSubmatch(filename)
if seMatch != nil && tvmMatch != nil {
isSeries = true
season = fmt.Sprintf("%02d", parseInt(seMatch[1]))
episode = fmt.Sprintf("%02d", parseInt(seMatch[2]))
tvmazeID = tvmMatch[1]
return
}
if imdbMatch != nil {
imdbID = imdbMatch[0]
}
return
}
func parseInt(s string) int {
var n int
fmt.Sscanf(s, "%d", &n)
return n
}
func (c *Client) FetchMovieMetadata(imdbID string) (*types.Metadata, error) {
url := fmt.Sprintf("%s?i=%s&apikey=%s", omdbAPIURL, imdbID, c.omdbAPIKey)
resp, err := c.httpClient.Get(url)
if err != nil {
return nil, fmt.Errorf("fetching OMDb: %w", err)
}
defer resp.Body.Close()
var result OMDbResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("decoding OMDb response: %w", err)
}
if result.Response != "True" {
return nil, fmt.Errorf("OMDb error: %s", result.Error)
}
dateReleased := formatDate(result.Year)
return &types.Metadata{
Title: result.Title,
DateReleased: dateReleased,
IMDBID: result.IMDBID,
OriginalMedia: types.MediaTypeBluRay,
}, nil
}
func (c *Client) FetchSeriesMetadata(tvmazeID, season, episode string) (*types.Metadata, error) {
url := fmt.Sprintf("%s/shows/%s/episodebynumber?season=%s&number=%s", tvmazeAPIURL, tvmazeID, season, episode)
resp, err := c.httpClient.Get(url)
if err != nil {
return nil, fmt.Errorf("fetching TVmaze: %w", err)
}
defer resp.Body.Close()
var ep TVMazeEpisode
if err := json.NewDecoder(resp.Body).Decode(&ep); err != nil {
return nil, fmt.Errorf("decoding TVmaze response: %w", err)
}
dateReleased := formatDate(ep.Airdate)
var imdbID string
if ep.Show.Extern.IMDB != "" {
imdbID = ep.Show.Extern.IMDB
}
return &types.Metadata{
Title: ep.Name,
Collection: ep.Show.Name,
Season: season,
Episode: episode,
DateReleased: dateReleased,
IMDBID: imdbID,
TVMazeID: tvmazeID,
IsSeries: true,
OriginalMedia: types.MediaTypeBluRay,
}, nil
}
func formatDate(date string) string {
if date == "" || date == "N/A" {
return ""
}
t, err := time.Parse("02 Jan 2006", date)
if err != nil {
return date
}
return t.Format("2006-01-02")
}