This reverts commit a970fb9d06.
This commit is contained in:
parent
aeca125c2e
commit
427d6e30fd
4 changed files with 26 additions and 137 deletions
|
|
@ -102,18 +102,12 @@ class SharedNfoTagsPlugin(Plugin[SharedNfoTagsOptions], ABC):
|
||||||
|
|
||||||
return nfo_tags
|
return nfo_tags
|
||||||
|
|
||||||
def _create_nfo(
|
def _create_nfo(self, entry: Entry, save_to_entry: bool = True) -> None:
|
||||||
self,
|
|
||||||
entry: Entry,
|
|
||||||
nfo_tags: Optional[Dict[str, List[XmlElement]]] = None,
|
|
||||||
save_to_entry: bool = True,
|
|
||||||
) -> None:
|
|
||||||
# Write the nfo tags to XML with the nfo_root
|
# Write the nfo tags to XML with the nfo_root
|
||||||
nfo_root = self.overrides.apply_formatter(
|
nfo_root = self.overrides.apply_formatter(
|
||||||
formatter=self.plugin_options.nfo_root, entry=entry
|
formatter=self.plugin_options.nfo_root, entry=entry
|
||||||
)
|
)
|
||||||
if nfo_tags is None:
|
nfo_tags = self._get_xml_element_dict(entry=entry)
|
||||||
nfo_tags = self._get_xml_element_dict(entry=entry)
|
|
||||||
|
|
||||||
if self.plugin_options.kodi_safe:
|
if self.plugin_options.kodi_safe:
|
||||||
nfo_root = to_max_3_byte_utf8_string(nfo_root)
|
nfo_root = to_max_3_byte_utf8_string(nfo_root)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Dict
|
|
||||||
from typing import List
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.config.preset_options import Overrides
|
from ytdl_sub.config.preset_options import Overrides
|
||||||
|
|
@ -7,7 +5,6 @@ from ytdl_sub.entries.entry import Entry
|
||||||
from ytdl_sub.plugins.nfo_tags import NfoTagsValidator
|
from ytdl_sub.plugins.nfo_tags import NfoTagsValidator
|
||||||
from ytdl_sub.plugins.nfo_tags import SharedNfoTagsOptions
|
from ytdl_sub.plugins.nfo_tags import SharedNfoTagsOptions
|
||||||
from ytdl_sub.plugins.nfo_tags import SharedNfoTagsPlugin
|
from ytdl_sub.plugins.nfo_tags import SharedNfoTagsPlugin
|
||||||
from ytdl_sub.utils.xml import XmlElement
|
|
||||||
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
|
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
|
||||||
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
|
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
|
||||||
|
|
||||||
|
|
@ -15,8 +12,8 @@ from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadAr
|
||||||
class OutputDirectoryNfoTagsOptions(SharedNfoTagsOptions):
|
class OutputDirectoryNfoTagsOptions(SharedNfoTagsOptions):
|
||||||
"""
|
"""
|
||||||
Adds a single NFO file in the output directory. An NFO file is simply an XML file with a
|
Adds a single NFO file in the output directory. An NFO file is simply an XML file with a
|
||||||
``.nfo`` extension. It builds the tags using each entry's source variables, and merges all the
|
``.nfo`` extension. It uses the last entry's source variables which can change per download
|
||||||
unique values into the final set of tags. Be cautious of which variables you use.
|
invocation. Be cautious of which variables you use.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
|
|
@ -50,29 +47,38 @@ class OutputDirectoryNfoTagsOptions(SharedNfoTagsOptions):
|
||||||
@property
|
@property
|
||||||
def tags(self) -> NfoTagsValidator:
|
def tags(self) -> NfoTagsValidator:
|
||||||
"""
|
"""
|
||||||
Tags within the nfo_root tag. Also supports xml attributes and duplicate keys:
|
Tags within the nfo_root tag. In the usage above, it would look like
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<tvshow>
|
||||||
|
<title>Sweet youtube TV show</title>
|
||||||
|
</tvshow>
|
||||||
|
|
||||||
|
Also supports xml attributes and duplicate keys:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
title: "Sweet youtube TV show"
|
named_season:
|
||||||
namedseason:
|
- tag: "{source_title}"
|
||||||
- tag: "{season_name}"
|
|
||||||
attributes:
|
attributes:
|
||||||
number: "{season_index}"
|
number: "{collection_index}"
|
||||||
|
behavior: "merge"
|
||||||
genre:
|
genre:
|
||||||
|
- tag: "Comedy"
|
||||||
|
behavior: "overwrite"
|
||||||
- "Comedy"
|
- "Comedy"
|
||||||
- "Drama"
|
- "Drama"
|
||||||
|
|
||||||
With merged tags, it could translate to
|
Which translates to
|
||||||
|
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<title>Sweet youtube TV show</title>
|
<title year="2022">Sweet youtube TV show</season>
|
||||||
<genre>Comedy</genre>
|
<genre>Comedy</genre>
|
||||||
<genre>Drama</genre>
|
<genre>Drama</genre>
|
||||||
<namedseason number="1">Some Playlist</namedseason>
|
|
||||||
<namedseason number="2">Another Playlist</namedseason>
|
|
||||||
"""
|
"""
|
||||||
return self._tags
|
return self._tags
|
||||||
|
|
||||||
|
|
@ -87,31 +93,17 @@ class OutputDirectoryNfoTagsPlugin(SharedNfoTagsPlugin):
|
||||||
enhanced_download_archive: EnhancedDownloadArchive,
|
enhanced_download_archive: EnhancedDownloadArchive,
|
||||||
):
|
):
|
||||||
super().__init__(plugin_options, overrides, enhanced_download_archive)
|
super().__init__(plugin_options, overrides, enhanced_download_archive)
|
||||||
self._nfo_tags: Dict[str, List[XmlElement]] = {}
|
|
||||||
self._last_entry: Optional[Entry] = None
|
self._last_entry: Optional[Entry] = None
|
||||||
|
|
||||||
def post_process_entry(self, entry: Entry) -> None:
|
def post_process_entry(self, entry: Entry) -> None:
|
||||||
"""
|
"""
|
||||||
Merges the nfo_tags dict of all entries. Tracks the last entry processed
|
Tracks the last entry processed
|
||||||
"""
|
"""
|
||||||
nfo_tags = self._get_xml_element_dict(entry=entry)
|
|
||||||
for key, xml_elements in nfo_tags.items():
|
|
||||||
# Key not in nfo_tags, add and continue
|
|
||||||
if key not in self._nfo_tags:
|
|
||||||
self._nfo_tags[key] = xml_elements
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Is in nfo_tags, only add new ones
|
|
||||||
for xml_element in xml_elements:
|
|
||||||
if xml_element not in self._nfo_tags[key]:
|
|
||||||
self._nfo_tags[key].append(xml_element)
|
|
||||||
|
|
||||||
self._last_entry = entry
|
self._last_entry = entry
|
||||||
|
|
||||||
def post_process_subscription(self):
|
def post_process_subscription(self):
|
||||||
"""
|
"""
|
||||||
Creates an NFO file in the root of the output directory using merged nfo tags and last entry
|
Creates an NFO file in the root of the output directory using the last entry
|
||||||
for the NFO root
|
|
||||||
"""
|
"""
|
||||||
if self._last_entry:
|
if self._last_entry:
|
||||||
self._create_nfo(entry=self._last_entry, nfo_tags=self._nfo_tags, save_to_entry=False)
|
self._create_nfo(entry=self._last_entry, save_to_entry=False)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import pytest
|
||||||
from e2e.expected_transaction_log import assert_transaction_log_matches
|
from e2e.expected_transaction_log import assert_transaction_log_matches
|
||||||
|
|
||||||
from ytdl_sub.subscriptions.subscription import Subscription
|
from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
|
from ytdl_sub.utils.exceptions import ValidationException
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
@ -60,33 +61,6 @@ def subscription_dict(output_directory):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def merged_output_nfo_preset_dict(output_directory):
|
|
||||||
return {
|
|
||||||
"preset": "yt_music_video_playlist",
|
|
||||||
"youtube": {"playlist_url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
|
|
||||||
# override the output directory with our fixture-generated dir
|
|
||||||
"output_options": {"output_directory": output_directory},
|
|
||||||
# download the worst format so it is fast
|
|
||||||
"ytdl_options": {
|
|
||||||
"format": "worst[ext=mp4]",
|
|
||||||
},
|
|
||||||
"output_directory_nfo_tags": {
|
|
||||||
"nfo_name": "tvshow.nfo",
|
|
||||||
"nfo_root": "tvshow",
|
|
||||||
"tags": {
|
|
||||||
"title": "Test Title",
|
|
||||||
"namedseason": [{"tag": "{title}", "attributes": {"number": "{playlist_index}"}}],
|
|
||||||
"genre": [
|
|
||||||
"Comedy",
|
|
||||||
"Drama",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"overrides": {"artist": "JMC"},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestNfoTagsPlugins:
|
class TestNfoTagsPlugins:
|
||||||
@pytest.mark.parametrize("kodi_safe", [True, False])
|
@pytest.mark.parametrize("kodi_safe", [True, False])
|
||||||
def test_nfo_tags(self, subscription_dict, music_video_config, output_directory, kodi_safe):
|
def test_nfo_tags(self, subscription_dict, music_video_config, output_directory, kodi_safe):
|
||||||
|
|
@ -109,21 +83,3 @@ class TestNfoTagsPlugins:
|
||||||
transaction_log=transaction_log,
|
transaction_log=transaction_log,
|
||||||
transaction_log_summary_file_name=f"plugins/nfo_tags/{transaction_log_file_name}",
|
transaction_log_summary_file_name=f"plugins/nfo_tags/{transaction_log_file_name}",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_merged_output_nfo_tags(
|
|
||||||
self, merged_output_nfo_preset_dict, music_video_config, output_directory
|
|
||||||
):
|
|
||||||
subscription = Subscription.from_dict(
|
|
||||||
config=music_video_config,
|
|
||||||
preset_name="merged_output_nfo_tags",
|
|
||||||
preset_dict=merged_output_nfo_preset_dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Only dry run is needed to see if NFO values are kodi safe
|
|
||||||
transaction_log = subscription.download(dry_run=True)
|
|
||||||
assert_transaction_log_matches(
|
|
||||||
output_directory=output_directory,
|
|
||||||
transaction_log=transaction_log,
|
|
||||||
transaction_log_summary_file_name=f"plugins/nfo_tags/merged_output_nfo_tags.txt",
|
|
||||||
regenerate_transaction_log=True,
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
Files created in '{output_directory}'
|
|
||||||
----------------------------------------
|
|
||||||
.ytdl-sub-merged_output_nfo_tags-download-archive.json
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo
|
|
||||||
NFO tags:
|
|
||||||
musicvideo:
|
|
||||||
album: Music Videos
|
|
||||||
artist: JMC
|
|
||||||
title: Jesse's Minecraft Server [Trailer - Feb.1]
|
|
||||||
year: 2011
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo
|
|
||||||
NFO tags:
|
|
||||||
musicvideo:
|
|
||||||
album: Music Videos
|
|
||||||
artist: JMC
|
|
||||||
title: Jesse's Minecraft Server [Trailer - Feb.27]
|
|
||||||
year: 2011
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4
|
|
||||||
JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo
|
|
||||||
NFO tags:
|
|
||||||
musicvideo:
|
|
||||||
album: Music Videos
|
|
||||||
artist: JMC
|
|
||||||
title: Jesse's Minecraft Server [Trailer - Mar.21]
|
|
||||||
year: 2011
|
|
||||||
tvshow.nfo
|
|
||||||
NFO tags:
|
|
||||||
tvshow:
|
|
||||||
genre:
|
|
||||||
- Comedy
|
|
||||||
- Drama
|
|
||||||
namedseason:
|
|
||||||
-
|
|
||||||
attributes:
|
|
||||||
number: 3
|
|
||||||
tag: Jesse's Minecraft Server [Trailer - Feb.1]
|
|
||||||
-
|
|
||||||
attributes:
|
|
||||||
number: 2
|
|
||||||
tag: Jesse's Minecraft Server [Trailer - Feb.27]
|
|
||||||
-
|
|
||||||
attributes:
|
|
||||||
number: 1
|
|
||||||
tag: Jesse's Minecraft Server [Trailer - Mar.21]
|
|
||||||
title: Test Title
|
|
||||||
Loading…
Reference in a new issue