diff --git a/build.py b/build.py index c515a40..17c5b3b 100644 --- a/build.py +++ b/build.py @@ -14,6 +14,10 @@ CHANNEL = 'UC8gVtzB3Lqm7nnfMhMvXGxQ' # YouTube separa cada tipo en su propia lista: UULF = solo vídeos, UUSH = solo Shorts FEED_VIDEOS = os.environ.get('FEED_VIDEOS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UULF{CHANNEL[2:]}') FEED_SHORTS = os.environ.get('FEED_SHORTS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UUSH{CHANNEL[2:]}') +FEED_POP_VIDEOS = os.environ.get('FEED_POP_VIDEOS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UULP{CHANNEL[2:]}') +FEED_POP_SHORTS = os.environ.get('FEED_POP_SHORTS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UUPS{CHANNEL[2:]}') +POP_VIDEOS_SHOWN = 4 +POP_SHORTS_SHOWN = 6 VIDEOS_SHOWN = 8 # además del destacado SHORTS_SHOWN = 12 NS = {'a': 'http://www.w3.org/2005/Atom', 'y': 'http://www.youtube.com/xml/schemas/2015', @@ -40,16 +44,22 @@ def read_feed(url): 'title': e.find('a:title', NS).text, 'date': f'{int(d[2])} {MESES[int(d[1]) - 1]} {d[0]}', 'desc': e.find('m:group/m:description', NS).text or '', + 'views': int((e.find('m:group/m:community/m:statistics', NS).attrib.get('views') or 0) + if e.find('m:group/m:community/m:statistics', NS) is not None else 0), }) return out try: videos, shorts = read_feed(FEED_VIDEOS), read_feed(FEED_SHORTS) + pop_videos, pop_shorts = read_feed(FEED_POP_VIDEOS), read_feed(FEED_POP_SHORTS) except Exception as exc: # sin red o feed caído: se conserva la web anterior print('feed no disponible, se mantiene index.html:', exc, file=sys.stderr) sys.exit(0) videos, shorts = videos[:VIDEOS_SHOWN + 1], shorts[:SHORTS_SHOWN] +# la lista de populares de YouTube no viene ordenada por vistas: se ordena aquí +pop_videos = sorted(pop_videos, key=lambda v: -v['views'])[:POP_VIDEOS_SHOWN] +pop_shorts = sorted(pop_shorts, key=lambda v: -v['views'])[:POP_SHORTS_SHOWN] def sync_thumbs(vids): @@ -73,10 +83,12 @@ def sync_thumbs(vids): return ok -ok = sync_thumbs(videos + shorts) +ok = sync_thumbs(videos + shorts + pop_videos + pop_shorts) okids = {v['id'] for v in ok} videos = [v for v in videos if v['id'] in okids] shorts = [v for v in shorts if v['id'] in okids] +pop_videos = [v for v in pop_videos if v['id'] in okids] +pop_shorts = [v for v in pop_shorts if v['id'] in okids] if not videos: sys.exit(0) @@ -128,24 +140,30 @@ def url(v): return f"https://www.youtube.com/watch?v={v['id']}" -def card(v, n): +def vistas(v): + return f"{v['views']:,}".replace(',', '.') + ' vistas' if v['views'] else '' + + +def card(v, n, show_views=False): return f''' - {esc(v['title'])} + {esc(v['title'])} ''' -def short_card(v, n): +def short_card(v, n, show_views=False): return f''' - {esc(v['title'])} + {esc(v['title'])}{'' if show_views and v['views'] else ''} ''' cards = ''.join(card(v, i) for i, v in enumerate(rest)) scards = ''.join(short_card(v, i) for i, v in enumerate(shorts)) +pcards = ''.join(card(v, i, True) for i, v in enumerate(pop_videos)) +pscards = ''.join(short_card(v, i, True) for i, v in enumerate(pop_shorts)) page = f''' @@ -223,6 +241,19 @@ page = f''' +
+
+

Lo más visto

+ Ver populares en YouTube → +
+

Vídeos

+
{pcards} +
+

Shorts

+
{pscards} +
+
+

De qué va

Un programa de noche, con tertulia y sin prisa. Cada semana entra gente distinta, con su oficio y su manía, y se habla de lo que sale: de cómo se educa a un adolescente, de la vida en las calles de El Cairo, de si el árabe es tan antiguo como dicen, de qué tienen en común las religiones o de cómo se hace un truco de cartas.

diff --git a/public/index.html b/public/index.html index 3783565..08563df 100644 --- a/public/index.html +++ b/public/index.html @@ -154,6 +154,59 @@
+
+
+

Lo más visto

+ Ver populares en YouTube → +
+

Vídeos

+
+ + + DOMESTICAR ADOLESCENTES, PLANTAR TOMATES Y CONSTRUIR MINIATURAS | AQNSN Programa 3 - Galaxoide + + + + ¿Cómo es la vida nocturna y callejera en Egipto? + + + + ISA BECERRIL NOS PRESENTA SU NOVELA "HIALURÓNICO" | AQNSN Episodio Piloto 0 + + + + Árabe formal VS Árabe de la calle, ¿qué diferencias hay? + +
+

Shorts

+
+ + + El árabe que se estudia y el que se habla en las calles son diferentes + + + + 😌 "Solo vi a una persona morir sonriendo..." + + + + "Recoger a un niño ahogado de dos años, eso..." + + + + Poligamia en Egipto, de la antigüedad a la actualidad + + + + El número 13 y su relación con la muerte #podcast #granada #misterio #latenight #andaquenosabesna + + + + ¿Cómo puede meterte miedo un Tanatopractor? 😖 + +
+
+

De qué va

Un programa de noche, con tertulia y sin prisa. Cada semana entra gente distinta, con su oficio y su manía, y se habla de lo que sale: de cómo se educa a un adolescente, de la vida en las calles de El Cairo, de si el árabe es tan antiguo como dicen, de qué tienen en común las religiones o de cómo se hace un truco de cartas.

diff --git a/public/styles.css b/public/styles.css index 24679bb..cd8442a 100644 --- a/public/styles.css +++ b/public/styles.css @@ -222,3 +222,7 @@ footer { margin-top: 40px; border-top: 1px solid var(--line); background: var(-- .scard:hover img { transform: scale(1.06); } .scard:hover .play { opacity: 1; } .scard .play::after { width: 44px; height: 44px; } + +/* lo más visto */ +.sub { margin: 26px 0 14px; font-size: .8rem; letter-spacing: .22em; text-transform: uppercase; color: var(--amber); font-weight: 700; } +.scard .meta time { color: var(--muted); font-size: .8rem; }