Skip to content

Commit

Permalink
Use guid for matching
Browse files Browse the repository at this point in the history
  • Loading branch information
reconman committed Mar 9, 2024
1 parent 5e2e9cc commit 8dbbaae
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 11 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,38 @@ https://anilist.co/anime/99263/Tate-no-Yuusha-no-Nariagari
- You can remove any existing entries from the example file as they are purely instructional
- Upon startup it will check if the file is a valid YAML file. The most likely reason it's not is because you didn't put quotes around an anime title with special characters (e.g. ":") in it.

#### Duplicate Plex Titles

For Plex shows and movies with the same title, use the optional `guid` field in the mapping.

For example, both of these Rurouni Kenshin shows are shown as "Rurouni Kenshin" in Plex:

```yaml
- title: "Rurouni Kenshin"
guid: plex://show/5d9c07ece264b7001fc38094
seasons:
- season: 1
anilist-id: 45
- season: 2
anilist-id: 45
- season: 3
anilist-id: 45
- title: "Rurouni Kenshin (2023)"
guid: plex://show/6330a57e9705fab2b34f656d
seasons:
- season: 1
anilist-id: 142877
```

When the `guid` field is set, the `title` and `synonyms` fields are ignored. However, you should still use different titles for human readability.

To find the guid, perform the following steps:
1. Open this URL in an **incognito browser window**: https://app.plex.tv/desktop/#!/search?pivot=top&query=
2. Search for your series or movie and click on the correct entry
3. Copy everything after `metadata%2F`, so for https://app.plex.tv/desktop/#!/provider/tv.plex.provider.discover/details?key=%2Flibrary%2Fmetadata%2F6330a57e9705fab2b34f656d copy `6330a57e9705fab2b34f656d`
4. If it's a TV show, add `plex://show/` before that identifier, for movies use `plex://movie/`

#### Community mappings

