From 3f7edc363551b9a477b76af1e56752c5aa0ed9fb Mon Sep 17 00:00:00 2001 From: JonnyWong16 Date: Sat, 24 Mar 2018 00:02:31 -0700 Subject: [PATCH] Redo newsletter template using tables --- .../images/newsletter/view-on-plex-cover.png | Bin 0 -> 4954 bytes .../images/newsletter/view-on-plex-poster.png | Bin 0 -> 5206 bytes .../newsletters/recently_added.html | 694 ++++++++++-------- .../newsletters/recently_added_master.html | 692 +++++++++-------- plexpy/helpers.py | 8 + plexpy/newsletters.py | 6 +- 6 files changed, 780 insertions(+), 620 deletions(-) create mode 100644 data/interfaces/default/images/newsletter/view-on-plex-cover.png create mode 100644 data/interfaces/default/images/newsletter/view-on-plex-poster.png diff --git a/data/interfaces/default/images/newsletter/view-on-plex-cover.png b/data/interfaces/default/images/newsletter/view-on-plex-cover.png new file mode 100644 index 0000000000000000000000000000000000000000..506848b71ed96679422484437c28798aad566154 GIT binary patch literal 4954 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 literal 0 HcmV?d00001 diff --git a/data/interfaces/default/images/newsletter/view-on-plex-poster.png b/data/interfaces/default/images/newsletter/view-on-plex-poster.png new file mode 100644 index 0000000000000000000000000000000000000000..40a3e2d1e7c2b6f8eaa0a1e0be07128e258c1ba3 GIT binary patch literal 5206 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 div { - padding: 5px; - text-overflow: ellipsis; - overflow: hidden; + .card-info-container > table { + height: 100%; } .card-info-title { border-bottom: 1px solid rgba(255, 255, 255, .1); - line-height: 20px; - font-size: 15px; + line-height: 1.2rem; + font-size: 0.9rem; + padding: 5px; } .card-info-title a { text-decoration: none; color: #ffffff; } - .card-info-body > div { - color: #ffffff; - font-size: 12px; - text-overflow: ellipsis; - overflow: hidden; + .card-info-body { + font-size: 0.75rem; + padding: 5px; + height: 100%; + } + .card-info-body > p { + max-width: 325px; } .card-instance.movie .card-info-body, .card-instance.show .card-info-body { - min-height: 157px; } .card-instance.album .card-info-body { + height: 82px; min-height: 82px; } .card-info-footer { - font-size: 10px; + font-size: 0.6rem; + padding-top: 0px; + padding-right: 5px; + padding-bottom: 5px; + padding-left: 5px; + } + .card-info-footer .star-rating-container { + vertical-align: bottom; + padding-right: 5px; } .card-info-footer .star-rating { - width: 60px; - font-size: 14px; - line-height: 17px; - float: right; - } - .star-rating-full { - color: #E5A00D; - direction: ltr; - padding: 0; - overflow: hidden; - float: left; - } - .star-rating-empty { - color: #aaaaaa; - direction: rtl; - padding: 0; - overflow: hidden; - float: left; - } - .star-rating span { + font-size: 0.8rem; + line-height: 1rem; + width: 0.5rem; display: inline-block; - text-align: center; - width: 12px; + } + .star-rating.full { + color: #E5A00D; + } + .star-rating.empty { + color: #aaaaaa; } .badge { display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 11px; - font-style: normal; line-height: 1; - color: #fff; text-align: center; white-space: nowrap; vertical-align: middle; background-color: rgba(0, 0, 0, .25); border-radius: 2px; + max-width: 75px; + text-overflow: ellipsis; + overflow: hidden; } /* ------------------------------------- RESPONSIVE AND MOBILE FRIENDLY STYLES ------------------------------------- */ - @media only screen and (max-width: 620px) { + @media only screen and (max-width: 1040px) { + .card-instance { + display: block !important; + margin: 0 auto; + } + table[class=body] .header { background-position: center !important; } @@ -510,11 +496,6 @@ font-size: 14px !important; } - table[class=body] .card-instance { - margin: 3px auto; - float: none; - } - table[class=body] .content { padding: 0 !important; } @@ -573,12 +554,12 @@
-
+
- + - +
@@ -588,9 +569,9 @@
${parameters['start_date']} - ${parameters['end_date']}
+ % if recently_added.get('movie'): + + + + + % endif + % if recently_added.get('show'): + + + + % endif + % if recently_added.get('artist'): + + + + % endif + + diff --git a/data/interfaces/newsletters/recently_added_master.html b/data/interfaces/newsletters/recently_added_master.html index 6cfe1879..179aa5da 100644 --- a/data/interfaces/newsletters/recently_added_master.html +++ b/data/interfaces/newsletters/recently_added_master.html @@ -1,6 +1,7 @@ % if data: <% import plexpy + from helpers import grouper recently_added = data['recently_added'] if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.NEWSLETTER_BASE_URL: @@ -73,7 +74,7 @@ box-sizing: border-box; display: block; margin: 0 auto; - max-width: 1042px; + max-width: 1037px; padding: 10px; } @@ -139,10 +140,8 @@ ul, ol { font-family: 'Open Sans', Helvetica, Arial, sans-serif; - font-size: 14px; font-weight: 400; margin: 0; - margin-bottom: 15px; } p li, @@ -245,6 +244,8 @@ .nowrap { white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } .clear { clear: both; @@ -335,150 +336,135 @@ MEDIA CARDS ------------------------------------- */ .card-instance { - float: left; - width: 500px; - margin: 3px; - border: 1px solid rgba(255,255,255,.1); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; font-size: 12px; overflow: hidden; - position: relative; + padding: 3px; + width: 502px; + min-width: 502px; + max-width: 502px; } .card-instance.movie, .card-instance.show { - height: 235px; + height: 233px; } .card-instance.album { - height: 160px; - } - .card-instance.odd { - float: none !important; - margin: 3px auto !important; + height: 158px; } .card-background { background-position: center; background-size: cover; - width: 100%; - height: 100%; + background-repeat: no-repeat; + background-clip: padding-box; + border: 1px solid rgba(255,255,255,.1); } .card-poster-container { - width: 150px; - margin: 3px; - border: 1px solid rgba(255,255,255,.1); - float: left; - position: relative; - z-index: 1; + width: 152px; + min-width: 152px; } .card-instance.movie .card-poster-container, .card-instance.show .card-poster-container{ - height: 225px; + height: 227px; } .card-instance.album .card-poster-container { - height: 150px; + height: 152px; } .card-poster { background-color: #3F4245; background-position: center; background-size: cover; - height: 100%; - width: 100%; + background-repeat: no-repeat; + background-clip: padding-box; + border: 1px solid rgba(255,255,255,.1); } .card-poster-overlay { - background-repeat: no-repeat; - background-position: bottom right; - width: 100%; - height: 100%; + display: block; } .card-info-container { - margin: 4px; - width: 332px; - float: left; - position: relative; - z-index: 1; + padding-left: 4px; } .card-instance.movie .card-info-container, .card-instance.show .card-info-container{ - height: 225px; + height: 227px; } .card-instance.album .card-info-container { - height: 150px; + height: 152px; } - .card-info-container > div { - padding: 5px; - text-overflow: ellipsis; - overflow: hidden; + .card-info-container > table { + height: 100%; } .card-info-title { border-bottom: 1px solid rgba(255, 255, 255, .1); - line-height: 20px; - font-size: 15px; + line-height: 1.2rem; + font-size: 0.9rem; + padding: 5px; } .card-info-title a { text-decoration: none; color: #ffffff; } - .card-info-body > div { - color: #ffffff; - font-size: 12px; - text-overflow: ellipsis; - overflow: hidden; + .card-info-body { + font-size: 0.75rem; + padding: 5px; + height: 100%; + } + .card-info-body > p { + max-width: 325px; } .card-instance.movie .card-info-body, .card-instance.show .card-info-body { - min-height: 157px; } .card-instance.album .card-info-body { + height: 82px; min-height: 82px; } .card-info-footer { - font-size: 10px; + font-size: 0.6rem; + padding-top: 0px; + padding-right: 5px; + padding-bottom: 5px; + padding-left: 5px; + } + .card-info-footer .star-rating-container { + vertical-align: bottom; + padding-right: 5px; } .card-info-footer .star-rating { - width: 60px; - font-size: 14px; - line-height: 17px; - float: right; - } - .star-rating-full { - color: #E5A00D; - direction: ltr; - padding: 0; - overflow: hidden; - float: left; - } - .star-rating-empty { - color: #aaaaaa; - direction: rtl; - padding: 0; - overflow: hidden; - float: left; - } - .star-rating span { + font-size: 0.8rem; + line-height: 1rem; + width: 0.5rem; display: inline-block; - text-align: center; - width: 12px; + } + .star-rating.full { + color: #E5A00D; + } + .star-rating.empty { + color: #aaaaaa; } .badge { display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 11px; - font-style: normal; line-height: 1; - color: #fff; text-align: center; white-space: nowrap; vertical-align: middle; background-color: rgba(0, 0, 0, .25); border-radius: 2px; + max-width: 75px; + text-overflow: ellipsis; + overflow: hidden; } /* ------------------------------------- RESPONSIVE AND MOBILE FRIENDLY STYLES ------------------------------------- */ - @media only screen and (max-width: 620px) { + @media only screen and (max-width: 1040px) { + .card-instance { + display: block !important; + margin: 0 auto; + } + table[class=body] .header { background-position: center !important; } @@ -510,11 +496,6 @@ font-size: 14px !important; } - table[class=body] .card-instance { - margin: 3px auto; - float: none; - } - table[class=body] .content { padding: 0 !important; } @@ -576,9 +557,9 @@
- Tautulli card-backbro - ${title} + Tautulli Newsletter - ${title} -
- % if recently_added.get('movie'):
@@ -602,67 +583,106 @@
-
- % for movie in recently_added['movie']: - <% - if loop.index == len(recently_added['movie'])-1 and loop.index % 2 == 0: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
- % if movie['tagline']: -
- ${movie['tagline']} -
- % endif -
- ${movie['summary'][:450] + (movie['summary'][450:] and '...')} -
-
- -
-
-
- % endfor -
- % endif - % if recently_added.get('show'): +
+ + + % for movie_a, movie_b in grouper(recently_added['movie'], 2): + + % for movie in (movie_a, movie_b): + % if movie: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${movie['title']} +
+ % if movie['tagline']: +

+ ${movie['tagline']} +

+ % endif +

+ ${movie['summary'][:450] + (movie['summary'][450:] and '...')} +

+
+
+
+
@@ -676,101 +696,129 @@
-
- % for show in recently_added['show']: - <% - if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: - link_rating_key = show['season'][0]['episode'][0]['rating_key'] - link_title = show['title'] + " - " + show['season'][0]['episode'][0]['title'] - else: - link_rating_key = show['rating_key'] - link_title = show['title'] - - if loop.index == len(recently_added['show'])-1 and loop.index % 2 == 0: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
-
- % if show['season_count'] > 1: - ${show['season_count']} seasons / - % endif - <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> - ${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''} -
-
- % for i, season in enumerate(show['season'][:8]): - Season ${season['media_index']} · - % if season['episode_count'] == 1: - Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} - % else: - Episodes ${season['episode_range']} - % endif - % if i < min(show['season_count'], 7): -
- % elif i == 7 and show['season_count'] > 8: - ...plus ${show['season_count'] - 8} more seasons! - % endif - % endfor -
-
- % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: - ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} - % else: - <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> - % if length: - ${show['summary'][:length] + (show['summary'][length:] and '...')} - % endif - % endif -
-
- -
-
-
- % endfor -
- % endif - % if recently_added.get('artist'): + + + % for show_a, show_b in grouper(recently_added['show'], 2): + + % for show in (show_a, show_b): + % if show: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${show['title']} +
+

+ % if show['season_count'] > 1: + ${show['season_count']} seasons / + % endif + <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> + ${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''} +

+

+ % for i, season in enumerate(show['season'][:8]): + Season ${season['media_index']} · + % if season['episode_count'] == 1: + Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} + % else: + Episodes ${season['episode_range']} + % endif + % if i < min(show['season_count'], 7): +
+ % elif i == 7 and show['season_count'] > 8: + ...plus ${show['season_count'] - 8} more seasons! + % endif + % endfor +

