mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-22 20:43:07 +00:00
[14] remove unneeded special overlay attribute
This commit is contained in:
parent
8bd4333779
commit
ce6ffbd4f2
4 changed files with 119 additions and 94 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
1.17.2-develop13
|
1.17.2-develop14
|
||||||
|
|
|
@ -169,38 +169,38 @@ overlays:
|
||||||
back_radius: 30
|
back_radius: 30
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Special Text Overlays
|
#### Special Text Variables
|
||||||
|
|
||||||
You can use the item's metadata to determine the text. You set the `name` to `text(special_text)` and then use the `special_text` attribute to format the text.
|
You can use the item's metadata to determine the text by adding Special Text Variables to you text Overlay.
|
||||||
|
|
||||||
There are multiple Special Text Variables that can be used when formatting the text. The variables are defined like so `<<name>>` and some can have modifiers like so `<<name$>>` where `$` is the modifier. The available options are:
|
There are multiple Special Text Variables that can be used when formatting the text. The variables are defined like so `<<name>>` and some can have modifiers like so `<<name$>>` where `$` is the modifier. The available options are:
|
||||||
|
|
||||||
| Special Text Variables & Mods | Movies | Shows | Seasons | Episodes |
|
| Special Text Variables & Mods | Movies | Shows | Seasons | Episodes |
|
||||||
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------:|:--------:|:--------:|:--------:|
|
|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------:|:--------:|:--------:|:--------:|
|
||||||
| `<<audience_rating>>`: audience rating (`8.7`, `9.0`)<br>`<<audience_rating%>>`: audience rating out of 100 (`87`, `90`)<br>`<<audience_rating#>>`: audience rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ❌ | ✅ |
|
| `<<audience_rating>>`: audience rating (`8.7`, `9.0`)<br>`<<audience_rating%>>`: audience rating out of 100 (`87`, `90`)<br>`<<audience_rating#>>`: audience rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ❌ | ✅ |
|
||||||
| `<<critic_rating>>`: critic rating (`8.7`, `9.0`)<br>`<<critic_rating%>>`: critic rating out of 100 (`87`, `90`)<br>`<<critic_rating#>>`: critic rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ❌ | ✅ |
|
| `<<critic_rating>>`: critic rating (`8.7`, `9.0`)<br>`<<critic_rating%>>`: critic rating out of 100 (`87`, `90`)<br>`<<critic_rating#>>`: critic rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ❌ | ✅ |
|
||||||
| `<<user_rating>>`: user rating (`8.7`, `9.0`)<br>`<<user_rating%>>`: user rating out of 100 (`87`, `90`)<br>`<<user_rating#>>`: user rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ✅ | ✅ |
|
| `<<user_rating>>`: user rating (`8.7`, `9.0`)<br>`<<user_rating%>>`: user rating out of 100 (`87`, `90`)<br>`<<user_rating#>>`: user rating removing `.0` as needed (`8.7`, `9`) | ✅ | ✅ | ✅ | ✅ |
|
||||||
| `<<title>>`: Title of the Item | ✅ | ✅ | ✅ | ✅ |
|
| `<<title>>`: Title of the Item | ✅ | ✅ | ✅ | ✅ |
|
||||||
| `<<show_title>>`: Title of the Item's Show | ❌ | ❌ | ✅ | ✅ |
|
| `<<show_title>>`: Title of the Item's Show | ❌ | ❌ | ✅ | ✅ |
|
||||||
| `<<season_title>>`: Title of the Item's Season | ❌ | ❌ | ❌ | ✅ |
|
| `<<season_title>>`: Title of the Item's Season | ❌ | ❌ | ❌ | ✅ |
|
||||||
| `<<original_title>>`: Original Title of the Item | ✅ | ✅ | ❌ | ❌ |
|
| `<<original_title>>`: Original Title of the Item | ✅ | ✅ | ❌ | ❌ |
|
||||||
| `<<content_rating>>`: Content Rating of the Item | ✅ | ✅ | ❌ | ✅ |
|
| `<<content_rating>>`: Content Rating of the Item | ✅ | ✅ | ❌ | ✅ |
|
||||||
| `<<episode_count>>`: Number of Episodes (`1`)<br>`<<episode_countW>`: Number of Episodes As Words (`One`)<br>`<<episode_count0>`: Number of Episodes With 10s Padding (`01`)<br>`<<episode_count00>`: Number of Episodes With 100s Padding (`001`) | ❌ | ✅ | ✅ | ❌ |
|
| `<<episode_count>>`: Number of Episodes (`1`)<br>`<<episode_countW>>`: Number of Episodes As Words (`One`)<br>`<<episode_count0>>`: Number of Episodes With 10s Padding (`01`)<br>`<<episode_count00>>`: Number of Episodes With 100s Padding (`001`) | ❌ | ✅ | ✅ | ❌ |
|
||||||
| `<<season_number>>`: Season Number (`1`)<br>`<<season_numberW>`: Season Number As Words (`One`)<br>`<<season_number0>`: Season Number With 10s Padding (`01`)<br>`<<season_number00>`: Season Number With 100s Padding (`001`) | ❌ | ❌ | ✅ | ✅ |
|
| `<<season_number>>`: Season Number (`1`)<br>`<<season_numberW>>`: Season Number As Words (`One`)<br>`<<season_number0>>`: Season Number With 10s Padding (`01`)<br>`<<season_number00>>`: Season Number With 100s Padding (`001`) | ❌ | ❌ | ✅ | ✅ |
|
||||||
| `<<episode_number>>`: Episode Number (`1`)<br>`<<episode_numberW>`: Episode Number As Words (`One`)<br>`<<episode_number0>`: Episode Number With 10s Padding (`01`)<br>`<<episode_number00>`: Episode Number With 100s Padding (`001`) | ❌ | ❌ | ❌ | ✅ |
|
| `<<episode_number>>`: Episode Number (`1`)<br>`<<episode_numberW>>`: Episode Number As Words (`One`)<br>`<<episode_number0>>`: Episode Number With 10s Padding (`01`)<br>`<<episode_number00>>`: Episode Number With 100s Padding (`001`) | ❌ | ❌ | ❌ | ✅ |
|
||||||
| `<<runtime>>`: Runtime of the Item in minutes`<<runtimeH>>`: Hours in runtime of the Item<br>`<<runtimeM>>`: Minutes remaining in the hour in the runtime of the Item | ✅ | ❌ | ❌ | ✅ |
|
| `<<runtime>>`: Complete Runtime of the Item in minutes (`150`)<br>`<<runtimeH>>`: Hours in runtime of the Item (`2`)<br>`<<runtimeM>>`: Minutes remaining in the hour in the runtime of the Item (`30`) | ✅ | ❌ | ❌ | ✅ |
|
||||||
| `<<originally_available>>`: Original Available Date of the Item`<<originally_available[FORMAT]>>`: Original Available Date of the Item in the given format. [Format Options](https://strftime.org/) | ✅ | ✅ | ❌ | ✅ |
|
| `<<originally_available>>`: Original Available Date of the Item<br>`<<originally_available[FORMAT]>>`: Original Available Date of the Item in the given format. [Format Options](https://strftime.org/) | ✅ | ✅ | ❌ | ✅ |
|
||||||
|
|
||||||
Note: You can use the `mass_audience_rating_update` or `mass_critic_rating_update` [Library Operation](../config/operations) to update your plex ratings to various services like `tmdb`, `imdb`, `mdb`, `metacritic`, `letterboxd` and many more.
|
Note: You can use the `mass_audience_rating_update` or `mass_critic_rating_update` [Library Operation](../config/operations) to update your plex ratings to various services like `tmdb`, `imdb`, `mdb`, `metacritic`, `letterboxd` and many more.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
I want to have the audience_rating display with a `%` out of 100 vs 0.0-10.0.
|
I want to have the audience_rating display with a `%` out of 100 vs 0.0-10.0.
|
||||||
```yaml
|
```yaml
|
||||||
overlays:
|
overlays:
|
||||||
audience_rating:
|
audience_rating:
|
||||||
overlay:
|
overlay:
|
||||||
name: text(special_text)
|
name: text(<<audience_rating%>>%)
|
||||||
special_text: <<audience_rating%>>%
|
|
||||||
horizontal_offset: 225
|
horizontal_offset: 225
|
||||||
horizontal_align: center
|
horizontal_align: center
|
||||||
vertical_offset: 15
|
vertical_offset: 15
|
||||||
|
@ -214,6 +214,39 @@ overlays:
|
||||||
back_height: 105
|
back_height: 105
|
||||||
```
|
```
|
||||||
|
|
||||||
|
I want to add `S##E##` to all my episode images.
|
||||||
|
```yaml
|
||||||
|
overlays:
|
||||||
|
text_content_rating:
|
||||||
|
builder_level: episode
|
||||||
|
overlay:
|
||||||
|
name: text(S<<season_number0>>E<<episode_number0>>)
|
||||||
|
horizontal_align: center
|
||||||
|
vertical_offset: 15
|
||||||
|
vertical_align: top
|
||||||
|
font: fonts/Inter-Medium.ttf
|
||||||
|
font_size: 63
|
||||||
|
font_color: "#FFFFFF"
|
||||||
|
back_color: "#00000099"
|
||||||
|
back_radius: 30
|
||||||
|
back_width: 300
|
||||||
|
back_height: 105
|
||||||
|
plex_all: true
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Common Special Text Uses
|
||||||
|
These are some commonly-used examples of Special Text overlays:
|
||||||
|
|
||||||
|
| Special Text | Example Output |
|
||||||
|
|:------------------------------------------------------------------|--------------------|
|
||||||
|
| `name: text(S<<season_number0>>E<<episode_number0>>)` | S01E01 |
|
||||||
|
| `name: text(Season <<season_number>> Episode <<episode_number>>)` | Season 1 Episode 1 |
|
||||||
|
| `name: text(Season <<season_number>>)` | Season 1 |
|
||||||
|
| `name: text(Episode <<episode_number>>)` | Episode 1 |
|
||||||
|
| `name: text(Runtime: <<runtime>>m)` | Runtime: 90m |
|
||||||
|
| `name: text(Runtime: <<runtimeH>>h <<runtimeM>>m)` | Runtime: 1h 30m |
|
||||||
|
|
||||||
|
|
||||||
#### Text Addon Images
|
#### Text Addon Images
|
||||||
|
|
||||||
You can add an image to accompany the text by specifying the image location using `file`, `url`, `git`, or `repo`.
|
You can add an image to accompany the text by specifying the image location using `file`, `url`, `git`, or `repo`.
|
||||||
|
|
|
@ -284,20 +284,14 @@ class Overlay:
|
||||||
if text in old_special_text2:
|
if text in old_special_text2:
|
||||||
text_mod = text[-1] if text[-1] in ["0", "%", "#"] else None
|
text_mod = text[-1] if text[-1] in ["0", "%", "#"] else None
|
||||||
text = text if text_mod is None else text[:-1]
|
text = text if text_mod is None else text[:-1]
|
||||||
self.special_text = f"<<{text}#>>" if text_mod == "#" else f"<<{text}%>>{'' if text_mod == '0' else '%'}"
|
self.name = f"text(<<{text}#>>)" if text_mod == "#" else f"text(<<{text}%>>{'' if text_mod == '0' else '%'})"
|
||||||
self.name = "text(special_text)"
|
if "<<originally_available[" in text:
|
||||||
elif self.name == "text(special_text)":
|
match = re.search("<<originally_available\\[(.+)]>>", text)
|
||||||
if "special_text" not in self.data or not self.data["special_text"]:
|
if match:
|
||||||
raise Failed("Overlay Error: text(special_text) requires the special_text attribute")
|
try:
|
||||||
if "<<originally_available[" in self.data["special_text"]:
|
datetime.now().strftime(match.group(1))
|
||||||
match = re.search("<<originally_available\\[(.+)]>>", self.data["special_text"])
|
except ValueError:
|
||||||
if match:
|
raise Failed("Overlay Error: originally_available date format not valid")
|
||||||
try:
|
|
||||||
datetime.now().strftime(match.group(1))
|
|
||||||
except ValueError:
|
|
||||||
raise Failed("Overlay Error: originally_available date format not valid")
|
|
||||||
self.special_text = self.data["special_text"]
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
box = self.image.size if self.image else None
|
box = self.image.size if self.image else None
|
||||||
self.portrait, self.portrait_box = self.get_backdrop(portrait_dim, box=box, text=self.name[5:-1])
|
self.portrait, self.portrait_box = self.get_backdrop(portrait_dim, box=box, text=self.name[5:-1])
|
||||||
|
@ -433,7 +427,7 @@ class Overlay:
|
||||||
output += f"{self.back_box[0]}{self.back_box[1]}{self.back_align}"
|
output += f"{self.back_box[0]}{self.back_box[1]}{self.back_align}"
|
||||||
if self.addon_position is not None:
|
if self.addon_position is not None:
|
||||||
output += f"{self.addon_position}{self.addon_offset}"
|
output += f"{self.addon_position}{self.addon_offset}"
|
||||||
for value in [self.font_color, self.back_color, self.back_radius, self.back_padding, self.back_line_color, self.back_line_width, self.special_text]:
|
for value in [self.font_color, self.back_color, self.back_radius, self.back_padding, self.back_line_color, self.back_line_width]:
|
||||||
if value is not None:
|
if value is not None:
|
||||||
output += f"{value}"
|
output += f"{value}"
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -120,9 +120,9 @@ class Overlays:
|
||||||
if self.config.Cache:
|
if self.config.Cache:
|
||||||
for over_name in over_names:
|
for over_name in over_names:
|
||||||
current_overlay = properties[over_name]
|
current_overlay = properties[over_name]
|
||||||
if current_overlay.name == "text(special_text)":
|
if current_overlay.name.startswith("text"):
|
||||||
for cache_key, cache_value in self.config.Cache.query_overlay_special_text(item.ratingKey).items():
|
for cache_key, cache_value in self.config.Cache.query_overlay_special_text(item.ratingKey).items():
|
||||||
actual = plex.attribute_translation[cache_key] if cache_key in plex.attribute_translation[cache_key] else cache_key
|
actual = plex.attribute_translation[cache_key] if cache_key in plex.attribute_translation else cache_key
|
||||||
if cache_value is None or not hasattr(item, actual) or getattr(item, actual) is None:
|
if cache_value is None or not hasattr(item, actual) or getattr(item, actual) is None:
|
||||||
continue
|
continue
|
||||||
if cache_key in overlay.float_vars:
|
if cache_key in overlay.float_vars:
|
||||||
|
@ -203,65 +203,63 @@ class Overlays:
|
||||||
|
|
||||||
def get_text(text_overlay):
|
def get_text(text_overlay):
|
||||||
full_text = text_overlay.name[5:-1]
|
full_text = text_overlay.name[5:-1]
|
||||||
if full_text == "special_text":
|
for format_var in overlay.vars_by_type[text_overlay.level]:
|
||||||
full_text = text_overlay.special_text
|
if f"<<{format_var}" in full_text and format_var == "originally_available[":
|
||||||
for format_var in overlay.vars_by_type[text_overlay.level]:
|
mod = re.search("<<originally_available\\[(.+)]>>", full_text).group(1)
|
||||||
if f"<<{format_var}" in full_text and format_var == "originally_available[":
|
format_var = "originally_available"
|
||||||
mod = re.search("<<originally_available\\[(.+)]>>", full_text).group(1)
|
elif f"<<{format_var}>>" in full_text and format_var.endswith("00"):
|
||||||
format_var = "originally_available"
|
mod = "00"
|
||||||
elif f"<<{format_var}>>" in full_text and format_var.endswith("00"):
|
format_var = format_var[:-2]
|
||||||
mod = "00"
|
elif f"<<{format_var}>>" in full_text and format_var.endswith(("%", "#", "H", "M", "0")):
|
||||||
format_var = format_var[:-2]
|
mod = format_var[-1]
|
||||||
elif f"<<{format_var}>>" in full_text and format_var.endswith(("%", "#", "H", "M", "0")):
|
format_var = format_var[:-1]
|
||||||
mod = format_var[-1]
|
elif f"<<{format_var}>>" in full_text:
|
||||||
format_var = format_var[:-1]
|
mod = ""
|
||||||
elif f"<<{format_var}>>" in full_text:
|
else:
|
||||||
mod = ""
|
continue
|
||||||
|
if format_var == "show_title":
|
||||||
|
actual_attr = "parentTitle" if text_overlay.level == "season" else "grandparentTitle"
|
||||||
|
elif format_var in plex.attribute_translation:
|
||||||
|
actual_attr = plex.attribute_translation[format_var]
|
||||||
|
else:
|
||||||
|
actual_attr = format_var
|
||||||
|
if not hasattr(item, actual_attr) or getattr(item, actual_attr) is None:
|
||||||
|
logger.warning(f"Overlay Warning: No {full_text} found")
|
||||||
|
continue
|
||||||
|
actual_value = getattr(item, actual_attr)
|
||||||
|
if self.config.Cache:
|
||||||
|
cache_store = actual_value.strftime("%Y-%m-%d") if format_var in overlay.date_vars else actual_value
|
||||||
|
self.config.Cache.update_overlay_special_text(item.ratingKey, format_var, cache_store)
|
||||||
|
sub_value = None
|
||||||
|
if format_var == "originally_available":
|
||||||
|
if mod:
|
||||||
|
sub_value = "<<originally_available\\[(.+)]>>"
|
||||||
|
final_value = actual_value.strftime(mod)
|
||||||
else:
|
else:
|
||||||
continue
|
final_value = actual_value.strftime("%Y-%m-%d")
|
||||||
if format_var == "show_title":
|
elif format_var == "runtime":
|
||||||
actual_attr = "parentTitle" if text_overlay.level == "season" else "grandparentTitle"
|
if mod == "H":
|
||||||
elif format_var in plex.attribute_translation:
|
final_value = int((actual_value / 60000) // 60)
|
||||||
actual_attr = plex.attribute_translation[format_var]
|
elif mod == "M":
|
||||||
|
final_value = int((actual_value / 60000) % 60)
|
||||||
else:
|
else:
|
||||||
actual_attr = format_var
|
final_value = int(actual_value / 60000)
|
||||||
if not hasattr(item, actual_attr) or getattr(item, actual_attr) is None:
|
elif mod == "%":
|
||||||
logger.warning(f"Overlay Warning: No {full_text} found")
|
final_value = int(actual_value * 10)
|
||||||
continue
|
elif mod == "#":
|
||||||
actual_value = getattr(item, actual_attr)
|
final_value = str(actual_value)[:-2] if str(actual_value).endswith(".0") else actual_value
|
||||||
if self.config.Cache:
|
elif mod == "W":
|
||||||
cache_store = actual_value.strftime("%Y-%m-%d") if format_var in overlay.date_vars else actual_value
|
final_value = num2words(int(actual_value))
|
||||||
self.config.Cache.update_overlay_special_text(item.ratingKey, format_var, cache_store)
|
elif mod == "0":
|
||||||
sub_value = None
|
final_value = f"{int(actual_value):02}"
|
||||||
if format_var == "originally_available":
|
elif mod == "00":
|
||||||
if mod:
|
final_value = f"{int(actual_value):03}"
|
||||||
sub_value = "<<originally_available\\[(.+)]>>"
|
else:
|
||||||
final_value = actual_value.strftime(mod)
|
final_value = actual_value
|
||||||
else:
|
if sub_value:
|
||||||
final_value = actual_value.strftime("%Y-%m-%d")
|
full_text = re.sub(sub_value, str(final_value), full_text)
|
||||||
elif format_var == "runtime":
|
else:
|
||||||
if mod == "H":
|
full_text = full_text.replace(f"<<{format_var}{mod}>>", str(final_value))
|
||||||
final_value = (actual_value / 60000) // 60
|
|
||||||
elif mod == "M":
|
|
||||||
final_value = (actual_value / 60000) % 60
|
|
||||||
else:
|
|
||||||
final_value = actual_value / 60000
|
|
||||||
elif mod == "%":
|
|
||||||
final_value = int(actual_value * 10)
|
|
||||||
elif mod == "#":
|
|
||||||
final_value = str(actual_value)[:-2] if str(actual_value).endswith(".0") else actual_value
|
|
||||||
elif mod == "W":
|
|
||||||
final_value = num2words(int(actual_value))
|
|
||||||
elif mod == "0":
|
|
||||||
final_value = f"{int(actual_value):02}"
|
|
||||||
elif mod == "00":
|
|
||||||
final_value = f"{int(actual_value):03}"
|
|
||||||
else:
|
|
||||||
final_value = actual_value
|
|
||||||
if sub_value:
|
|
||||||
full_text = re.sub(sub_value, str(final_value), full_text)
|
|
||||||
else:
|
|
||||||
full_text = full_text.replace(f"<<{format_var}{mod}>>", str(final_value))
|
|
||||||
return str(full_text)
|
return str(full_text)
|
||||||
|
|
||||||
for over_name in applied_names:
|
for over_name in applied_names:
|
||||||
|
|
Loading…
Reference in a new issue