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 zcmeHLdpuNm|5v+h(XzCnr(GH2QZ92fh8c!1ZY^@BB*vM+U@qo@A=#vikU}aEmHRE1 z7P;}>G>g9ay&8NL*FIE@LSB_xbY!kHu>h{A#RQv9iO0#ww{0)oQHiOFoC>Eh0P1TLvF!AOr3W>vDxiA>PpAzNpi89389J0@yN+&bI*qVQU zQ-~xEg#ZO}W&lI#!qB=dV8Zlt@fb7=sgFk@KS1pmWU3$UpP(olh`?h|e+LBxLnd)Z z{}D_E@O}&yjRbC&N+bDG5KOv16!JNUcymTDg9SPU+3EiAxsAEG1B>BD4F)IJPF7|R z8w+zR3WvqQ&~Vgyx^{MW8#qpYlCFArBFr-iGi41_dA%KnbA8LWj06-i6M~`GcLE-=a3DX5|D3~vR0bn?N zBn1ZO`ytVK1{gnmiryz{2U%3G97(}{w7S8H3|jOh>*}Hm4D?_a3>J*P?*=O}1qH(a zNPR4l?1up;lnv3p*Ad>D$_6vc`&dTKl#q|3U@GLjbnql#qa+AWU_%QOGW6qP>Yv2p zzw-QXeOLemH2QB;^1(Zs;l~Lhu_&hgVC?>b1`+>?I-3;w?}`6+iTuFmpNRjXX8-@h zKZXPdAkqCPU~ff0H@1S<=t3V7g80W=y`TF-$NB^Z+u+9VbN>ZzK6h{m9W>1X`*V}h zTs+wS+&yj63kz*`v{KAQ8A;z93FtBB8G+bXe zAD7{Vb#^|Rp})0&H>Nj`tl5(~m#;=^WIcIcAh+t6>#?M|BRZ`;=1x^f!-`Nev3Ble ztxiKH{H>e9(d5fnLQz#k!${Qf(y@t7D>aobH*qjaZY>foGGrAh_Iv!inY3wp>=vE> z-TW^G+vnX{e)LhZsTUwNJ+XY%M>4&4K5_evvP+6mGd!=WHXH8tQGoKY3Wg z_SD0#V3vDLYEizX?WGVwV-%Pl2HkxZ-4nc+^)7~+>2EIowIo@cL_#Y>U6&NOMQ z(KM@VC7#NL*G~7Cs=z9kaaP1)wIJ@t8R8j?Au?Dn5uhq}>={X@+lIr8#x`S*uL`6Qf4j=moQtCOG z4+G(5ft~xF>oa4yK|^yC9r*}rk{#~^UA6SeWI7CxWO?r!8GN!&;QJj(X!LYX+Eyt| z2it3Bos>||mn;Q;jj32%`ilEQdSxs#y29sfyi_#p^r3>otvl`jVj-Q|v3+h>)~#(a zt<%G7aoC~2Xsmg^>P=#-3D9>QKaWnA7@WF1vnsxesxe$pu1%7at4vh?Ike(DIxXi| zv@_%{h8FbMH(!c;8chrYJvAYyr6KInkj(rJJ;re3VvouCv8s@fOdNap^>C9R``zn- zkcQByh;w{f3k!>H($dqrwP3I;M<*vV!O*Z_p@uey=C@-g9chotJZslF!q=p~!wx;4 zJ?si~nw_0>?&$1{j+%LPe}K^g10$C6F178Vv7 zczbzGtJ=}~ukiWS+oreLq+tJID5>fe zzS)k{tePtNH7s|gNrsmjSbvG%&RL#&S(W$0MSHdDg}pbdOd6?=^49}1@?X`%^$C_c z%=Ya`wjxBYHFo+|21rXwUsQx2xnvOjcJ!AE7cPvz4pou+p50H4Q!)%K?O5RUTqQ)# zb!QnS>v%V>PE1^ld^6GS9W5SJO*TSTy^M19^76X-M%Wl#jyfH^ogY_ zYnv^;MM9&Kg;kW!^BXKOv$IVeyyP79YB?_6>D4dD?+@BxW<5PUEm>4lWWLufgR@oc zvVEq3<5HjV!MypY!LZQ=QL|@8W~LDm2AjGH^2wZy$dZ!N^s62?;^{ew9S$=!H7#4P z*VNKlHrCVQJ`B3qgl!LtQz;!y%!yG##-W{fR&qMXXq7EeI>k9Tqg7pg)#Kyi-QstH zjL!J>XVc;GDzS3u!Id7(oev%itv^dWxVE2I{Ht$K2Y47CUtNqBl(>7Qrlh=4gHmV5 zyONqkWyQrE8EI*K1ys+7*)IK5C7HNKkz2d2=!<3>8yiEK4P{766OmY>zDswqW;UPd zdxZ%Ya(8oc+oPx$*49_#+{tgxoveSgGabX5d3LKQa=|ZZ`d7uv#N6`3KNaU!R!$$V zvAKT;>ZGNu-E&+#-(OJl{Dn5cv*z`S#pyBUGYJW83W|!!S-Sq+QQGe1MlYIffK)R< zSw4q_LS%-on5bKfqSFhqkJpR7V>E^gJU&{-B>mM;)W}vxAVlwO-MTe+N|t43m&ESM z(7VXD?(XVJ8f@fMC-I+2eyefmlnwy72KIH+>N?Sq~>4O6T*{ zY*Jo_HcXzVd}%o0-=~hqP|#~tm2axKx_iB@vezl(Y;bRH@66upV<|Yl2bX?HQL~Br zM%nmcR+d;@&i!VP`tqQR@v}+bk&uv}jPfNOV6j*&ZF?ev8Md~G z;9q~N1|E;s($YFGzkEENPquJOyLa#2(U6c3l-ahYtlJo93VCVS(dkIG$Go?lzmAVuTbkG_t!#WOAT%^I!p-gX>C>mbO5$5T z!U)HvcbQDKnn1kzDYb)T-^wZBIWJx(AezI$Nx7Xn)o&kxhZN7mjJ?wPZGGn2%FiR~ zxepvDDawr(Q{0~k*E^kgyt^*07vlL~%Vf_qEetpKydHY9E1lsW*N~X^5|UNwRsw)E z?#?e%(a;zlU7nweD=aSlS_wagtsRUSOWLlInEmMWt`47{4o@j0 zjOn%(-f(esQ|Nh19=@7sO(b%;+@zrXa>BTH@r}Hj`;k^NB9UI}d3`cF&nVzw&Ty+( zCeD1XPlsju!lmOT%3vL7XQA0g4>0EdH$R=RK+Owc2@o16g?#Hn)Ycy)`qR~g1|Bp_PA|U z=ku8(bGXU*2MnS2HRa1TBbTb;GbRg_IR+nl=cwY@fYL9{mL9qv%rP434hQ0$q9%$^m^3F zJ6Evd?cw0F`sB?MPO??L9GH4Hp0~(s5blY)dreA75R(bP7#2yYYGP?P zn-nwf8;WWzU3i%LtX=NP^y6|_w}L~hJ6ZuT!7Av6b3#R;(&%)!THIYzc`^sgUPpWT zi_~-He85U{a&@ggwp6w9*IyIhV`@Cna8uW}d+lEXnftg6!sSY!Z8z96*8+CWXW?2g zXZY8SU2KR5#d)F`gl#WzEgQ zl*r?0%7QXba4QiU_4XD81O(JQnd3g44v)>JE gc3ak literal 0 HcmV?d00001 diff --git a/data/interfaces/newsletters/recently_added.html b/data/interfaces/newsletters/recently_added.html index e5f79219..43a62e8a 100644 --- a/data/interfaces/newsletters/recently_added.html +++ b/data/interfaces/newsletters/recently_added.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; } @@ -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 +
+
+
+
-