downloaders have access to overrides

This commit is contained in:
Jesse Bannon 2022-08-31 22:12:55 -07:00
parent 74c9210448
commit 7ef5947fd7
8 changed files with 47 additions and 72 deletions

View file

@ -88,6 +88,7 @@ class Downloader(DownloadArchiver, Generic[DownloaderOptionsT, DownloaderEntryT]
download_options: DownloaderOptionsT, download_options: DownloaderOptionsT,
enhanced_download_archive: EnhancedDownloadArchive, enhanced_download_archive: EnhancedDownloadArchive,
ytdl_options_builder: YTDLOptionsBuilder, ytdl_options_builder: YTDLOptionsBuilder,
overrides: Overrides,
): ):
""" """
Parameters Parameters
@ -98,14 +99,16 @@ class Downloader(DownloadArchiver, Generic[DownloaderOptionsT, DownloaderEntryT]
Download archive Download archive
ytdl_options_builder ytdl_options_builder
YTDL options builder YTDL options builder
overrides
Override variables
""" """
DownloadArchiver.__init__(self=self, enhanced_download_archive=enhanced_download_archive) DownloadArchiver.__init__(self=self, enhanced_download_archive=enhanced_download_archive)
self.download_options = download_options self.download_options = download_options
self.overrides = overrides
self._ytdl_options_builder = ytdl_options_builder.clone().add( self._ytdl_options_builder = ytdl_options_builder.clone().add(
self.ytdl_option_defaults(), before=True self.ytdl_option_defaults(), before=True
) )
self._added_override_variables: Dict[str, str] = {}
@contextmanager @contextmanager
def ytdl_downloader(self, ytdl_options_overrides: Optional[Dict] = None) -> ytdl.YoutubeDL: def ytdl_downloader(self, ytdl_options_overrides: Optional[Dict] = None) -> ytdl.YoutubeDL:
@ -128,28 +131,6 @@ class Downloader(DownloadArchiver, Generic[DownloaderOptionsT, DownloaderEntryT]
""" """
return self._ytdl_options_builder.to_dict().get("skip_download", False) return self._ytdl_options_builder.to_dict().get("skip_download", False)
def add_override_variables(self, override_variables_to_add: Dict[str, str]) -> None:
"""
Override variables added from the downloader. Should be added before yielding
entries
Parameters
----------
override_variables_to_add
The override variables to add
"""
self._added_override_variables = dict(
self._added_override_variables, **override_variables_to_add
)
def get_added_override_variables(self) -> Dict[str, str]:
"""
Returns
-------
Added override variables
"""
return self._added_override_variables
def extract_info(self, ytdl_options_overrides: Optional[Dict] = None, **kwargs) -> Dict: def extract_info(self, ytdl_options_overrides: Optional[Dict] = None, **kwargs) -> Dict:
""" """
Wrapper around yt_dlp.YoutubeDL.YoutubeDL.extract_info Wrapper around yt_dlp.YoutubeDL.YoutubeDL.extract_info
@ -354,14 +335,9 @@ class Downloader(DownloadArchiver, Generic[DownloaderOptionsT, DownloaderEntryT]
) -> Iterable[DownloaderEntryT] | Iterable[Tuple[DownloaderEntryT, FileMetadata]]: ) -> Iterable[DownloaderEntryT] | Iterable[Tuple[DownloaderEntryT, FileMetadata]]:
"""The function to perform the download of all media entries""" """The function to perform the download of all media entries"""
def post_download(self, overrides: Overrides): def post_download(self):
""" """
After all media entries have been downloaded, post processed, and moved to the output After all media entries have been downloaded, post processed, and moved to the output
directory, run this function. This lets the downloader add any extra files directly to the directory, run this function. This lets the downloader add any extra files directly to the
output directory, for things like YT channel image, banner. output directory, for things like YT channel image, banner.
Parameters
----------
overrides:
Subscription overrides
""" """

View file

@ -137,12 +137,15 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
download_options: DownloaderOptionsT, download_options: DownloaderOptionsT,
enhanced_download_archive: EnhancedDownloadArchive, enhanced_download_archive: EnhancedDownloadArchive,
ytdl_options_builder: YTDLOptionsBuilder, ytdl_options_builder: YTDLOptionsBuilder,
overrides: Overrides,
): ):
super().__init__( super().__init__(
download_options=download_options, download_options=download_options,
enhanced_download_archive=enhanced_download_archive, enhanced_download_archive=enhanced_download_archive,
ytdl_options_builder=ytdl_options_builder, ytdl_options_builder=ytdl_options_builder,
overrides=overrides,
) )
self.channel: Optional[YoutubeChannel] = None self.channel: Optional[YoutubeChannel] = None
def _get_channel(self, entry_dicts: List[Dict]) -> YoutubeChannel: def _get_channel(self, entry_dicts: List[Dict]) -> YoutubeChannel:
@ -151,6 +154,12 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
working_directory=self.working_directory, working_directory=self.working_directory,
) )
def _get_channel_videos(self, entry_dicts: List[Dict]) -> List[YoutubeVideo]:
return [
YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory)
for entry_dict in self._filter_entry_dicts(entry_dicts, sort_by="playlist_index")
]
def download(self) -> Generator[YoutubeVideo, None, None]: def download(self) -> Generator[YoutubeVideo, None, None]:
""" """
Downloads all videos from a channel Downloads all videos from a channel
@ -172,21 +181,19 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
log_prefix_on_info_json_dl="Downloading metadata for", log_prefix_on_info_json_dl="Downloading metadata for",
url=self.download_options.channel_url, url=self.download_options.channel_url,
) )
self.channel = self._get_channel(entry_dicts=entry_dicts)
self.add_override_variables(
override_variables_to_add={
"source_description": self.channel.kwargs_get("description", "")
}
)
channel_videos = self._filter_entry_dicts(entry_dicts, sort_by="playlist_index") self.channel = self._get_channel(entry_dicts=entry_dicts)
entries_to_download = self._get_channel_videos(entry_dicts=entry_dicts)
self.overrides.add_override_variables(
variables_to_add={"source_description": self.channel.kwargs_get("description", "")}
)
# Iterate in descending order to process older videos first. In case an error occurs and a # Iterate in descending order to process older videos first. In case an error occurs and a
# the channel must be redownloaded, it will fetch most recent metadata first, and break # the channel must be redownloaded, it will fetch most recent metadata first, and break
# on the older video that's been processed and is in the download archive. # on the older video that's been processed and is in the download archive.
for idx, entry_dict in enumerate(reversed(channel_videos), start=1): for idx, video in enumerate(reversed(entries_to_download), start=1):
video = YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory) download_logger.info("Downloading %d/%d %s", idx, len(entries_to_download), video.title)
download_logger.info("Downloading %d/%d %s", idx, len(entry_dicts), video.title)
# Re-download the contents even if it's a dry-run as a single video. At this time, # Re-download the contents even if it's a dry-run as a single video. At this time,
# channels do not download subtitles or subtitle metadata # channels do not download subtitles or subtitle metadata
@ -226,17 +233,12 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
thumbnail_url=thumbnail_url, output_thumbnail_path=output_thumbnail_path thumbnail_url=thumbnail_url, output_thumbnail_path=output_thumbnail_path
) )
def post_download(self, overrides: Overrides): def post_download(self):
""" """
Downloads and moves channel avatar and banner images to the output directory. Downloads and moves channel avatar and banner images to the output directory.
Parameters
----------
overrides
Overrides that can contain variables in the avatar or banner file path
""" """
if self.download_options.channel_avatar_path: if self.download_options.channel_avatar_path:
avatar_thumbnail_name = overrides.apply_formatter( avatar_thumbnail_name = self.overrides.apply_formatter(
self.download_options.channel_avatar_path self.download_options.channel_avatar_path
) )
self._download_thumbnail( self._download_thumbnail(
@ -246,7 +248,7 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
self.save_file(file_name=avatar_thumbnail_name) self.save_file(file_name=avatar_thumbnail_name)
if self.download_options.channel_banner_path: if self.download_options.channel_banner_path:
banner_thumbnail_name = overrides.apply_formatter( banner_thumbnail_name = self.overrides.apply_formatter(
self.download_options.channel_banner_path self.download_options.channel_banner_path
) )
self._download_thumbnail( self._download_thumbnail(

View file

@ -82,8 +82,8 @@ class YoutubePlaylistDownloader(
) )
playlist = self._filter_entry_dicts(entry_dicts, extractor="youtube:tab")[0] playlist = self._filter_entry_dicts(entry_dicts, extractor="youtube:tab")[0]
self.add_override_variables( self.overrides.add_override_variables(
override_variables_to_add={"source_description": playlist.get("description", "")} variables_to_add={"source_description": playlist.get("description", "")}
) )
# Iterate in reverse order to process older videos first. In case an error occurs and a # Iterate in reverse order to process older videos first. In case an error occurs and a

View file

@ -69,6 +69,6 @@ class YoutubeVideoDownloader(YoutubeDownloader[YoutubeVideoDownloaderOptions, Yo
"""Download a single Youtube video""" """Download a single Youtube video"""
entry_dict = self.extract_info(url=self.download_options.video_url) entry_dict = self.extract_info(url=self.download_options.video_url)
video = YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory) video = YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory)
self.add_override_variables({"source_description": video.description}) self.overrides.add_override_variables({"source_description": video.description})
return [video] return [video]

View file

@ -36,6 +36,9 @@ class BaseEntry(ABC):
return self._kwargs[key] return self._kwargs[key]
def kwargs_get(self, key: str, default: Optional[Any] = None) -> Any: def kwargs_get(self, key: str, default: Optional[Any] = None) -> Any:
"""
Dict get on kwargs
"""
if not self.kwargs_contains(key): if not self.kwargs_contains(key):
return default return default
return self.kwargs(key) return self.kwargs(key)

View file

@ -234,7 +234,6 @@ class SubscriptionDownload(BaseSubscription, ABC):
""" """
self._enhanced_download_archive.reinitialize(dry_run=dry_run) self._enhanced_download_archive.reinitialize(dry_run=dry_run)
plugins = self._initialize_plugins() plugins = self._initialize_plugins()
added_override_variables = False
ytdl_options_builder = SubscriptionYTDLOptions( ytdl_options_builder = SubscriptionYTDLOptions(
preset=self._preset_options, preset=self._preset_options,
@ -249,16 +248,10 @@ class SubscriptionDownload(BaseSubscription, ABC):
download_options=self.downloader_options, download_options=self.downloader_options,
enhanced_download_archive=self._enhanced_download_archive, enhanced_download_archive=self._enhanced_download_archive,
ytdl_options_builder=ytdl_options_builder, ytdl_options_builder=ytdl_options_builder,
overrides=self.overrides,
) )
for entry in downloader.download(): for entry in downloader.download():
# TODO: make this a step before download
if not added_override_variables:
self.overrides.add_override_variables(
variables_to_add=downloader.get_added_override_variables()
)
added_override_variables = True
entry_metadata = FileMetadata() entry_metadata = FileMetadata()
if isinstance(entry, tuple): if isinstance(entry, tuple):
entry, entry_metadata = entry entry, entry_metadata = entry
@ -272,7 +265,7 @@ class SubscriptionDownload(BaseSubscription, ABC):
plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
) )
downloader.post_download(overrides=self.overrides) downloader.post_download()
for plugin in plugins: for plugin in plugins:
plugin.post_process_subscription() plugin.post_process_subscription()

View file

@ -1,55 +1,55 @@
{ {
".ytdl-sub-pz-download-archive.json": "70615451318cdb5e018e007c77893a39", ".ytdl-sub-pz-download-archive.json": "70615451318cdb5e018e007c77893a39",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e", "Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.info.json": "5d16096bc4256239932db2c2d98161a3", "Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.info.json": "a5e93b8087ba3e0fa4a8410b5929eded",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.mp4": "931a705864c57d21d6fedebed4af6bbc", "Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.mp4": "931a705864c57d21d6fedebed4af6bbc",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.nfo": "2d0738094d8e649eaebbab16fd647da1", "Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.nfo": "2d0738094d8e649eaebbab16fd647da1",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2-thumb.jpg": "8b32ee9c037fa669e444a0ac181525a1", "Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2-thumb.jpg": "8b32ee9c037fa669e444a0ac181525a1",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.info.json": "514d2c3eab500f9541910d7573cb495e", "Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.info.json": "d7112915f5d437e38f6b1ec633274fcb",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.mp4": "d3469b4dca7139cb3dbc38712b6796bf", "Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.mp4": "d3469b4dca7139cb3dbc38712b6796bf",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.nfo": "5c258f9e54854ef292ce3c58331da110", "Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.nfo": "5c258f9e54854ef292ce3c58331da110",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "f9ccc0b104551ecd7b737451051118aa", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "51bb8da215aa43a2824126002d4c9cb5",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "abb3ac33366cc3b86d0467c8fb80a323", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "abb3ac33366cc3b86d0467c8fb80a323",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "6ad149bea780198512d73f075722ef82", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "a7d62181e7e45640af423312039f9d0f",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "46190954652c9d9812e061fc0c9e1d92", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "46190954652c9d9812e061fc0c9e1d92",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "d040165f8ebc346c202605b19ed8e46b", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "14e7e02d3b0fec685dcabd585256a7e0",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "30993fa8e00a0e370b4db244f3da8f7d", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "30993fa8e00a0e370b4db244f3da8f7d",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net)-thumb.jpg": "c956192a379b3661595c9920972d4819", "Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net)-thumb.jpg": "c956192a379b3661595c9920972d4819",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).info.json": "331af1c81b1bfa1df62179067a5f06b0", "Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).info.json": "4b97b5e5450bcafaa1b439e05a4559db",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).mp4": "3d9c19835b03355d6fd5d00cd59dbe5b", "Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).mp4": "3d9c19835b03355d6fd5d00cd59dbe5b",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).nfo": "11a0e8754c414875bcd454358683da5f", "Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).nfo": "11a0e8754c414875bcd454358683da5f",
"Season 2011/s2011.e0630 - Project Zombie Fin-thumb.jpg": "00ed383591779ffe98291de60f198fe9", "Season 2011/s2011.e0630 - Project Zombie Fin-thumb.jpg": "00ed383591779ffe98291de60f198fe9",
"Season 2011/s2011.e0630 - Project Zombie Fin.info.json": "07d6b5e38b8e03cbe0f1ca795f266a43", "Season 2011/s2011.e0630 - Project Zombie Fin.info.json": "83bb5f10310a9a8c5f8f002a6017a40b",
"Season 2011/s2011.e0630 - Project Zombie Fin.mp4": "4971cb2d4fa29460361031f3fa8e1ea9", "Season 2011/s2011.e0630 - Project Zombie Fin.mp4": "4971cb2d4fa29460361031f3fa8e1ea9",
"Season 2011/s2011.e0630 - Project Zombie Fin.nfo": "a464b9c8c48a9a5d4776436d8108f8f5", "Season 2011/s2011.e0630 - Project Zombie Fin.nfo": "a464b9c8c48a9a5d4776436d8108f8f5",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC]-thumb.jpg": "1718599d5189c65f7d8cf6acfa5ea851", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC]-thumb.jpg": "1718599d5189c65f7d8cf6acfa5ea851",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].info.json": "e804c82258849767d5f006627e66ac8f", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].info.json": "2a139950a598abb1c6d335e6fb5bbe5f",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].mp4": "55e9b0add08c48c9c66105da0def2426", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].mp4": "55e9b0add08c48c9c66105da0def2426",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].nfo": "3562934ab9a5e802d955eda24ad355de", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].nfo": "3562934ab9a5e802d955eda24ad355de",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6", "Season 2012/s2012.e0123 - Project Zombie Map Trailer-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.info.json": "d81b260f37fbf8499d6ba716f5d1c42a", "Season 2012/s2012.e0123 - Project Zombie Map Trailer.info.json": "efc6100c795e73fd4ae4ccab791b4136",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.mp4": "65e4ce53ed5ec4139995469f99477a50", "Season 2012/s2012.e0123 - Project Zombie Map Trailer.mp4": "65e4ce53ed5ec4139995469f99477a50",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.nfo": "5e810d839be90dab579400a6177f90b3", "Season 2012/s2012.e0123 - Project Zombie Map Trailer.nfo": "5e810d839be90dab579400a6177f90b3",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer-thumb.jpg": "e29d49433175de8a761af35c5307791f", "Season 2013/s2013.e0719 - Project Zombie Rewind Trailer-thumb.jpg": "e29d49433175de8a761af35c5307791f",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.info.json": "4e450b92e57f8c99033b49e3326cdf72", "Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.info.json": "68b2b622896d086ba8237932725d7430",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.mp4": "18620a8257a686beda65e54add4d4cd1", "Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.mp4": "18620a8257a686beda65e54add4d4cd1",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.nfo": "83772bec917bb5d71e1ca0c061c1ec78", "Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.nfo": "83772bec917bb5d71e1ca0c061c1ec78",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b", "Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json": "01a181a123d1b92d016dced5615ca67a", "Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json": "3e174f2abeadfecfdcd40dd18ab6f2e1",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc", "Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82", "Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46", "Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e", "Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json": "2ca573a5eb58e92df951be0a05e8e49c", "Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json": "070fb6004aec97be575887224b93b229",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", "Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a", "Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a",
"fanart.jpg": "129c6639b47299bc48062f0365e670ee", "fanart.jpg": "129c6639b47299bc48062f0365e670ee",
"poster.jpg": "5de28eea5a921a041452ab3ce1041f73", "poster.jpg": "5de28eea5a921a041452ab3ce1041f73",
"tvshow.nfo": "85cef9db54e9afb7af8e4912b5262d3f" "tvshow.nfo": "c1c888ff6691f36328d1fb9d8c43adff"
} }

View file

@ -283,4 +283,5 @@ poster.jpg
tvshow.nfo tvshow.nfo
NFO tags: NFO tags:
tvshow: tvshow:
plot: Plugin and map updates for the server Project Zombie.
title: Project / Zombie title: Project / Zombie