[3] Added the `mass_added_at_update` operation

pull/2038/head
meisnate12 8 months ago
parent 2aac1cd1ae
commit 188063cb19

@ -4,6 +4,7 @@
# New Features
Checks requirement versions to print a message if one needs to be updated
Added the `mass_added_at_update` operation to mass set the Added At field of Movies and Shows.
# Updates
Changed the `overlay_artwork_filetype` Setting to accept `webp_lossy` and `webp_lossless` while the old attribute `webp` will be treated as `webp_lossy`.

@ -1 +1 @@
2.0.1-develop2
2.0.1-develop3

@ -302,6 +302,45 @@ You can create individual blocks of operations by using a list under `operations
- 1900-01-01
```
###### Mass Added At Update
??? blank "`mass_added_at_update` - Updates the added at date of every item in the library.<a class="headerlink" href="#mass-added-at-update" title="Permanent link"></a>"
<div id="mass-added-at-update" />Updates every item's added at date in the library to the chosen site's date.
<hr style="margin: 0px;">
**Attribute:** `mass_added_at_update`
**Accepted Values:** Source or List of sources to use in that order
<table class="clearTable">
<tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr>
<tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr>
<tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr>
<tr><td>`mdb`</td><td>Use MDBList Release Date</td></tr>
<tr><td>`mdb_digital`</td><td>Use MDBList Digital Release Date</td></tr>
<tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr>
<tr><td>`mal`</td><td>Use MyAnimeList Release Date</td></tr>
<tr><td>`lock`</td><td>Lock Added At Field</td></tr>
<tr><td>`unlock`</td><td>Unlock Added At Field</td></tr>
<tr><td>`remove`</td><td>Remove Added At and Lock Field</td></tr>
<tr><td>`reset`</td><td>Remove Added At and Unlock Field</td></tr>
<tr><td colspan="2">Any String in the Format: YYYY-MM-DD for Added At (<code>2022-05-28</code>)</td></tr>
</table>
???+ example "Example"
```yaml
libraries:
TV Shows:
operations:
mass_added_at_update:
- mdb_digital
- mdb
- 1900-01-01
```
###### Mass Rating Update
??? blank "`mass_***_rating_update` - Updates the audience/critic/user rating of every item in the library.<a class="headerlink" href="#mass-star-rating-update" title="Permanent link"></a>"

