mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-30 19:54:16 -04:00
Add genres and studio objects for the scanner
This commit is contained in:
parent
c894f33c11
commit
10b291b4aa
@ -23,6 +23,7 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
using Kyoo.Postgresql;
|
using Kyoo.Postgresql;
|
||||||
|
using Kyoo.Utils;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Kyoo.Core.Controllers
|
namespace Kyoo.Core.Controllers
|
||||||
@ -61,6 +62,13 @@ namespace Kyoo.Core.Controllers
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override async Task Validate(Genre resource)
|
||||||
|
{
|
||||||
|
resource.Slug ??= Utility.ToSlug(resource.Name);
|
||||||
|
await base.Validate(resource);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<Genre> Create(Genre obj)
|
public override async Task<Genre> Create(Genre obj)
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.Abstractions.Controllers;
|
using Kyoo.Abstractions.Controllers;
|
||||||
using Kyoo.Abstractions.Models;
|
using Kyoo.Abstractions.Models;
|
||||||
using Kyoo.Postgresql;
|
using Kyoo.Postgresql;
|
||||||
|
using Kyoo.Utils;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Kyoo.Core.Controllers
|
namespace Kyoo.Core.Controllers
|
||||||
@ -80,6 +81,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task Validate(Studio resource)
|
protected override async Task Validate(Studio resource)
|
||||||
{
|
{
|
||||||
|
resource.Slug ??= Utility.ToSlug(resource.Name);
|
||||||
|
|
||||||
await base.Validate(resource);
|
await base.Validate(resource);
|
||||||
if (resource.ExternalIDs != null)
|
if (resource.ExternalIDs != null)
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ from providers.types.metadataid import MetadataID
|
|||||||
from ..provider import Provider
|
from ..provider import Provider
|
||||||
from ..types.movie import Movie, MovieTranslation
|
from ..types.movie import Movie, MovieTranslation
|
||||||
from ..types.status import Status
|
from ..types.status import Status
|
||||||
|
from ..types.studio import Studio
|
||||||
|
|
||||||
|
|
||||||
class TheMovieDatabase(Provider):
|
class TheMovieDatabase(Provider):
|
||||||
@ -84,8 +85,25 @@ class TheMovieDatabase(Provider):
|
|||||||
status=Status.FINISHED
|
status=Status.FINISHED
|
||||||
if movie["status"] == "Released"
|
if movie["status"] == "Released"
|
||||||
else Status.PLANNED,
|
else Status.PLANNED,
|
||||||
studios=list(map(lambda x: x["name"], movie["production_companies"])),
|
studios=[
|
||||||
genres=[self.genre_map[x["id"]] for x in movie["genres"] if x["id"] in self.genre_map],
|
Studio(
|
||||||
|
name=x["name"],
|
||||||
|
logos=[f"https://image.tmdb.org/t/p/original{x['logo_path']}"]
|
||||||
|
if "logo_path" in x
|
||||||
|
else [],
|
||||||
|
external_id={
|
||||||
|
"themoviedatabase": MetadataID(
|
||||||
|
x["id"], f"https://www.themoviedb.org/company/{x['id']}"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
for x in movie["production_companies"]
|
||||||
|
],
|
||||||
|
genres=[
|
||||||
|
self.genre_map[x["id"]]
|
||||||
|
for x in movie["genres"]
|
||||||
|
if x["id"] in self.genre_map
|
||||||
|
],
|
||||||
external_id={
|
external_id={
|
||||||
"themoviedatabase": MetadataID(
|
"themoviedatabase": MetadataID(
|
||||||
movie["id"], f"https://www.themoviedb.org/movie/{movie['id']}"
|
movie["id"], f"https://www.themoviedb.org/movie/{movie['id']}"
|
||||||
|
@ -13,6 +13,7 @@ class Provider:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls: type[Self], client: ClientSession) -> list[Self]:
|
def get_all(cls: type[Self], client: ClientSession) -> list[Self]:
|
||||||
from providers.implementations.themoviedatabase import TheMovieDatabase
|
from providers.implementations.themoviedatabase import TheMovieDatabase
|
||||||
|
|
||||||
providers = []
|
providers = []
|
||||||
|
|
||||||
tmdb = os.environ.get("THEMOVIEDB_APIKEY")
|
tmdb = os.environ.get("THEMOVIEDB_APIKEY")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class Genre(Enum):
|
class Genre(str, Enum):
|
||||||
ACTION = "action"
|
ACTION = "action"
|
||||||
ADVENTURE = "adventure"
|
ADVENTURE = "adventure"
|
||||||
ANIMATION = "animation"
|
ANIMATION = "animation"
|
||||||
@ -20,3 +20,6 @@ class Genre(Enum):
|
|||||||
THRILLER = "thriller"
|
THRILLER = "thriller"
|
||||||
WAR = "war"
|
WAR = "war"
|
||||||
WESTERN = "western"
|
WESTERN = "western"
|
||||||
|
|
||||||
|
def to_kyoo(self):
|
||||||
|
return {"name": self}
|
||||||
|
@ -3,8 +3,10 @@ from dataclasses import asdict, dataclass, field
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
from .genre import Genre
|
from .genre import Genre
|
||||||
from .status import Status
|
from .status import Status
|
||||||
|
from .studio import Studio
|
||||||
from .metadataid import MetadataID
|
from .metadataid import MetadataID
|
||||||
|
|
||||||
|
|
||||||
@ -28,7 +30,7 @@ class Movie:
|
|||||||
release_date: Optional[date | int] = None
|
release_date: Optional[date | int] = None
|
||||||
status: Status = Status.UNKNOWN
|
status: Status = Status.UNKNOWN
|
||||||
path: Optional[str] = None
|
path: Optional[str] = None
|
||||||
studios: list[str] = field(default_factory=list)
|
studios: list[Studio] = field(default_factory=list)
|
||||||
genres: list[Genre] = field(default_factory=list)
|
genres: list[Genre] = field(default_factory=list)
|
||||||
# TODO: handle staff
|
# TODO: handle staff
|
||||||
# staff: list[Staff]
|
# staff: list[Staff]
|
||||||
@ -36,6 +38,13 @@ class Movie:
|
|||||||
|
|
||||||
translations: dict[str, MovieTranslation] = field(default_factory=dict)
|
translations: dict[str, MovieTranslation] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def format_date(self, date: date | int | None) -> str | None:
|
||||||
|
if date is None:
|
||||||
|
return None
|
||||||
|
if isinstance(date, int):
|
||||||
|
return f"{date}-01-01T00:00:00Z"
|
||||||
|
return date.isoformat()
|
||||||
|
|
||||||
def to_kyoo(self):
|
def to_kyoo(self):
|
||||||
# For now, the API of kyoo only support one language so we remove the others.
|
# For now, the API of kyoo only support one language so we remove the others.
|
||||||
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
|
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
|
||||||
@ -43,11 +52,15 @@ class Movie:
|
|||||||
**asdict(self),
|
**asdict(self),
|
||||||
**asdict(self.translations[default_language]),
|
**asdict(self.translations[default_language]),
|
||||||
"poster": next(iter(self.translations[default_language].posters), None),
|
"poster": next(iter(self.translations[default_language].posters), None),
|
||||||
"thumbnail": next(iter(self.translations[default_language].thumbnails), None),
|
"thumbnail": next(
|
||||||
|
iter(self.translations[default_language].thumbnails), None
|
||||||
|
),
|
||||||
"logo": next(iter(self.translations[default_language].logos), None),
|
"logo": next(iter(self.translations[default_language].logos), None),
|
||||||
"trailer": next(iter(self.translations[default_language].trailers), None),
|
"trailer": next(iter(self.translations[default_language].trailers), None),
|
||||||
"studio": next(iter(self.studios), None),
|
"studio": next(iter(x.to_kyoo() for x in self.studios), None),
|
||||||
"startAir": self.release_date,
|
"release_date": None,
|
||||||
|
"startAir": self.format_date(self.release_date),
|
||||||
"title": self.translations[default_language].name,
|
"title": self.translations[default_language].name,
|
||||||
|
"genres": [x.to_kyoo() for x in self.genres],
|
||||||
"isMovie": True,
|
"isMovie": True,
|
||||||
}
|
}
|
||||||
|
13
scanner/providers/types/studio.py
Normal file
13
scanner/providers/types/studio.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from dataclasses import asdict, dataclass, field
|
||||||
|
|
||||||
|
from .metadataid import MetadataID
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Studio:
|
||||||
|
name: str
|
||||||
|
logos: list[str] = field(default_factory=list)
|
||||||
|
external_id: dict[str, MetadataID] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def to_kyoo(self):
|
||||||
|
return asdict(self)
|
@ -45,9 +45,9 @@ class Scanner:
|
|||||||
movie = await self.provider.identify_movie(
|
movie = await self.provider.identify_movie(
|
||||||
raw["title"], raw.get("year"), language=self.languages
|
raw["title"], raw.get("year"), language=self.languages
|
||||||
)
|
)
|
||||||
|
movie.path = str(path)
|
||||||
logging.debug("Got movie: %s", movie)
|
logging.debug("Got movie: %s", movie)
|
||||||
await self.post("movies", data=movie.to_kyoo())
|
await self.post("movies", data=movie.to_kyoo())
|
||||||
movie.path = str(path)
|
|
||||||
elif raw["type"] == "episode":
|
elif raw["type"] == "episode":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user