tvmaze: Assign tags based on country, language, network/webchannel, genre, type based on TagKey

- type & genre were already supported before but now use TagKey instead of correctly titled tags
master
Felix Stupp 1 year ago
parent c5eb23ebff
commit a3a07e6ce0
Signed by: zocker
GPG Key ID: 93E1BD26F6B02FB7

@ -3,14 +3,32 @@ from __future__ import annotations
from typing import (
Any,
Dict,
Iterable,
List,
Literal,
NewType,
Optional,
TypeVar,
TypedDict,
Union,
)
from ...models import Tag, TagKey
from ...models.localization import (
get_country_tag as get_country_tag_by_code,
get_language_tag,
)
EXTRACTOR_KEY = ".extractor/com.tvmaze"
EXTRACTOR_NAME = "TVMaze"
GenreName = NewType("GenreName", str)
NetworkId = NewType("NetworkId", int)
ShowTypeName = NewType("ShowTypeName", str)
WebChannelId = NewType("WebChannelId", int)
Weekdays = Union[
Literal["Monday"],
@ -76,7 +94,7 @@ def select_best_image(*image_list: TvmazeImage) -> Optional[str]:
class TvmazeNetwork(TypedDict):
id: int
id: NetworkId
name: str
country: TvmazeCountry
webChannel: Optional[Any]
@ -100,8 +118,8 @@ class TvmazeSeason(TypedDict):
episodeOrder: int
premiereDate: str
endDate: str
network: TvmazeNetwork
webChannel: Optional[Any]
network: Optional[TvmazeNetwork]
webChannel: Optional[TvmazeWebChannel]
image: TvmazeImage
summary: str
@ -110,9 +128,9 @@ class TvmazeShow(TypedDict):
id: int
url: str
name: str
type: str
type: ShowTypeName
language: str
genres: List[str]
genres: List[GenreName]
status: str
runtime: int
averageRuntime: int
@ -122,6 +140,9 @@ class TvmazeShow(TypedDict):
schedule: TvmazeSchedule
rating: TvmazeRating
weight: int
network: Optional[TvmazeNetwork]
webChannel: Optional[TvmazeWebChannel]
dvdCountry: Optional[TvmazeCountry]
externals: TvmazeExternalIds
image: TvmazeImage
summary: str
@ -132,6 +153,13 @@ class TvmazeShowEmbedded(TvmazeShow):
_embedded: TvmazeEmbeddings
class TvmazeWebChannel(TypedDict):
id: WebChannelId
name: str
country: TvmazeCountry
dvdCountry: Optional[TvmazeCountry]
T = TypeVar("T", bound=Dict)
@ -140,3 +168,110 @@ def add_embedding(object: T, key: str, value: Any, parent_key: str = "_embedded"
object[parent_key] = {}
object[parent_key][key] = value
return object
# Tag related stuff
GENRE_PREFIX = f"{EXTRACTOR_KEY}/genre"
NETWORK_PREFIX = f"{EXTRACTOR_KEY}/network"
SHOW_TYPE_PREFIX = f"{EXTRACTOR_KEY}/show_type"
WEB_CHANNEL_PREFIX = f"{EXTRACTOR_KEY}/web_channel"
## multi tag generators
def get_show_tags(show: TvmazeShow) -> Iterable[Tag]:
general_video_tag = TagKey.get_tag(".kind/video")
if general_video_tag is not None:
yield general_video_tag
yield get_show_type_tag(show["type"])
yield get_language_tag(show["language"])
for genre in show["genres"]:
yield get_genre_tag(genre)
network = show["network"]
if network is not None:
yield from get_all_network_tags(network)
web_channel = show["webChannel"]
if web_channel is not None:
yield from get_all_web_channel_tags(web_channel)
def get_all_network_tags(network: TvmazeNetwork) -> Iterable[Tag]:
country = network["country"]
if country is not None:
yield get_country_tag(country)
yield get_network_tag(network)
def get_all_web_channel_tags(web_channel: TvmazeWebChannel) -> Iterable[Tag]:
country = web_channel["country"]
if country is not None:
yield get_country_tag(country)
yield get_web_channel_tag(web_channel)
## single tag generators
def get_country_tag(country: TvmazeCountry) -> Tag:
return get_country_tag_by_code(country["code"])
def get_genre_tag(genre_name: GenreName) -> Tag:
return get_any_tag(
category_key=GENRE_PREFIX,
category_name="Genre",
element_key=genre_name.lower(),
element_name=genre_name,
)
def get_network_tag(network: TvmazeNetwork) -> Tag:
return get_any_tag(
category_key=NETWORK_PREFIX,
category_name="Network",
element_key=str(network["id"]),
element_name=network["name"],
)
def get_show_type_tag(show_type_name: ShowTypeName) -> Tag:
return get_any_tag(
category_key=SHOW_TYPE_PREFIX,
category_name="Show Type",
element_key=show_type_name.lower(),
element_name=show_type_name,
)
def get_web_channel_tag(web_channel: TvmazeWebChannel) -> Tag:
return get_any_tag(
category_key=WEB_CHANNEL_PREFIX,
category_name="Web Channel",
element_key=str(web_channel["id"]),
element_name=web_channel["name"],
)
def get_any_tag(
*,
category_key: str,
category_name: str,
element_key: str,
element_name: str,
) -> Tag:
TagKey.get_or_create_tag(
tag_key=category_key,
title=f"[{EXTRACTOR_NAME}] {category_name}",
use_for_preferences=False,
)
return TagKey.get_or_create_tag(
tag_key=f"{category_key}/{element_key}",
title=f"[{EXTRACTOR_NAME}] [{category_name}] {element_name}",
use_for_preferences=True,
super_tags=[
category_key,
],
)

@ -1,21 +1,21 @@
from __future__ import annotations
from datetime import datetime
import itertools
import re
from typing import List, Optional
from typing import Optional
from pony import orm # TODO remove
import requests
from ...models import (
MediaCollection,
Tag,
MediaElement,
)
from ..all.tvmaze import (
TvmazeEpisodeEmbedded,
TvmazeShowEmbedded,
add_embedding,
get_show_tags,
)
from ..generic import (
ChangedReport,
@ -125,12 +125,9 @@ class TvmazeCollectionExtractor(CollectionExtractor[TvmazeShowEmbedded]):
self.__get_show_custom_uri(data["id"]),
)
)
for genre in itertools.chain(["Video", data["type"]], data["genres"]):
tag_list: List[Tag] = list(
orm.select(tag for tag in Tag if tag.title == genre)
)
if len(tag_list) == 1:
object.tag_list.add(tag_list[0])
for tag in get_show_tags(data):
object.tag_list.add(tag)
elem_set = set[MediaElement]()
for episode in data["_embedded"]["episodes"]:
if episode["airstamp"] is not None:
add_embedding(episode, "show", data)

@ -9,7 +9,6 @@ import requests
from ...models import MediaElement, MediaThumbnail
from ..all.tvmaze import (
TvmazeEpisodeEmbedded,
TvmazeShowEmbedded,
select_best_image,
)
from ..generic import (

Loading…
Cancel
Save