There are some mappings provided by the Github community at https://github.com/RickDB/PlexAniSync-Custom-Mappings/. You can use them by specifying `remote-urls` like in the example mapping file.
Expand Down
20 changes: 12 additions & 8 deletions plexanisync/anilist.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def match_to_plex(self, anilist_series: List[AnilistSeries], plex_series_watched
plex_title = plex_series.title
plex_title_sort = plex_series.title_sort
plex_title_original = plex_series.title_original
plex_guid = plex_series.guid
plex_year = plex_series.year
plex_seasons = plex_series.seasons
plex_show_rating = plex_series.rating
Expand All @@ -65,7 +66,7 @@ def match_to_plex(self, anilist_series: List[AnilistSeries], plex_series_watched
for plex_season in plex_seasons:

season_mappings: List[AnilistCustomMapping] = self.__retrieve_season_mappings(
plex_title, plex_season.season_number
plex_title, plex_guid, plex_season.season_number
)
# split season -> handle it in "any remaining seasons" section
if season_mappings and len(season_mappings) == 1:
Expand Down Expand Up @@ -171,7 +172,7 @@ def match_to_plex(self, anilist_series: List[AnilistSeries], plex_series_watched
]
potential_titles = list(potential_titles_cleaned)

season_mappings = self.__retrieve_season_mappings(plex_title, season_number)
season_mappings = self.__retrieve_season_mappings(plex_title, plex_guid, season_number)
# Custom mapping check - check user list
if season_mappings:
watchcounts = self.__map_watchcount_to_seasons(plex_title, season_mappings, plex_season.watched_episodes)
Expand Down Expand Up @@ -262,7 +263,7 @@ def match_to_plex(self, anilist_series: List[AnilistSeries], plex_series_watched
media_id_search = None
# ignore the Plex year since Plex does not have years for seasons
skip_year_check = True
season_mappings = self.__retrieve_season_mappings(plex_title, season_number)
season_mappings = self.__retrieve_season_mappings(plex_title, plex_guid, season_number)
if season_mappings:
watchcounts = self.__map_watchcount_to_seasons(plex_title, season_mappings, plex_season.watched_episodes)

Expand Down Expand Up @@ -651,14 +652,17 @@ def __update_episode_incremental(
for current_episodes_watched in range(anilist_episodes_watched + 1, watched_episode_count + 1):
self.graphql.update_series(series.anilist_id, current_episodes_watched, new_status, plex_rating)

def __retrieve_season_mappings(self, title: str, season: int) -> List[AnilistCustomMapping]:
def __retrieve_season_mappings(self, title: str, guid: str, season: int) -> List[AnilistCustomMapping]:
season_mappings: List[AnilistCustomMapping] = []

if self.custom_mappings and title.lower() in self.custom_mappings:
season_mappings = self.custom_mappings[title.lower()]
# filter mappings by season
season_mappings = [e for e in season_mappings if e.season == season]
if self.custom_mappings:
if guid in self.custom_mappings:
season_mappings = self.custom_mappings[guid]
elif title.lower() in self.custom_mappings:
season_mappings = self.custom_mappings[title.lower()]

# filter mappings by season
season_mappings = [e for e in season_mappings if e.season == season]
return season_mappings

def __map_watchcount_to_seasons(
Expand Down
22 changes: 19 additions & 3 deletions plexanisync/custom_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def construct_scalar(self, node):

def read_custom_mappings() -> Dict[str, List[AnilistCustomMapping]]:
custom_mappings: Dict[str, List[AnilistCustomMapping]] = {}
title_guid_mappings: Dict[str, str] = {}
if not os.path.isfile(MAPPING_FILE):
logger.info(f"Custom map file not found: {MAPPING_FILE}")
return custom_mappings
Expand Down Expand Up @@ -112,9 +113,9 @@ def read_custom_mappings() -> Dict[str, List[AnilistCustomMapping]]:
logger.error(f'Custom Mappings {mapping_location} validation failed!')
__handle_yaml_error(file_mappings_remote, e)

__add_mappings(custom_mappings, mapping_location, file_mappings_remote)
__add_mappings(custom_mappings, title_guid_mappings, mapping_location, file_mappings_remote)

__add_mappings(custom_mappings, MAPPING_FILE, file_mappings_local)
__add_mappings(custom_mappings, title_guid_mappings, MAPPING_FILE, file_mappings_local)

return custom_mappings

Expand All @@ -137,12 +138,15 @@ def __handle_yaml_error(file_mappings_local, error):
sys.exit(1)


def __add_mappings(custom_mappings, mapping_location, file_mappings):
def __add_mappings(custom_mappings: Dict[str, List[AnilistCustomMapping]],

Check failure on line 141 in plexanisync/custom_mappings.py

View workflow job for this annotation

GitHub Actions / lint-and-test

R0914: Too many local variables (16/15) (too-many-locals)

Check failure on line 141 in plexanisync/custom_mappings.py

View workflow job for this annotation

GitHub Actions / lint-and-test

R0914: Too many local variables (16/15) (too-many-locals)
title_guid_mappings: Dict[str, str],
mapping_location, file_mappings):
# handles missing and empty 'entries'
entries = file_mappings.get('entries', []) or []
for file_entry in entries:
series_title = str(file_entry['title'])
synonyms: List[str] = file_entry.get('synonyms', [])
guid: str = str(file_entry.get('guid', ""))
series_mappings: List[AnilistCustomMapping] = []
for file_season in file_entry['seasons']:
season = file_season['season']
Expand All @@ -155,12 +159,24 @@ def __add_mappings(custom_mappings, mapping_location, file_mappings):
series_mappings.append(AnilistCustomMapping(season, anilist_id, start))
if synonyms:
logger.debug(f"{series_title} has synonyms: {synonyms}")

if guid:
# store the mapping under the guid if one is set
custom_mappings[guid] = series_mappings

for title in [series_title] + synonyms:
title_lower = title.lower()
if title_lower in custom_mappings:
logger.info(f"Overwriting previous mapping for {title}")
if title_lower in title_guid_mappings and not guid:
# if the current mapping doesn't have a guid, remove the guid mapping with the same title
# this ensures that users can override community mappings without specifying the guid field
custom_mappings.pop(title_guid_mappings[title_lower], None)
custom_mappings[title_lower] = series_mappings

if guid:
title_guid_mappings[title_lower] = guid


# Get the custom mappings from the web.
def __get_custom_mapping_remote(file_mappings) -> List[Tuple[str, str]]:
Expand Down
3 changes: 3 additions & 0 deletions plexanisync/plexmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class PlexWatchedSeries:
title: str
title_sort: str
title_original: str
guid: str
year: int
seasons: List[PlexSeason]
anilist_id: Optional[int]
Expand Down Expand Up @@ -220,6 +221,7 @@ def get_watched_shows(self, shows: List[Show]) -> Optional[List[PlexWatchedSerie
show.title.strip(),
show.titleSort.strip(),
show.originalTitle.strip(),
show.guid,
year,
seasons,
anilist_id,
Expand Down Expand Up @@ -259,6 +261,7 @@ def get_watched_shows(self, shows: List[Show]) -> Optional[List[PlexWatchedSerie
show.title.strip(),
show.titleSort.strip(),
show.originalTitle.strip(),
show.guid,
year,
[PlexSeason(1, rating, 1, 1, 1)],
anilist_id,
Expand Down

0 comments on commit 8dbbaae

Please sign in to comment.