+

+ % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: + ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} + % else: + <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> + % if length: + ${show['summary'][:length] + (show['summary'][length:] and '...')} + % endif + % endif +

+
+
+
+
@@ -784,71 +832,100 @@
-
- <% album_count = 0 %> - % for artist in recently_added['artist']: - % for album in artist['album']: - <% - album_count += 1 - - if album_count == total_albums and album_count % 2 == 1: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
-
- ${artist['title']} · ${album['track_count']} track${'s' if album['track_count'] > 1 else ''} -
- % if artist['title'].lower() != 'various artists': -
- ${album['summary'][:200] + (album['summary'][200:] and '...')} -
- % endif -
- -
-
-
- % endfor - % endfor -
- % endif - + + + % for album_a, album_b in grouper([a for artist in recently_added['artist'] for a in artist['album']], 2): + + % for album in (album_a, album_b): + % if album: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${album['title']} +
+

+ ${album['parent_title']} · ${album['track_count']} track${'s' if album['track_count'] > 1 else ''} +

+ % if artist['title'].lower() != 'various artists': +

+ ${album['summary'][:200] + (album['summary'][200:] and '...')} +

+ % endif +
+
+
+
-
+
@@ -588,9 +569,9 @@
${parameters['start_date']} - ${parameters['end_date']}
+ % if recently_added.get('movie'): + + + + + % endif + % if recently_added.get('show'): + + + + % endif + % if recently_added.get('artist'): + + + + % endif + + diff --git a/plexpy/helpers.py b/plexpy/helpers.py index 466d901d..175588c9 100644 --- a/plexpy/helpers.py +++ b/plexpy/helpers.py @@ -20,6 +20,7 @@ import geoip2.database, geoip2.errors import gzip import hashlib import imghdr +from itertools import izip_longest import ipwhois, ipwhois.exceptions, ipwhois.utils from IPy import IP import json @@ -974,3 +975,10 @@ def momentjs_to_arrow(format, duration=False): for f in invalid_formats: format = format.replace(f, '') return format + + +def grouper(iterable, n, fillvalue=None): + "Collect data into fixed-length chunks or blocks" + # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx + args = [iter(iterable)] * n + return izip_longest(fillvalue=fillvalue, *args) \ No newline at end of file diff --git a/plexpy/newsletters.py b/plexpy/newsletters.py index 95318a7a..ed822045 100644 --- a/plexpy/newsletters.py +++ b/plexpy/newsletters.py @@ -413,7 +413,7 @@ class Newsletter(object): os.makedirs(newsletter_folder) try: - with open(newsletter_file_fp, 'w') as n_file: + with open(newsletter_file_fp, 'wb') as n_file: n_file.write(self.newsletter.encode('utf-8')) logger.info(u"Tautulli Newsletters :: %s newsletter saved to %s" % (self.NAME, newsletter_file)) @@ -661,8 +661,8 @@ class RecentlyAdded(Newsletter): if self.is_preview or plexpy.CONFIG.NEWSLETTER_SELF_HOSTED: for item in movies + shows + albums: item['thumb_hash'] = set_hash_image_info(img=item['thumb'], - width=300, - height=450, + width=150, + height=225, fallback='poster') item['art_hash'] = set_hash_image_info(img=item['art'], width=500,
- % if recently_added.get('movie'):
@@ -602,67 +583,106 @@
-
- % for movie in recently_added['movie']: - <% - if loop.index == len(recently_added['movie'])-1 and loop.index % 2 == 0: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
- % if movie['tagline']: -
- ${movie['tagline']} -
- % endif -
- ${movie['summary'][:450] + (movie['summary'][450:] and '...')} -
-
- -
-
-
- % endfor -
- % endif - % if recently_added.get('show'): +
+ + + % for movie_a, movie_b in grouper(recently_added['movie'], 2): + + % for movie in (movie_a, movie_b): + % if movie: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${movie['title']} +
+ % if movie['tagline']: +

