Skip to content

Commit

Permalink
Release v1.14.3
Browse files Browse the repository at this point in the history
Create Comic Book card, fix Emby/Jellyfin evaluations, other changes and fixes
  • Loading branch information
CollinHeist authored Aug 20, 2023
2 parents 42374dc + 2847f6b commit dff94d8
Show file tree
Hide file tree
Showing 26 changed files with 1,006 additions and 169 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ __pycache__/
# PEP 582
__pypackages__/

config/
yaml/
yml/
source/
logs/
fonts/
modules/.objects/
*._*
*.yml
*.yaml
*.prof
.DS_Store
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ For invocation and configuration details, read [here](https://github.com/CollinH
> If you have trouble getting the Maker working, or have a problem, [create an issue on GitHub](https://github.com/CollinHeist/TitleCardMaker/issues/new), or [join the Discord](https://discord.gg/bJ3bHtw8wH) for help.
## Examples
Below are some examples of each style of title card that can be created automatically by the TitleCardMaker:
Below are examples of almost all the types of title card that can be created automatically by TitleCardMaker:

### Built-in Card Types
<img alt="Anime" src="https://user-images.githubusercontent.com/17693271/185820454-4e3dca1c-c0df-4fa0-a7a7-81e070aa9e69.jpg" height="150"/> <img alt="Cutout" src="https://user-images.githubusercontent.com/17693271/212500535-e88daff6-ecc0-4cc8-8627-82069114c7e0.jpg" height="150"/> <img alt="Divider" src="https://user-images.githubusercontent.com/17693271/232378485-a9a737dc-9faf-47c2-b639-7df3d3ffb194.jpg" height="150"> <img alt="Fade" src="https://user-images.githubusercontent.com/17693271/214648223-b4f68553-e982-4efa-a16b-9662018b5d40.jpg" height="150"/> <img alt="Frame" src="https://user-images.githubusercontent.com/17693271/202352614-155a176a-fdb0-4476-9f11-6a3a20533a54.jpg" height="150"/> <img alt="Landscape" src="https://user-images.githubusercontent.com/17693271/202352137-b411da21-65ce-4bed-991b-90428c71ec34.jpg" height="150"/> <img alt="Logo" src="https://user-images.githubusercontent.com/17693271/172227163-0ee4990a-b0a8-4dbd-91b3-3f57dfe6e732.jpg" height="150"/> <img alt="Olivier" src="https://user-images.githubusercontent.com/17693271/212500009-067f14ff-4f48-4f75-bacd-7311a9aba716.jpg" height="150"/> <img alt="Poster" src="https://user-images.githubusercontent.com/17693271/180627387-f72bb58e-e001-4608-b4be-82a26263c628.jpg" height="150"/> <img alt="Roman" src="https://user-images.githubusercontent.com/17693271/203910966-4dde1466-6c7e-4422-923b-1f9222ad49e9.jpg" height="150"/> <img alt="Standard" src="https://user-images.githubusercontent.com/17693271/212500240-ae946f2c-a5c8-4881-85f2-83ccb45bf46e.jpg" height="150"/> <img alt="Star Wars" src="https://user-images.githubusercontent.com/17693271/170836059-136fa6eb-40ef-4cd7-9aca-8ad8e0537239.jpg" height="150"> <img alt="tinted Frame" src="https://user-images.githubusercontent.com/17693271/233257029-8b17ce2e-01ea-4ae3-bc73-54e152be4d31.jpg" height="150"> <img alt="Tinted Glass" src="https://user-images.githubusercontent.com/17693271/213939482-6018b2be-28c5-42dd-988d-d7b9733fe0e8.jpg" height="150">
<img alt="Anime" src="https://user-images.githubusercontent.com/17693271/185820454-4e3dca1c-c0df-4fa0-a7a7-81e070aa9e69.jpg" height="150"/> <img alt="comic book" src="https://github.com/CollinHeist/TitleCardMaker/assets/17693271/c5f34e46-ec3b-44a9-a563-b9a24db8cd1a" height="150"/> <img alt="Cutout" src="https://user-images.githubusercontent.com/17693271/212500535-e88daff6-ecc0-4cc8-8627-82069114c7e0.jpg" height="150"/> <img alt="Divider" src="https://user-images.githubusercontent.com/17693271/232378485-a9a737dc-9faf-47c2-b639-7df3d3ffb194.jpg" height="150"> <img alt="Fade" src="https://user-images.githubusercontent.com/17693271/214648223-b4f68553-e982-4efa-a16b-9662018b5d40.jpg" height="150"/> <img alt="Frame" src="https://user-images.githubusercontent.com/17693271/202352614-155a176a-fdb0-4476-9f11-6a3a20533a54.jpg" height="150"/> <img alt="Landscape" src="https://user-images.githubusercontent.com/17693271/202352137-b411da21-65ce-4bed-991b-90428c71ec34.jpg" height="150"/> <img alt="Logo" src="https://user-images.githubusercontent.com/17693271/172227163-0ee4990a-b0a8-4dbd-91b3-3f57dfe6e732.jpg" height="150"/> <img alt="Olivier" src="https://user-images.githubusercontent.com/17693271/212500009-067f14ff-4f48-4f75-bacd-7311a9aba716.jpg" height="150"/> <img alt="Poster" src="https://user-images.githubusercontent.com/17693271/180627387-f72bb58e-e001-4608-b4be-82a26263c628.jpg" height="150"/> <img alt="Roman" src="https://user-images.githubusercontent.com/17693271/203910966-4dde1466-6c7e-4422-923b-1f9222ad49e9.jpg" height="150"/> <img alt="Standard" src="https://user-images.githubusercontent.com/17693271/212500240-ae946f2c-a5c8-4881-85f2-83ccb45bf46e.jpg" height="150"/> <img alt="Star Wars" src="https://user-images.githubusercontent.com/17693271/170836059-136fa6eb-40ef-4cd7-9aca-8ad8e0537239.jpg" height="150"> <img alt="tinted Frame" src="https://user-images.githubusercontent.com/17693271/233257029-8b17ce2e-01ea-4ae3-bc73-54e152be4d31.jpg" height="150"> <img alt="Tinted Glass" src="https://user-images.githubusercontent.com/17693271/213939482-6018b2be-28c5-42dd-988d-d7b9733fe0e8.jpg" height="150"> <img alt="White Border" height="150" src="https://github.com/CollinHeist/TitleCardMaker/assets/17693271/14f25d6a-4be7-4078-97c2-7730ed070508"/>

> The above cards are, in order, the [anime](https://github.com/CollinHeist/TitleCardMaker/wiki/AnimeTitleCard), [cutout](https://github.com/CollinHeist/TitleCardMaker/wiki/CutoutTitleCard), [divider](https://github.com/CollinHeist/TitleCardMaker/wiki/DividerTitleCard), [fade](https://github.com/CollinHeist/TitleCardMaker/wiki/FadeTitleCard), [frame](https://github.com/CollinHeist/TitleCardMaker/wiki/FrameTitleCard), [landscape](https://github.com/CollinHeist/TitleCardMaker/wiki/LandscapeTitleCard), [logo](https://github.com/CollinHeist/TitleCardMaker/wiki/LogoTitleCard), [olivier](https://github.com/CollinHeist/TitleCardMaker/wiki/OlivierTitleCard), [poster](https://github.com/CollinHeist/TitleCardMaker/wiki/PosterTitleCard), [roman](https://github.com/CollinHeist/TitleCardMaker/wiki/RomanNumeralTitleCard), [standard](https://github.com/CollinHeist/TitleCardMaker/wiki/StandardTitleCard), [star wars](https://github.com/CollinHeist/TitleCardMaker/wiki/StarWarsTitleCard), [tinted frame](https://github.com/CollinHeist/TitleCardMaker/wiki/TintedFrameTitleCard), and the [tinted glass](https://github.com/CollinHeist/TitleCardMaker/wiki/TintedGlassTitleCard) title cards - the [textless](https://github.com/CollinHeist/TitleCardMaker/wiki/TitleCard) card is not shown.
> The above cards are, in order, the [anime](https://github.com/CollinHeist/TitleCardMaker/wiki/AnimeTitleCard), [comic book](https://github.com/CollinHeist/TitleCardMaker/wiki/ComicBookTitleCard), [cutout](https://github.com/CollinHeist/TitleCardMaker/wiki/CutoutTitleCard), [divider](https://github.com/CollinHeist/TitleCardMaker/wiki/DividerTitleCard), [fade](https://github.com/CollinHeist/TitleCardMaker/wiki/FadeTitleCard), [frame](https://github.com/CollinHeist/TitleCardMaker/wiki/FrameTitleCard), [landscape](https://github.com/CollinHeist/TitleCardMaker/wiki/LandscapeTitleCard), [logo](https://github.com/CollinHeist/TitleCardMaker/wiki/LogoTitleCard), [olivier](https://github.com/CollinHeist/TitleCardMaker/wiki/OlivierTitleCard), [poster](https://github.com/CollinHeist/TitleCardMaker/wiki/PosterTitleCard), [roman](https://github.com/CollinHeist/TitleCardMaker/wiki/RomanNumeralTitleCard), [standard](https://github.com/CollinHeist/TitleCardMaker/wiki/StandardTitleCard), [star wars](https://github.com/CollinHeist/TitleCardMaker/wiki/StarWarsTitleCard), [tinted frame](https://github.com/CollinHeist/TitleCardMaker/wiki/TintedFrameTitleCard), [tinted glass](https://github.com/CollinHeist/TitleCardMaker/wiki/TintedGlassTitleCard), and the [white border](https://github.com/CollinHeist/TitleCardMaker/wiki/WhiteBorderTitleCard) title cards - the [textless](https://github.com/CollinHeist/TitleCardMaker/wiki/TitleCard) card is not shown.

<details><summary><h3>User-Created Card Types</h3></summary>

Expand All @@ -72,3 +72,9 @@ If you'd like to contribute - whether that's a suggested feature, a bug fix, or

## Support
This has taken a pretty substantial amount of effort, so if you find this project useful you can support me on [BuyMeACoffee](https://www.buymeacoffee.com/CollinHeist), or become a [GitHub sponsor](https://github.com/sponsors/CollinHeist) - I would really appreciate it!

A _huge_ thank you to my current and past sponsors.

<p align="center">
<img src="https://raw.githubusercontent.com/CollinHeist/static/main/sponsorkit/sponsors.svg/sponsors.svg"/>
</p>
12 changes: 7 additions & 5 deletions modules/BaseCardType.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from abc import abstractmethod
from typing import Any, Optional, Union
from typing import Optional, Union

from titlecase import titlecase

from modules.Debug import log
from modules.ImageMaker import ImageMaker


ImageMagickCommands = list[str]


class BaseCardType(ImageMaker):
"""
This class describes an abstract card type. A BaseCardType is a
Expand Down Expand Up @@ -135,9 +136,10 @@ def __init__(self,
def __repr__(self) -> str:
"""Returns an unambiguous string representation of the object."""

attributes = ', '.join(f'{attr}={getattr(self, attr)!r}'
for attr in self.__slots__
if not attr.startswith('__'))
attributes = ', '.join(
f'{attr}={getattr(self, attr)!r}' for attr in self.__slots__
if not attr.startswith('__')
)

return f'<{self.__class__.__name__} {attributes}>'

Expand Down
49 changes: 31 additions & 18 deletions modules/Font.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ class Font(YamlReader):

"""Valid YAML attributes to customize a font"""
VALID_ATTRIBUTES = (
'validate', 'color', 'size', 'file', 'case', 'replacements',
'vertical_shift', 'interline_spacing', 'kerning', 'stroke_width',
'validate', 'color', 'size', 'file', 'case', 'case_name',
'replacements', 'vertical_shift', 'interline_spacing',
'interword_spacing' 'kerning', 'stroke_width',
)

"""Compiled regex to identify percentage values for scalars"""
Expand All @@ -29,14 +30,16 @@ class Font(YamlReader):
__slots__ = (
'__card_class', '__series_info', '__validator', '__validate', 'color',
'size', 'file', 'replacements', 'delete_missing', 'case_name', 'case',
'vertical_shift', 'interline_spacing', 'kerning', 'stroke_width',
'vertical_shift', 'interline_spacing', 'interword_spacing', 'kerning',
'stroke_width',
)


def __init__(self,
yaml: dict,
card_class: BaseCardType,
series_info: SeriesInfo) -> None:
series_info: SeriesInfo,
) -> None:
"""
Construct a new instance of a Font.
Expand Down Expand Up @@ -75,15 +78,18 @@ def custom_hash(self) -> str:

font_file_name = Path(self.file).name

return (f'{self.color}|{self.size}|{font_file_name}|{self.replacements}'
f'|{self.case_name}|{self.vertical_shift}'
f'|{self.interline_spacing}|{self.kerning}|{self.stroke_width}')
return (
f'{self.color}|{self.size}|{font_file_name}|{self.replacements}'
f'|{self.case_name}|{self.vertical_shift}|{self.interline_spacing}'
f'|{self.interword_spacing}|{self.kerning}|{self.stroke_width}'
)


def __error(self,
attribute: str,
value: str,
description: Optional[str] = None) -> None:
description: Optional[str] = None,
) -> None:
"""
Print an error message for the given attribute of the given
value. Also sets the valid attribute of this object to False.
Expand Down Expand Up @@ -166,6 +172,13 @@ def __parse_attributes(self) -> None:
else:
self.__error('interline_spacing', value, 'must be integer')

# Interword spacing
if (value := self.get('interword_spacing', type_=int)) is not None:
if isinstance(value, int):
self.interword_spacing = value
else:
self.__error('interword_spacing', value, 'must be integer')

# Kerning
if (value := self.get('kerning', type_=str)) is not None:
if bool(self._PERCENT_REGEX.match(value)):
Expand All @@ -188,34 +201,34 @@ def reset(self) -> None:
self.__validate = global_objects.pp.validate_fonts

# Default itle card characteristics and font values
self.color = self.__card_class.TITLE_COLOR
self.size = 1.0
self.file = self.__card_class.TITLE_FONT
self.replacements = self.__card_class.FONT_REPLACEMENTS
self.delete_missing = True
self.case_name = self.__card_class.DEFAULT_FONT_CASE
self.case = self.__card_class.CASE_FUNCTIONS[self.case_name]
self.vertical_shift = 0
self.interline_spacing = 0
self.color = self.__card_class.TITLE_COLOR
self.delete_missing = True
self.file = self.__card_class.TITLE_FONT
self.kerning = 1.0
self.interline_spacing = 0
self.interword_spacing = 0
self.size = 1.0
self.replacements = self.__card_class.FONT_REPLACEMENTS
self.stroke_width = 1.0
self.vertical_shift = 0


def get_attributes(self) -> dict[str, Any]:
"""
Return a dictionary of attributes for this font to be unpacked.
Returns:
Dictionary of attributes whose keys are 'title_color',
'font_size', 'font', 'vertical_shift', 'interline_spacing',
'kerning', and 'stroke_width'.
Dictionary of attributes.
"""

return {
'font_color': self.color,
'font': self.file,
'font_file': self.file,
'font_interline_spacing': self.interline_spacing,
'font_interword_spacing': self.interword_spacing,
'font_kerning': self.kerning,
'font_size': self.size,
'font_stroke_width': self.stroke_width,
Expand Down
9 changes: 6 additions & 3 deletions modules/Profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ def custom_hash(self) -> str:

def get_valid_profiles(self,
card_class: 'CardType',
all_variations: bool) -> list[dict[str, str]]:
all_variations: bool,
) -> list[dict[str, str]]:
"""
Gets the valid applicable profiles for this profile. For example,
for a profile with only generic attributes, it's invalid to
Expand Down Expand Up @@ -154,7 +155,8 @@ def convert_profile(self, seasons: str, font: str) -> None:

def convert_extras(self,
card_type: 'BaseCardType',
extras: dict[str, Any]) -> None:
extras: dict[str, Any],
) -> None:
"""
Convert the given extras according to this profile's rules.
Expand Down Expand Up @@ -343,7 +345,8 @@ def __remove_episode_text_format(self, title_text: str) -> str:

def convert_title(self,
title_text: str,
manually_specified: bool = False) -> str:
manually_specified: bool = False,
) -> str:
"""
Convert the given title text through this profile's settings.
This is any combination of text substitutions, case functions,
Expand Down
11 changes: 8 additions & 3 deletions modules/Show.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,8 @@ def __apply_styles(self, select_only: Optional[Episode] = None) -> bool:


def select_source_images(self,
select_only: Optional[Episode] = None) -> None:
select_only: Optional[Episode] = None,
) -> None:
"""
Modify this series' Episode source images based on their watch
statuses, and how that style applies to this show's un/watched
Expand Down Expand Up @@ -837,11 +838,13 @@ def select_source_images(self,
always_check_emby = (
bool(self.emby_interface)
and ('emby' in self.image_source_priority)
and self.emby_interface.has_series(self.series_info))
and self.emby_interface.has_series(self.library_name,
self.series_info))
always_check_jellyfin = (
bool(self.jellyfin_interface)
and ('jellyfin' in self.image_source_priority)
and self.jellyfin_interface.has_series(self.series_info))
and self.jellyfin_interface.has_series(self.library_name,
self.series_info))
always_check_tmdb = (
bool(self.tmdb_interface)
and ('tmdb' in self.image_source_priority))
Expand Down Expand Up @@ -886,6 +889,8 @@ def select_source_images(self,
)
elif source_interface == 'jellyfin' and check_jellyfin:
image = self.jellyfin_interface.get_source_image(
self.library_name,
self.series_info,
episode.episode_info,
)
elif source_interface == 'plex' and check_plex:
Expand Down
2 changes: 2 additions & 0 deletions modules/TitleCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Built-in BaseCardType classes
from modules.cards.AnimeTitleCard import AnimeTitleCard
from modules.cards.ComicBookTitleCard import ComicBookTitleCard
from modules.cards.CutoutTitleCard import CutoutTitleCard
from modules.cards.DividerTitleCard import DividerTitleCard
from modules.cards.FadeTitleCard import FadeTitleCard
Expand Down Expand Up @@ -58,6 +59,7 @@ class TitleCard:
'4x3': FadeTitleCard,
'anime': AnimeTitleCard,
'blurred border': TintedFrameTitleCard,
'comic book': ComicBookTitleCard,
'cutout': CutoutTitleCard,
'divider': DividerTitleCard,
'fade': FadeTitleCard,
Expand Down
2 changes: 1 addition & 1 deletion modules/WebInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def download_image(image: Union[str, bytes], destination: Path) -> bool:
if len(image) == 0:
raise Exception(f'URL {image} returned no content error')
if any(bad_content in image for bad_content in WebInterface.BAD_CONTENT):
raise Exception(f'URL {image} returned (bad) malormed content')
raise Exception(f'URL {image} returned (bad) malformed content')

# Write content to file, return success
destination.write_bytes(image)
Expand Down
11 changes: 8 additions & 3 deletions modules/cards/AnimeTitleCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ class AnimeTitleCard(BaseCardType):
'source_file', 'output_file', 'title_text', 'season_text',
'episode_text', 'hide_season_text', 'hide_episode_text', 'font_color',
'font_file', 'font_kerning', 'font_size', 'font_stroke_width',
'font_interline_spacing', 'font_vertical_shift', 'omit_gradient',
'stroke_color', 'separator', 'kanji', 'use_kanji', 'require_kanji',
'kanji_vertical_shift', 'episode_text_color',
'font_interline_spacing', 'font_interword_spacing',
'font_vertical_shift', 'omit_gradient', 'stroke_color', 'separator',
'kanji', 'use_kanji', 'require_kanji', 'kanji_vertical_shift',
'episode_text_color',
)

def __init__(self, *,
Expand All @@ -64,6 +65,7 @@ def __init__(self, *,
font_color: str = TITLE_COLOR,
font_file: str = TITLE_FONT,
font_interline_spacing: int = 0,
font_interword_spacing: int = 0,
font_kerning: float = 1.0,
font_size: float = 1.0,
font_stroke_width: float = 1.0,
Expand Down Expand Up @@ -105,6 +107,7 @@ def __init__(self, *,
self.font_color = font_color
self.font_file = font_file
self.font_interline_spacing = font_interline_spacing
self.font_interword_spacing = font_interword_spacing
self.font_kerning = font_kerning
self.font_size = font_size
self.font_stroke_width = font_stroke_width
Expand Down Expand Up @@ -136,6 +139,7 @@ def __title_text_global_effects(self) -> ImageMagickCommands:
f'-font "{self.font_file}"',
f'-kerning {kerning}',
f'-interline-spacing {interline_spacing}',
f'-interword-spacing {self.font_interword_spacing}',
f'-pointsize {font_size}',
f'-gravity southwest',
]
Expand Down Expand Up @@ -359,6 +363,7 @@ def is_custom_font(font: 'Font') -> bool: # type: ignore
return ((font.color != AnimeTitleCard.TITLE_COLOR)
or (font.file != AnimeTitleCard.TITLE_FONT)
or (font.interline_spacing != 0)
or (font.interword_spacing != 0)
or (font.kerning != 1.0)
or (font.size != 1.0)
or (font.stroke_width != 1.0)
Expand Down
Loading

0 comments on commit dff94d8

Please sign in to comment.