@ -1429,6 +1429,10 @@
"type": "string",
"enum": ["tmdb","tvdb","omdb","mdb","anidb","mal","lock","unlock","remove","reset"]
},
"mass_added_at_update": {
"type": "string",
"enum": ["tmdb","tvdb","omdb","mdb","anidb","mal","lock","unlock","remove","reset"]
},
"mass_audience_rating_update": {
"anyOf": [
{

@ -135,8 +135,8 @@ library_operations = {
"mass_audience_rating_update": mass_rating_options, "mass_episode_audience_rating_update": mass_episode_rating_options,
"mass_critic_rating_update": mass_rating_options, "mass_episode_critic_rating_update": mass_episode_rating_options,
"mass_user_rating_update": mass_rating_options, "mass_episode_user_rating_update": mass_episode_rating_options,
"mass_original_title_update": mass_original_title_options, "mass_originally_available_update": mass_available_options,
"mass_imdb_parental_labels": imdb_label_options,
"mass_original_title_update": mass_original_title_options, "mass_imdb_parental_labels": imdb_label_options,
"mass_originally_available_update": mass_available_options, "mass_added_at_update": mass_available_options,
"mass_collection_mode": "mass_collection_mode", "mass_poster_update": "dict", "mass_background_update": "dict",
"metadata_backup": "dict", "delete_collections": "dict", "genre_mapper": "dict", "content_rating_mapper": "dict",
}
@ -917,7 +917,7 @@ class ConfigFile:
final_list.append(str(list_attr))
elif op == "mass_genre_update":
final_list.append(list_attr if isinstance(list_attr, list) else [list_attr])
elif op == "mass_originally_available_update":
elif op in ["mass_originally_available_update", "mass_added_at_update"]:
final_list.append(util.validate_date(list_attr))
elif op.endswith("rating_update"):
final_list.append(util.check_int(list_attr, datatype="float", minimum=0, maximum=10, throw=True))

@ -97,6 +97,7 @@ class Library(ABC):
self.mass_content_rating_update = params["mass_content_rating_update"]
self.mass_original_title_update = params["mass_original_title_update"]
self.mass_originally_available_update = params["mass_originally_available_update"]
self.mass_added_at_update = params["mass_added_at_update"]
self.mass_imdb_parental_labels = params["mass_imdb_parental_labels"]
self.mass_poster_update = params["mass_poster_update"]
self.mass_background_update = params["mass_background_update"]
@ -124,7 +125,7 @@ class Library(ABC):
self.items_library_operation = True if self.assets_for_all or self.mass_genre_update or self.remove_title_parentheses \
or self.mass_audience_rating_update or self.mass_critic_rating_update or self.mass_user_rating_update \
or self.mass_episode_audience_rating_update or self.mass_episode_critic_rating_update or self.mass_episode_user_rating_update \
or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_original_title_update\
or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_added_at_update or self.mass_original_title_update\
or self.mass_imdb_parental_labels or self.genre_mapper or self.content_rating_mapper or self.mass_studio_update\
or self.radarr_add_all_existing or self.sonarr_add_all_existing or self.mass_poster_update or self.mass_background_update else False
self.library_operation = True if self.items_library_operation or self.delete_collections or self.mass_collection_mode \

@ -1,5 +1,5 @@
import os, re
from datetime import datetime
from datetime import datetime, timedelta, timezone
from modules import plex, util, anidb
from modules.util import Failed, LimitReached, YAML
from plexapi.exceptions import NotFound
@ -10,14 +10,15 @@ logger = util.logger
meta_operations = [
"mass_audience_rating_update", "mass_user_rating_update", "mass_critic_rating_update",
"mass_episode_audience_rating_update", "mass_episode_user_rating_update", "mass_episode_critic_rating_update",
"mass_genre_update", "mass_content_rating_update", "mass_originally_available_update", "mass_original_title_update",
"mass_poster_update", "mass_background_update", "mass_studio_update"
"mass_genre_update", "mass_content_rating_update", "mass_originally_available_update", "mass_added_at_update",
"mass_original_title_update", "mass_poster_update", "mass_background_update", "mass_studio_update"
]
name_display = {
"audienceRating": "Audience Rating",
"rating": "Critic Rating",
"userRating": "User Rating",
"originallyAvailableAt": "Originally Available Date",
"addedAt": "Added At Date",
"contentRating": "Content Rating"
}
@ -45,6 +46,7 @@ class Operations:
logger.debug(f"Mass Content Rating Update: {self.library.mass_content_rating_update}")
logger.debug(f"Mass Original Title Update: {self.library.mass_original_title_update}")
logger.debug(f"Mass Originally Available Update: {self.library.mass_originally_available_update}")
logger.debug(f"Mass Added At Update: {self.library.mass_added_at_update}")
logger.debug(f"Mass IMDb Parental Labels: {self.library.mass_imdb_parental_labels}")
logger.debug(f"Mass Poster Update: {self.library.mass_poster_update}")
logger.debug(f"Mass Background Update: {self.library.mass_background_update}")
@ -88,7 +90,7 @@ class Operations:
genre_edits = {"add": {}, "remove": {}}
content_edits = {}
studio_edits = {}
available_edits = {}
date_edits = {"originallyAvailableAt": {}, "addedAt": {}}
remove_edits = {}
reset_edits = {}
lock_edits = {}
@ -664,65 +666,69 @@ class Operations:
except Failed:
continue
if self.library.mass_originally_available_update:
current_available = item.originallyAvailableAt
if current_available:
current_available = current_available.strftime("%Y-%m-%d")
for option in self.library.mass_originally_available_update:
if option in ["lock", "remove"]:
if option == "remove" and current_available:
if "originallyAvailableAt" not in remove_edits:
remove_edits["originallyAvailableAt"] = []
remove_edits["originallyAvailableAt"].append(item.ratingKey)
item_edits += "\nRemove Originally Available Date (Batched)"
elif "originallyAvailableAt" not in locked_fields:
if "originallyAvailableAt" not in lock_edits:
lock_edits["originallyAvailableAt"] = []
lock_edits["originallyAvailableAt"].append(item.ratingKey)
item_edits += "\nLock Originally Available Date (Batched)"
break
elif option in ["unlock", "reset"]:
if option == "reset" and current_available:
if "originallyAvailableAt" not in reset_edits:
reset_edits["originallyAvailableAt"] = []
reset_edits["originallyAvailableAt"].append(item.ratingKey)
item_edits += "\nReset Originally Available Date (Batched)"
elif "originallyAvailableAt" in locked_fields:
if "originallyAvailableAt" not in unlock_edits:
unlock_edits["originallyAvailableAt"] = []
unlock_edits["originallyAvailableAt"].append(item.ratingKey)
item_edits += "\nUnlock Originally Available Date (Batched)"
break
else:
try:
if option == "tmdb":
new_available = tmdb_obj().release_date if self.library.is_movie else tmdb_obj().first_air_date # noqa
elif option == "omdb":
new_available = omdb_obj().released # noqa
elif option == "tvdb":
new_available = tvdb_obj().release_date # noqa
elif option == "mdb":
new_available = mdb_obj().released # noqa
elif option == "mdb_digital":
new_available = mdb_obj().released_digital # noqa
elif option == "anidb":
new_available = anidb_obj().released # noqa
elif option == "mal":
new_available = mal_obj().aired # noqa
else:
new_available = option
if not new_available:
logger.info(f"No {option} Originally Available Date Found")
raise Failed
new_available = new_available.strftime("%Y-%m-%d")
if current_available != new_available:
if new_available not in available_edits:
available_edits[new_available] = []
available_edits[new_available].append(item.ratingKey)
item_edits += f"\nUpdate Originally Available Date (Batched) | {new_available}"
for attribute, item_attr in [
(self.library.mass_originally_available_update, "originallyAvailableAt"),
(self.library.mass_added_at_update, "addedAt")
]:
if attribute:
current = getattr(item, item_attr)
if current:
current = current.strftime("%Y-%m-%d")
for option in attribute:
if option in ["lock", "remove"]:
if option == "remove" and current:
if item_attr not in remove_edits:
remove_edits[item_attr] = []
remove_edits[item_attr].append(item.ratingKey)
item_edits += f"\nRemove {name_display[item_attr]} (Batched)"
elif item_attr not in locked_fields:
if item_attr not in lock_edits:
lock_edits[item_attr] = []
lock_edits[item_attr].append(item.ratingKey)
item_edits += f"\nLock {name_display[item_attr]} (Batched)"
break
except Failed:
continue
elif option in ["unlock", "reset"]:
if option == "reset" and current:
if item_attr not in reset_edits:
reset_edits[item_attr] = []
reset_edits[item_attr].append(item.ratingKey)
item_edits += f"\nReset {name_display[item_attr]} (Batched)"
elif item_attr in locked_fields:
if item_attr not in unlock_edits:
unlock_edits[item_attr] = []
unlock_edits[item_attr].append(item.ratingKey)
item_edits += f"\nUnlock {name_display[item_attr]} (Batched)"
break
else:
try:
if option == "tmdb":
new_date = tmdb_obj().release_date if self.library.is_movie else tmdb_obj().first_air_date # noqa
elif option == "omdb":
new_date = omdb_obj().released # noqa
elif option == "tvdb":
new_date = tvdb_obj().release_date # noqa
elif option == "mdb":
new_date = mdb_obj().released # noqa
elif option == "mdb_digital":
new_date = mdb_obj().released_digital # noqa
elif option == "anidb":
new_date = anidb_obj().released # noqa
elif option == "mal":
new_date = mal_obj().aired # noqa
else:
new_date = option
if not new_date:
logger.info(f"No {option} {name_display[item_attr]} Found")
raise Failed
new_date = new_date.strftime("%Y-%m-%d")
if current != new_date:
if new_date not in date_edits[item_attr]:
date_edits[item_attr][new_date] = []
date_edits[item_attr][new_date].append(item.ratingKey)
item_edits += f"\nUpdate {name_display[item_attr]} (Batched) | {new_date}"
break
except Failed:
continue
if len(item_edits) > 0:
logger.info(f"Item Edits{item_edits}")
@ -920,11 +926,27 @@ class Operations:
self.library.Plex.editStudio(new_studio)
self.library.Plex.saveMultiEdits()
_size = len(available_edits.items())
for i, (new_available, rating_keys) in enumerate(sorted(available_edits.items()), 1):
logger.info(get_batch_info(i, _size, "originallyAvailableAt", len(rating_keys), display_value=new_available))
_size = len(date_edits["originallyAvailableAt"].items())
for i, (new_date, rating_keys) in enumerate(sorted(date_edits["originallyAvailableAt"].items()), 1):
logger.info(get_batch_info(i, _size, "originallyAvailableAt", len(rating_keys), display_value=new_date))
self.library.Plex.batchMultiEdits(self.library.load_list_from_cache(rating_keys))
self.library.Plex.editOriginallyAvailable(new_available)
self.library.Plex.editOriginallyAvailable(new_date)
self.library.Plex.saveMultiEdits()
epoch = datetime(1970, 1, 1)
_size = len(date_edits["addedAt"].items())
for i, (new_date, rating_keys) in enumerate(sorted(date_edits["addedAt"].items()), 1):
logger.info(get_batch_info(i, _size, "addedAt", len(rating_keys), display_value=new_date))
self.library.Plex.batchMultiEdits(self.library.load_list_from_cache(rating_keys))
new_date = datetime.strptime(new_date, "%Y-%m-%d")
logger.trace(new_date)
try:
ts = int(round(new_date.timestamp()))
except (TypeError, OSError):
offset = int(datetime(2000, 1, 1, tzinfo=timezone.utc).timestamp() - datetime(2000, 1, 1).timestamp())
ts = int((new_date - epoch).total_seconds()) - offset
logger.trace(epoch + timedelta(seconds=ts))
self.library.Plex.editAddedAt(ts)
self.library.Plex.saveMultiEdits()
_size = len(remove_edits.items())

Loading…
Cancel
Save