+ ${movie['tagline']} +

+ % endif +

+ ${movie['summary'][:450] + (movie['summary'][450:] and '...')} +

+
+
+
+
@@ -676,101 +696,129 @@
-
- % for show in recently_added['show']: - <% - if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: - link_rating_key = show['season'][0]['episode'][0]['rating_key'] - link_title = show['title'] + " - " + show['season'][0]['episode'][0]['title'] - else: - link_rating_key = show['rating_key'] - link_title = show['title'] - - if loop.index == len(recently_added['show'])-1 and loop.index % 2 == 0: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
-
- % if show['season_count'] > 1: - ${show['season_count']} seasons / - % endif - <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> - ${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''} -
-
- % for i, season in enumerate(show['season'][:8]): - Season ${season['media_index']} · - % if season['episode_count'] == 1: - Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} - % else: - Episodes ${season['episode_range']} - % endif - % if i < min(show['season_count'], 7): -
- % elif i == 7 and show['season_count'] > 8: - ...plus ${show['season_count'] - 8} more seasons! - % endif - % endfor -
-
- % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: - ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} - % else: - <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> - % if length: - ${show['summary'][:length] + (show['summary'][length:] and '...')} - % endif - % endif -
-
- -
-
-
- % endfor -
- % endif - % if recently_added.get('artist'): + + + % for show_a, show_b in grouper(recently_added['show'], 2): + + % for show in (show_a, show_b): + % if show: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${show['title']} +
+

