Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""LICENSE
2Copyright 2015 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of toktokkie.
6toktokkie is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11toktokkie is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with toktokkie. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
20from abc import ABC
21from typing import List, Dict, Optional
22from toktokkie.enums import IdType
23from toktokkie.exceptions import InvalidMetadata
24from toktokkie.metadata.base.MetadataBase import MetadataBase
25from toktokkie.metadata.tv.components.TvSeason import TvSeason
26from toktokkie.metadata.tv.components.TvEpisode import TvEpisode
27from toktokkie.metadata.tv.components.TvEpisodeRange import TvEpisodeRange
30class TvExtras(MetadataBase, ABC):
31 """
32 Extra properties and methods specific to tv series
33 """
35 @property
36 def seasons(self) -> List[TvSeason]:
37 """
38 :return: A list of TV seasons
39 """
40 seasons_list = list(map(
41 lambda x: TvSeason.from_json(self.directory_path, self.ids, x),
42 self.json["seasons"]
43 ))
44 seasons_list.sort(
45 key=lambda season: season.name.replace("Season ", "")
46 )
47 return seasons_list
49 @seasons.setter
50 def seasons(self, seasons: List[TvSeason]):
51 """
52 Setter method for the seasons
53 :param seasons: The seasons to set
54 :return: None
55 """
56 self.json["seasons"] = []
57 for season in seasons:
58 print(season)
59 self.json["seasons"].append(season.json)
61 def get_season(self, season_name: str) -> TvSeason:
62 """
63 Retrieves a single season for a provided season name
64 :param season_name: The name of the season
65 :return: The season
66 :raises KeyError: If the season could not be found
67 """
68 for season in self.seasons:
69 if season.name == season_name:
70 return season
71 raise KeyError(season_name)
73 @property
74 def excludes(self) -> Dict[IdType, Dict[int, List[int]]]:
75 """
76 Generates data for episodes to be excluded during renaming etc.
77 :return A dictionary mapping episode anithemes to seasons and id types
78 Form: {idtype: {season: [ep1, ep2]}}
79 """
80 generated = {} # type: Dict[IdType, Dict[int, List[int]]]
82 for _id_type in self.json.get("excludes", {}):
84 id_type = IdType(_id_type)
85 generated[id_type] = {}
87 for exclude in self.json["excludes"][_id_type]:
89 try:
90 episode_range = TvEpisodeRange.from_json(exclude)
91 episodes = episode_range.episodes
92 except InvalidMetadata:
93 episodes = [TvEpisode.from_json(exclude)]
95 for episode in episodes:
96 if episode.season not in generated[id_type]:
97 generated[id_type][episode.season] = []
98 generated[id_type][episode.season].append(episode.episode)
100 return generated
102 @property
103 def season_start_overrides(self) -> Dict[IdType, Dict[int, int]]:
104 """
105 :return: A dictionary mapping episodes that override a season starting
106 point to ID types
107 Form: {idtype: {season: episode}}
108 """
109 return self.json.get("season_start_overrides", {})
111 @property
112 def multi_episodes(self) -> Dict[IdType, Dict[int, Dict[int, int]]]:
113 """
114 :return: A dictionary mapping lists of multi-episodes to id types
115 Form: {idtype: {season: {start: end}}}
116 """
117 generated = {} # type: Dict[IdType, Dict[int, Dict[int, int]]]
119 for _id_type in self.json.get("multi_episodes", {}):
121 id_type = IdType(_id_type)
122 generated[id_type] = {}
124 for multi_episode in self.json["multi_episodes"][_id_type]:
125 episode_range = TvEpisodeRange.from_json(multi_episode)
127 season_number = episode_range.season
128 start = episode_range.start_episode
129 end = episode_range.end_episode
131 if episode_range.season not in generated[id_type]:
132 generated[id_type][season_number] = {}
134 generated[id_type][season_number][start] = end
136 return generated
138 def add_multi_episode(
139 self,
140 id_type: IdType,
141 season: int,
142 start_episode: int,
143 end_episode: int
144 ):
145 """
146 Adds a multi-episode
147 :param id_type: The ID type
148 :param season: The season of the multi episode
149 :param start_episode: The start episode
150 :param end_episode: The end episode
151 :return: None
152 """
153 if "multi_episodes" not in self.json:
154 self.json["multi_episodes"] = {}
155 if id_type.value not in self.json["multi_episodes"]:
156 self.json["multi_episodes"][id_type.value] = []
158 self.json["multi_episodes"][id_type.value].append({
159 "season": season,
160 "start_episode": start_episode,
161 "end_episode": end_episode
162 })
164 def add_exclude(
165 self,
166 id_type: IdType,
167 season: int,
168 episode: int,
169 end_episode: Optional[int] = None
170 ):
171 """
172 Adds an excluded episode
173 :param id_type: The ID type
174 :param season: The season of the excluded episode
175 :param episode: The excluded episode number
176 :param end_episode: Optional end episode for multi-episode excludes
177 :return: None
178 """
179 if "excludes" not in self.json:
180 self.json["excludes"] = {}
181 if id_type.value not in self.json["excludes"]:
182 self.json["excludes"][id_type.value] = []
184 exclude = {"season": season}
185 if end_episode is None:
186 exclude.update({"episode": episode})
187 else:
188 exclude.update({
189 "start_episode": episode, "end_episode": end_episode
190 })
192 self.json["excludes"][id_type.value].append(exclude)
194 def add_season_start_override(
195 self, id_type: IdType, season: int, episode: int
196 ):
197 """
198 Adds a new season start override
199 :param id_type: The ID type
200 :param season: The season
201 :param episode: The episode
202 :return: None
203 """
204 if "season_start_overrides" not in self.json:
205 self.json["season_start_overrides"] = {}
206 if id_type not in self.json["season_start_overrides"]:
207 self.json["season_start_overrides"][id_type] = {}
209 self.json["season_start_overrides"][id_type][season] = episode