Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement episode and season search templates #3732

Merged
merged 139 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
34b61ec
Added the episode and season search templates to the tv_shows table.
p0psicles Feb 8, 2018
7138a81
Mako changes for start using Vue for editShow.mako.
p0psicles Feb 27, 2018
c32613d
Small fixes to existing Vue.js code in config.
p0psicles Feb 27, 2018
1e985e5
Moved sceneExceptions table from cache to main.db.
p0psicles Feb 27, 2018
5a73eb3
Fixed tvmaze debug log.
p0psicles Feb 27, 2018
f1b03b9
Fixed old bug where trakt is not using indexer to compare.
p0psicles Feb 27, 2018
27c078f
Fix bug in artwork, passing indexer_id while should pass object.
p0psicles Feb 27, 2018
5cf4eb3
Refactored sceneExceptions, returning now a named tuple in stead of t…
p0psicles Feb 27, 2018
307db2d
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Feb 27, 2018
a4b097f
Refactored get_scene_exceptions_by_name to use the exception_cache, a…
p0psicles Feb 27, 2018
36ea69e
Fix typo
p0psicles Feb 27, 2018
3bc492c
Changed most of the editShow.mako to use vue for form handling.
p0psicles Feb 27, 2018
391095b
Updated theme slim src.
p0psicles Feb 27, 2018
bf56f53
Added apiv2 routes for patching ignored and required words.
p0psicles Mar 1, 2018
cfbc59d
Moved anidb to helper.
p0psicles Mar 2, 2018
2d44548
editShow.mako: Replacing get seriesObj from mako python to use apiv2.
p0psicles Mar 2, 2018
b17638d
Fixed quotes and removed json.dumps.
p0psicles Mar 2, 2018
1a58c62
Fixed editShow loading series data through mounted() function.
p0psicles Mar 2, 2018
1ad51d7
Styled the anidbReleaseGroupUi.mako component.
p0psicles Mar 2, 2018
1b113f5
Fixed the propagation of the list of strings for the requiredWords an…
p0psicles Mar 2, 2018
2b9b337
cleaned up vue and removed python imports
OmgImAlexis Mar 2, 2018
abd4f51
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles May 10, 2018
21963a9
Remove old components.
p0psicles May 10, 2018
2727c08
Add convert method to main.mako, so it can be used in other templates…
p0psicles May 11, 2018
0acb67c
Added new vue component name-pattern.
p0psicles May 11, 2018
fd59fd3
No need to create a new variable here.
p0psicles May 11, 2018
441c0b1
Make use of the namespace for the convert method.
p0psicles May 11, 2018
8fd2590
Remove the fillExamples methods, as i'm in the process of changing th…
p0psicles May 11, 2018
e80d5bc
config_Postprocessing.mako: Started implementing vue for the episode …
p0psicles May 11, 2018
90dbefd
Replaced all the different custom naming types (sports, air by date, …
p0psicles May 23, 2018
4aeeec1
Add axios clients for apiv1 and webRout rest calls.
p0psicles May 27, 2018
a21a195
Move convert method in mako to namespace.
p0psicles May 27, 2018
7c0c0b5
Get exceptions from show.
p0psicles May 27, 2018
c3dc0db
Api changes maps.
p0psicles May 27, 2018
060418c
Introduced a new component for name patterns.
p0psicles May 27, 2018
4fe55f5
Remove token from api client.
p0psicles May 29, 2018
697c5de
Added onChangePattern method, to process name-pattern component updates.
p0psicles May 29, 2018
cee4c06
Added postprocessing items to the apiv2 config.
p0psicles May 29, 2018
45c1d6c
Updated apiv2 config attributes for postprocessing.
p0psicles May 29, 2018
7aa4257
Added MultiEp style select.
p0psicles May 29, 2018
9f9eb2b
Also update animeNamingType (add absolute number) support to naming-p…
p0psicles May 30, 2018
e3bed79
Update muli-ep exaples when changing multi-ep style.
p0psicles May 30, 2018
f9f7d00
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Jul 30, 2018
f1b3170
Fix db migration bugs after conflicts.
p0psicles Jul 30, 2018
9b8bf79
Merge remote-tracking branch 'origin/develop' into feature/templated-…
p0psicles Jan 17, 2020
77c8e9d
Added search_templates.py
p0psicles Jan 17, 2020
26cbb86
Fix duplicate creation of strings
p0psicles Jan 17, 2020
46dccf5
Separated read_from_db from generate method.
p0psicles Jan 17, 2020
5ce1b88
Add search_templates to apiv2 series result
p0psicles Jan 17, 2020
fedef2c
Update table search_templates
p0psicles Feb 8, 2020
9b0a685
Fix regression in name_parser/parser.py
p0psicles Feb 8, 2020
7805190
Move db connection to constructor.
p0psicles Feb 8, 2020
3ffc67e
Add config.templates and config.searchTemplates to apiv2.
p0psicles Feb 8, 2020
688d978
Added @properties for the templates.
p0psicles Feb 8, 2020
376c163
Added first UI's for creating search templates.
p0psicles Feb 8, 2020
388938e
Add property aliases_to_json because of the new structure of exceptions.
p0psicles Feb 18, 2020
0eb6601
Fix aliases in edit-show.vue because of new structure.
p0psicles Feb 18, 2020
f25498f
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Mar 17, 2020
a26c212
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Mar 17, 2020
74d225c
Yarn dev and eslint --fix
p0psicles Mar 17, 2020
cd9adcc
Fix enabling/disabling and saving default search templates.
p0psicles Mar 20, 2020
b47be60
Add flag to templates for specifying season searches.
p0psicles Mar 27, 2020
c8b2bfd
Add new tab to editShow "search templates"
p0psicles Mar 27, 2020
b8655c5
Add new component for adding search templates.
p0psicles Mar 27, 2020
0a450a9
Create new component for managing scene exceptions.
p0psicles Mar 27, 2020
b0314b1
Remove unused import.
p0psicles Mar 28, 2020
c2f1713
Add seasoned scene exceptions.
p0psicles Mar 28, 2020
84df542
Merge remote-tracking branch 'remotes/origin/develop' into feature/se…
p0psicles Mar 28, 2020
9f0bcd2
Fixed a number of small bugs, related to the renaming of seriesName (…
p0psicles Mar 28, 2020
084dbc9
Fix adding/removing scene exceptions.
p0psicles Mar 29, 2020
3191493
Merge remote-tracking branch 'remotes/origin/develop' into feature/se…
p0psicles Mar 29, 2020
c44843f
removeEmpty is not used anymore.
p0psicles Mar 29, 2020
d977bfb
Added newnlines between class.
p0psicles Mar 29, 2020
fbc2e81
Remove getAllSceneExceptions, as this is replaced by aliases.
p0psicles Mar 31, 2020
389ad6f
Removed allSceneExceptions, as this is replaced by aliases.
p0psicles Mar 31, 2020
7aac365
updated fixture with alias examples.
p0psicles Mar 31, 2020
edce48c
Merge remote-tracking branch 'remotes/origin/develop' into feature/se…
p0psicles Mar 31, 2020
f1b3c02
Added newline.
p0psicles Apr 2, 2020
b73f608
Fix stylelint
p0psicles Apr 2, 2020
c68ef83
Merge remote-tracking branch 'remotes/origin/feature/season-aliases' …
p0psicles Apr 2, 2020
2e2eecc
Fix test use TitleException.
p0psicles Apr 3, 2020
9297931
yarn dev
p0psicles Apr 3, 2020
a62a801
Fix test_parse_anime tests.
p0psicles Apr 3, 2020
a37f202
Fix api-description
p0psicles Apr 3, 2020
1c9565b
Fix flake warnings
p0psicles Apr 3, 2020
4f0497e
Utilize the field "custom" to specify if a scene exception is a custo…
p0psicles Apr 3, 2020
509aa3c
Small visual enhancement.
p0psicles Apr 3, 2020
39afa5c
Add custom field for guessit tests.
p0psicles Apr 3, 2020
c56dba8
Fix flake warnings
p0psicles Apr 4, 2020
1fd5e92
Fix typo
p0psicles Apr 4, 2020
33c5121
Flake indentation?
p0psicles Apr 4, 2020
1733d88
Let's try this
p0psicles Apr 4, 2020
18a010a
Show Medusa icon for exceptions that are not custom.
p0psicles Apr 4, 2020
495cb51
Vue lint and css-lint fixes.
p0psicles Apr 4, 2020
102be7d
Flake, we keep trying.
p0psicles Apr 4, 2020
0114353
Try to fix api tests.
p0psicles Apr 4, 2020
046e6d5
hanging indent
p0psicles Apr 4, 2020
7fe997a
Finally fixing this sh$t.
p0psicles Apr 4, 2020
53293c2
Change tooltip message
p0psicles Apr 5, 2020
e8753e4
yarn dev
p0psicles Apr 5, 2020
64d1c53
Merge remote-tracking branch 'remotes/origin/feature/season-aliases' …
p0psicles Apr 5, 2020
049a6b4
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Apr 9, 2020
31bcc74
Add db constraint: Make sure template + season is always unique.
p0psicles Apr 10, 2020
561c080
Rename show_name to title.
p0psicles Apr 10, 2020
eb47e35
Re-generate search templates on modifactions to scene_exceptions.
p0psicles Apr 10, 2020
5b0cfd2
Prevent adding scene_exceptions that already exist.
p0psicles Apr 10, 2020
cab0a75
Add id to search_templates.
p0psicles Apr 10, 2020
0734740
Merge remote-tracking branch 'remotes/origin/develop' into feature/te…
p0psicles Nov 27, 2020
7d3cf99
Fix lint errors
p0psicles Nov 27, 2020
9207b73
hide/show templates tab.
p0psicles Nov 27, 2020
9ef2684
Merge remote-tracking branch 'origin/develop' into feature/templated-…
p0psicles Jan 8, 2022
eaf9314
Fix merge conflicts and linting
p0psicles Jan 9, 2022
3928c19
Fix adding custom search templates.
p0psicles Jan 10, 2022
b89b01c
Add first version of basic searching using the search templates
p0psicles Jan 11, 2022
9efef84
Don't search irrelevant scene seasons
p0psicles Jan 11, 2022
8103ce2
Improve default template creation for season scene exceptions
p0psicles Jan 11, 2022
31c251c
Remove debounce, not needed.
p0psicles Jan 11, 2022
66050f9
Fix debounced error
p0psicles Jan 11, 2022
6a1508b
Place back debounce
p0psicles Jan 11, 2022
e4eea94
Merge remote-tracking branch 'origin/develop' into feature/templated-…
p0psicles Jan 13, 2022
de88ad7
yarn dev
p0psicles Jan 13, 2022
258a001
Remove unique constraint
p0psicles Jan 13, 2022
47585d9
No need to re-recreate all default templates when requesting from api.
p0psicles Jan 13, 2022
5e1a731
Added info for displaying info on show / season exception.
p0psicles Jan 13, 2022
fb3dccc
Only get search_templates when detailed.
p0psicles Jan 13, 2022
306e0d4
Add test-guessit component
p0psicles Jan 22, 2022
6bd8d7b
Fixed show merging errors
p0psicles Jan 22, 2022
6e01837
Asume season 1, when no season number parsed
p0psicles Jan 22, 2022
05cbd28
Add parsing of special episodes by episode title.
p0psicles Jan 25, 2022
7cc6b8b
Change to staticmethod
p0psicles Jan 25, 2022
b7da1fd
Change check to startsWith
p0psicles Jan 25, 2022
8261b76
Rename remove -> remove_custom.
p0psicles Jan 25, 2022
5e8d37f
Merge remote-tracking branch 'origin/develop' into feature/templated-…
p0psicles Jan 25, 2022
73a2448
Add animation to red cross
p0psicles Jan 25, 2022
ba114e2
update snapshot
p0psicles Jan 25, 2022
19a564b
Fix linting issues
p0psicles Jan 25, 2022
dccaf35
Fix flake
p0psicles Jan 25, 2022
f4ce643
this image is not used
p0psicles Jan 25, 2022
fc83d46
Update changelog
p0psicles Jan 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Add support for banner and background images to indexer tvmaze ([10234](https://github.com/pymedusa/Medusa/pull/10234))
- Add option for using ffprobe to validate postprocessed media ([10132](https://github.com/pymedusa/Medusa/pull/10132))
- Add change indexer page to change the current indexer for shows in bulk ([9862](https://github.com/pymedusa/Medusa/pull/9862))
- Add search templates feature. ([3732](https://github.com/pymedusa/Medusa/pull/3732))

#### Improvements
- Add column sorting for the add new show page search results ([10217](https://github.com/pymedusa/Medusa/pull/10217))
Expand Down
34 changes: 34 additions & 0 deletions medusa/databases/main_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,3 +995,37 @@ def execute(self):
self.addColumn('history', 'part_of_batch', 'INTEGER')

self.inc_minor_version()


class AddSearchTemplates(AddHistoryFDHFields):
"""Create a new table search_templates in main.db."""

def test(self):
"""
Test if the version is at least 44.19
"""
return self.connection.version >= (44, 19)

def execute(self):
utils.backup_database(self.connection.path, self.connection.version)

log.info(u'Creating a new table search_templates in the main.db database.')

self.connection.action(
"""CREATE TABLE "search_templates" (
`search_template_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`template` TEXT,
`title` TEXT,
`indexer` INTEGER,
`series_id` INTEGER,
`season` INTEGER,
`enabled` INTEGER DEFAULT 1,
`default` INTEGER DEFAULT 1,
`season_search` INTEGER DEFAULT 0);"""
)

log.info(u'Adding new templates field in the tv_shows table')
if not self.hasColumn('tv_shows', 'templates'):
self.addColumn('tv_shows', 'templates', 'NUMERIC', 0)

self.inc_minor_version()
1 change: 0 additions & 1 deletion medusa/name_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ def build_name_cache(series_obj=None):
"""Build internal name cache.

:param series_obj: Specify series to build name cache for, if None, just do all series
:param force: Force the build name cache. Do not depend on the scene_exception_refresh table.
"""
def _cache_name(cache_series_obj):
"""Build the name cache for a single show."""
Expand Down
51 changes: 46 additions & 5 deletions medusa/name_parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ def _parse_series(result):
new_absolute_numbers = []

ex_season = scene_exceptions.get_season_from_name(result.series, result.series_name) or result.season_number
if ex_season is None:
ex_season = 1
log.info(
p0psicles marked this conversation as resolved.
Show resolved Hide resolved
"For the show {name} we could not parse a season number. We did match the title, so we'll asume season 1",
{'name': result.series.name}
)

for episode_number in result.episode_numbers:
season = ex_season
Expand All @@ -300,6 +306,33 @@ def _parse_series(result):

return new_episode_numbers, new_season_numbers, new_absolute_numbers

@staticmethod
def _parse_special(result):
new_episode_numbers = []
new_season_numbers = []

episode_title = result.guess.get('episode_title')
if not episode_title:
log.info(
'{name}: This episode is marked as a special. We could not find an episode title. And we need that to map it to an episode in the library.',
{'name': result.series.name}
)
return new_episode_numbers, new_season_numbers

# Sanitize the episode title.
episode_title = episode_title.lower()
if episode_title.startswith('special'):
episode_title = episode_title.split('special')[-1].strip()

all_episodes = result.series.get_all_episodes(season=0)
for special_episode in all_episodes:
if special_episode.name.lower() == episode_title:
new_season_numbers.append(0)
new_episode_numbers.append(special_episode.episode)
return new_episode_numbers, new_season_numbers

return [], []

def _parse_string(self, name):
guess = guessit.guessit(name, dict(show_type=self.show_type))

Expand All @@ -318,18 +351,22 @@ def _parse_string(self, name):
new_season_numbers = []
new_absolute_numbers = []

# Try to map special episodes without an episode number using the episode title.
if result.is_episode_special and not result.episode_numbers:
new_episode_numbers, new_season_numbers = self._parse_special(result)

# if we have an air-by-date show and the result is air-by-date,
# then get the real season/episode numbers
if result.series.air_by_date and result.is_air_by_date:
elif result.series.air_by_date and result.is_air_by_date:
new_episode_numbers, new_season_numbers = self._parse_air_by_date(result)

elif result.series.is_anime or result.is_anime:
new_episode_numbers, new_season_numbers, new_absolute_numbers = self._parse_anime(result)

elif result.season_number is not None:
else:
new_episode_numbers, new_season_numbers, new_absolute_numbers = self._parse_series(result)

else:
if not new_season_numbers and not new_episode_numbers:
raise InvalidNameException('The result that was found ({result_name}) is not yet supported by Medusa '
'and will be skipped. Sorry.'.format(result_name=result.original_name))

Expand Down Expand Up @@ -468,14 +505,15 @@ def to_parse_result(self, name, guess):
episode_numbers=helpers.ensure_list(guess.get('episode')),
ab_episode_numbers=helpers.ensure_list(guess.get('absolute_episode')),
air_date=guess.get('date'), release_group=guess.get('release_group'),
proper_tags=helpers.ensure_list(guess.get('proper_tag')), version=guess.get('version', -1))
proper_tags=helpers.ensure_list(guess.get('proper_tag')), version=guess.get('version', -1),
episode_details=helpers.ensure_list(guess.get('episode_details')))


class ParseResult(object):
"""Represent the release information for a given name."""

def __init__(self, guess, series_name=None, season_number=None, episode_numbers=None, ab_episode_numbers=None,
air_date=None, release_group=None, proper_tags=None, version=None, original_name=None):
air_date=None, release_group=None, proper_tags=None, version=None, original_name=None, episode_details=None):
"""Initialize the class.

:param guess:
Expand All @@ -498,6 +536,8 @@ def __init__(self, guess, series_name=None, season_number=None, episode_numbers=
:type version: int
:param original_name:
:type original_name: str
:param episode_details:
:type episode_details: list of str
"""
self.original_name = original_name
self.series_name = series_name
Expand All @@ -512,6 +552,7 @@ def __init__(self, guess, series_name=None, season_number=None, episode_numbers=
self.proper_tags = proper_tags
self.guess = guess
self.total_time = None
self.episode_details = episode_details

def __eq__(self, other):
"""Equal implementation.
Expand Down
5 changes: 3 additions & 2 deletions medusa/naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ def check_valid_naming(pattern=None, multi=None, anime_type=None):
if anime_type is None:
anime_type = app.NAMING_ANIME

logger.log(u'Checking whether the pattern ' + pattern + ' is valid for a single episode', logger.DEBUG)
logger.log(f'Checking whether the pattern {pattern} is valid for a single episode', logger.DEBUG)
valid = validate_name(pattern, None, anime_type)

if multi is not None:
logger.log(u'Checking whether the pattern ' + pattern + ' is valid for a multi episode', logger.DEBUG)
logger.log(f'Checking whether the pattern {pattern} is valid for a multi episode', logger.DEBUG)
valid = valid and validate_name(pattern, multi, anime_type)

return valid
Expand Down Expand Up @@ -169,6 +169,7 @@ def validate_name(pattern, multi=None, anime_type=None, file_only=False, abd=Fal
if parse_result.season_number != ep.season:
logger.log(u"Season number incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
return False
# If the template is a season search string, we don't need to check for episode.
if parse_result.episode_numbers != [x.episode for x in [ep] + ep.related_episodes]:
logger.log(u"Episode numbering incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
return False
Expand Down
27 changes: 27 additions & 0 deletions medusa/providers/generic_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,21 @@ def _get_episode_search_strings(self, episode, add_string=''):
'Episode': []
}

# If show.use_templates is enabled, where using those instead of creating them here.
if episode.series.use_templates:
for template in episode.series.search_templates.templates:

# Only limit to episode search templates. And filter out disabled search templates.
if template.season_search or not template.enabled:
continue

# Make sure we only use a season search template when searched for that season.
if episode.scene_season is not None and template.season != -1 and episode.scene_season != template.season:
continue

search_string['Episode'].append(episode.formatted_search_string(template.template, title=template.title))
return [search_string]

all_possible_show_names = episode.series.get_all_possible_names()
if episode.scene_season is not None:
all_possible_show_names = all_possible_show_names.union(
Expand Down Expand Up @@ -697,6 +712,18 @@ def _get_season_search_strings(self, episode):
'Season': []
}

# If show.use_templates is enabled, where using those instead of creating them here.
if episode.series.use_templates:
for template in episode.series.search_templates.templates:
if not template.season_search or not template.enabled:
continue

if episode.scene_season and template.season != -1 and episode.scene_season != template.season:
continue

search_string['Season'].append(episode.formatted_search_string(template.template, title=template.title))
return [search_string]

for show_name in episode.series.get_all_possible_names(season=episode.scene_season):
episode_string = show_name + self.search_separator

Expand Down
4 changes: 4 additions & 0 deletions medusa/queues/show_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,10 @@ def message_step(new_step):
message_step('add scene numbering')
self.show.add_scene_numbering()

# Load search templates
message_step('generate search templates')
self.show.init_search_templates()

if self.show_dir:
# If a show dir was passed, this was added as an existing show.
# For new shows we should have any files on disk.
Expand Down
6 changes: 4 additions & 2 deletions medusa/scene_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def get_season_from_name(series_obj, exception_name):

def get_all_scene_exceptions(series_obj):
"""
Get all scene exceptions for a show ID.
Get all scene exceptions for a show object using indexer and series_id.

:param series_obj: series object.
:return: dict of exceptions (e.g. exceptions_cache[season][exception_name])
Expand Down Expand Up @@ -239,6 +239,8 @@ def update_scene_exceptions(series_obj, scene_exceptions):
[series_obj.indexer, series_obj.series_id, exception['title'], exception['season'], exception['custom']]
)

refresh_exceptions_cache(series_obj)


def retrieve_exceptions(force=False, exception_type=None):
"""
Expand Down Expand Up @@ -283,7 +285,7 @@ def retrieve_exceptions(force=False, exception_type=None):
for scene_exception, season in iteritems(exception_dict):
if scene_exception not in existing_exceptions:
queries.append([
'INSERT OR IGNORE INTO scene_exceptions '
'INSERT OR IGNORE INTO scene_exceptions'
'(indexer, series_id, title, season, custom) '
'VALUES (?,?,?,?,?)',
[indexer, series_id, scene_exception, season, False]
Expand Down
2 changes: 1 addition & 1 deletion medusa/scene_numbering.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def get_indexer_numbering(series_obj, scene_episode, scene_season=None):
"""
# Try to get a mapping from scene_numbering.
season, episode = get_custom_numbering_from_scene(series_obj, scene_episode, scene_season)
if all((season, episode)):
if all((season is not None, episode)):
return season, episode

if series_obj.is_scene:
Expand Down
Loading