+ % if show['season_count'] > 1: + ${show['season_count']} seasons / + % endif + <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> + ${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''} +

+

+ % for i, season in enumerate(show['season'][:8]): + Season ${season['media_index']} · + % if season['episode_count'] == 1: + Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} + % else: + Episodes ${season['episode_range']} + % endif + % if i < min(show['season_count'], 7): +
+ % elif i == 7 and show['season_count'] > 8: + ...plus ${show['season_count'] - 8} more seasons! + % endif + % endfor +

+

+ % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: + ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} + % else: + <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> + % if length: + ${show['summary'][:length] + (show['summary'][length:] and '...')} + % endif + % endif +

+
+
+
+
@@ -784,71 +832,100 @@
-
- <% album_count = 0 %> - % for artist in recently_added['artist']: - % for album in artist['album']: - <% - album_count += 1 - - if album_count == total_albums and album_count % 2 == 1: - clear = '
' - odd = 'odd' - else: - clear = odd = '' - %> - ${clear | n} -
-
- -
- -
-
- ${artist['title']} · ${album['track_count']} track${'s' if album['track_count'] > 1 else ''} -
- % if artist['title'].lower() != 'various artists': -
- ${album['summary'][:200] + (album['summary'][200:] and '...')} -
- % endif -
- -
-
-
- % endfor - % endfor -
- % endif - + + + % for album_a, album_b in grouper([a for artist in recently_added['artist'] for a in artist['album']], 2): + + % for album in (album_a, album_b): + % if album: + + % else: + + % endif + % endfor + + % endfor + +
+ + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + + + +
+ ${album['title']} +
+

+ ${album['parent_title']} · ${album['track_count']} track${'s' if album['track_count'] > 1 else ''} +

+ % if artist['title'].lower() != 'various artists': +

+ ${album['summary'][:200] + (album['summary'][200:] and '...')} +

+ % endif +
+
+
+
-