From 73f643955404134c12bf483c32fcbd2bb03a4bac Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 21:32:54 +0100 Subject: [PATCH 1/7] feat: adds video link to description (it's a wip, don't judge) --- main.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index d540132..6bffa4c 100644 --- a/main.py +++ b/main.py @@ -300,13 +300,20 @@ async def addFeedEntry(fg, episode, session, locale): fe = fg.add_entry() fe.guid(episode["id"]) fe.title(episode["title"]) - fe.description(episode["description"]) - fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) - fe.podcast.itunes_image(episode["imageUrl"]) url, duration = extract_audio_url(episode) if url is None: - return + return + + # Generate the video url and paste it as prefix in the description :') + ep_id = url.split("/")[-1].replace(".mp3", "") + hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" + description = f"Video URL: {hls_url} (ymmv) {episode['description']}" + fe.description(description) + + fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) + fe.podcast.itunes_image(episode["imageUrl"]) + logging.debug(f"Found podcast '{episode['title']}'") fe.podcast.itunes_duration(duration) content_length, content_type = await urlHeadInfo(session, episode['id'], url, locale) From 8d41f09fbc107661f56d6d3dd6de8ce3609c8e21 Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 22:12:17 +0100 Subject: [PATCH 2/7] feat: adds check if video exists and adds to description iff it does --- main.py | 12 ++++++++---- podimo/utils.py | 7 +++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 6bffa4c..c815d09 100644 --- a/main.py +++ b/main.py @@ -32,7 +32,7 @@ from hypercorn.asyncio import serve from urllib.parse import quote from podimo.config import * -from podimo.utils import generateHeaders, randomHexId +from podimo.utils import generateHeaders, randomHexId, video_exists_at_url import podimo.cache as cache import cloudscraper import traceback @@ -299,7 +299,6 @@ def extract_audio_url(episode): async def addFeedEntry(fg, episode, session, locale): fe = fg.add_entry() fe.guid(episode["id"]) - fe.title(episode["title"]) url, duration = extract_audio_url(episode) if url is None: @@ -308,8 +307,13 @@ async def addFeedEntry(fg, episode, session, locale): # Generate the video url and paste it as prefix in the description :') ep_id = url.split("/")[-1].replace(".mp3", "") hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" - description = f"Video URL: {hls_url} (ymmv) {episode['description']}" - fe.description(description) + + if video_exists_at_url(hls_url): + fe.description(f"Video URL found at: {hls_url} (experimental) || {episode['description']}") + fe.title(episode["title"] + " (video available)") + else: + fe.description(episode["description"]) + fe.title(episode["title"]) fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) fe.podcast.itunes_image(episode["imageUrl"]) diff --git a/podimo/utils.py b/podimo/utils.py index 9d6803b..0d9b4f6 100644 --- a/podimo/utils.py +++ b/podimo/utils.py @@ -21,6 +21,7 @@ from random import choice, randint from hashlib import sha256 import asyncio +import requests from functools import wraps, partial def randomHexId(length: int): @@ -68,3 +69,9 @@ async def run(*args, loop=None, executor=None, **kwargs): pfunc = partial(func, *args, **kwargs) return await loop.run_in_executor(executor, pfunc) return run + +def video_exists_at(url: str) -> bool: + res = requests.get(url) + if res.text.strip().startswith("#EXTM3U"): + return True + return False From f5be9c94b4610e72d21ed1e55b7143f9862280ea Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 22:12:17 +0100 Subject: [PATCH 3/7] feat: adds check if video exists and adds to description iff it does --- main.py | 12 ++++++++---- podimo/utils.py | 7 +++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 6bffa4c..c815d09 100644 --- a/main.py +++ b/main.py @@ -32,7 +32,7 @@ from hypercorn.asyncio import serve from urllib.parse import quote from podimo.config import * -from podimo.utils import generateHeaders, randomHexId +from podimo.utils import generateHeaders, randomHexId, video_exists_at_url import podimo.cache as cache import cloudscraper import traceback @@ -299,7 +299,6 @@ def extract_audio_url(episode): async def addFeedEntry(fg, episode, session, locale): fe = fg.add_entry() fe.guid(episode["id"]) - fe.title(episode["title"]) url, duration = extract_audio_url(episode) if url is None: @@ -308,8 +307,13 @@ async def addFeedEntry(fg, episode, session, locale): # Generate the video url and paste it as prefix in the description :') ep_id = url.split("/")[-1].replace(".mp3", "") hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" - description = f"Video URL: {hls_url} (ymmv) {episode['description']}" - fe.description(description) + + if video_exists_at_url(hls_url): + fe.description(f"Video URL found at: {hls_url} (experimental) || {episode['description']}") + fe.title(episode["title"] + " (video available)") + else: + fe.description(episode["description"]) + fe.title(episode["title"]) fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) fe.podcast.itunes_image(episode["imageUrl"]) diff --git a/podimo/utils.py b/podimo/utils.py index 9d6803b..0d9b4f6 100644 --- a/podimo/utils.py +++ b/podimo/utils.py @@ -21,6 +21,7 @@ from random import choice, randint from hashlib import sha256 import asyncio +import requests from functools import wraps, partial def randomHexId(length: int): @@ -68,3 +69,9 @@ async def run(*args, loop=None, executor=None, **kwargs): pfunc = partial(func, *args, **kwargs) return await loop.run_in_executor(executor, pfunc) return run + +def video_exists_at(url: str) -> bool: + res = requests.get(url) + if res.text.strip().startswith("#EXTM3U"): + return True + return False From 54fa0f1c47929e330695dff0cd07695b1b4b2a07 Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 22:26:43 +0100 Subject: [PATCH 4/7] fix: rename function --- podimo/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/podimo/utils.py b/podimo/utils.py index 0d9b4f6..b38cb43 100644 --- a/podimo/utils.py +++ b/podimo/utils.py @@ -70,7 +70,7 @@ async def run(*args, loop=None, executor=None, **kwargs): return await loop.run_in_executor(executor, pfunc) return run -def video_exists_at(url: str) -> bool: +def video_exists_at_url(url: str) -> bool: res = requests.get(url) if res.text.strip().startswith("#EXTM3U"): return True From c4d3c45fe6e07dd2f8f3a8bee8baef7576c5c8f3 Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 22:36:29 +0100 Subject: [PATCH 5/7] feat: adds env vars for video settings --- .env.example | 18 ++++++++++++++++++ main.py | 4 ++-- podimo/config.py | 7 +++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 80444d8..e61596b 100644 --- a/.env.example +++ b/.env.example @@ -115,3 +115,21 @@ PODIMO_BIND_HOST="127.0.0.1:12104" # Enable extra logging in debugging mode # Set to false if you don't want to see as much information DEBUG=true + +############# +## VIDEO ## +############# +# Experimental: enable rudimentary video support for video podcasts. +# This won't make the video available in your podcast app, but will add a link +# to the video (m3u8 stream) in the podcast description. +# This is a very experimental feature, may not work for all video podcasts. +# Enable this feature by setting the following variable to true. +# ENABLE_VIDEO=false + +# Optionally, you can add a custom string to the title of podcasts that have +# a video version (that will be in the description). To do so, set the following +# variable to the string you want to add (e.g. "(video available)"). +# VIDEO_TITLE_SUFFIX="(video available)" + + + diff --git a/main.py b/main.py index c815d09..7fc087b 100644 --- a/main.py +++ b/main.py @@ -308,9 +308,9 @@ async def addFeedEntry(fg, episode, session, locale): ep_id = url.split("/")[-1].replace(".mp3", "") hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" - if video_exists_at_url(hls_url): + if VIDEO_ENABLED and video_exists_at_url(hls_url): fe.description(f"Video URL found at: {hls_url} (experimental) || {episode['description']}") - fe.title(episode["title"] + " (video available)") + fe.title(episode["title"] + VIDEO_TITLE_SUFFIX) else: fe.description(episode["description"]) fe.title(episode["title"]) diff --git a/podimo/config.py b/podimo/config.py index b9bb6cb..5613923 100644 --- a/podimo/config.py +++ b/podimo/config.py @@ -115,3 +115,10 @@ if line and not line.startswith('#'): line = line.split(' ', 1)[0] BLOCKED.add(line) + + +# load experimental video support env vars +VIDEO_ENABLED = bool( + str(config.get("ENABLE_VIDEO", None)).lower() in ["true", "1", "t", "y", "yes"] +) +VIDEO_TITLE_SUFFIX = str(config.get("VIDEO_TITLE_SUFFIX", "")) \ No newline at end of file From 454c86048d08d8271b7249408c4ad3501a323c86 Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 22:38:30 +0100 Subject: [PATCH 6/7] feat: adds space hint --- .env.example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index e61596b..f2dc3a8 100644 --- a/.env.example +++ b/.env.example @@ -129,7 +129,8 @@ DEBUG=true # Optionally, you can add a custom string to the title of podcasts that have # a video version (that will be in the description). To do so, set the following # variable to the string you want to add (e.g. "(video available)"). -# VIDEO_TITLE_SUFFIX="(video available)" +# Remember to add a space at the beginning of the string. +# VIDEO_TITLE_SUFFIX=" (video available)" From 1f7c9242d7ad8e3a3934a4dc16d30bead94e85f2 Mon Sep 17 00:00:00 2001 From: Menno Liefstingh Date: Tue, 5 Nov 2024 23:01:26 +0100 Subject: [PATCH 7/7] make video checking optional --- .env.example | 8 +++++++- main.py | 14 +++++++++++--- podimo/config.py | 5 ++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index f2dc3a8..dc191ad 100644 --- a/.env.example +++ b/.env.example @@ -126,11 +126,17 @@ DEBUG=true # Enable this feature by setting the following variable to true. # ENABLE_VIDEO=false +# Optionally, you can check if a podcast has a video version by making a +# request to the Podimo servers. This isn't properly tested and might slow +# down the tool or break it. +# Enable this feature by setting the following variable to true. +# ENABLE_VIDEO_CHECK=false + # Optionally, you can add a custom string to the title of podcasts that have # a video version (that will be in the description). To do so, set the following # variable to the string you want to add (e.g. "(video available)"). # Remember to add a space at the beginning of the string. -# VIDEO_TITLE_SUFFIX=" (video available)" +# VIDEO_TITLE_SUFFIX='(video available)' diff --git a/main.py b/main.py index 7fc087b..6738956 100644 --- a/main.py +++ b/main.py @@ -308,9 +308,17 @@ async def addFeedEntry(fg, episode, session, locale): ep_id = url.split("/")[-1].replace(".mp3", "") hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" - if VIDEO_ENABLED and video_exists_at_url(hls_url): - fe.description(f"Video URL found at: {hls_url} (experimental) || {episode['description']}") - fe.title(episode["title"] + VIDEO_TITLE_SUFFIX) + if VIDEO_ENABLED: + if VIDEO_CHECK_ENABLED: + if video_exists_at_url(hls_url): + fe.description( + f"Video URL found at: {hls_url} (experimental) || {episode['description']}" + ) + fe.title(episode["title"] + VIDEO_TITLE_SUFFIX) + else: + fe.description(f"Video URL: {hls_url} (not verified) || {episode['description']}") + fe.title(episode["title"]) + else: fe.description(episode["description"]) fe.title(episode["title"]) diff --git a/podimo/config.py b/podimo/config.py index 5613923..14ebb23 100644 --- a/podimo/config.py +++ b/podimo/config.py @@ -121,4 +121,7 @@ VIDEO_ENABLED = bool( str(config.get("ENABLE_VIDEO", None)).lower() in ["true", "1", "t", "y", "yes"] ) -VIDEO_TITLE_SUFFIX = str(config.get("VIDEO_TITLE_SUFFIX", "")) \ No newline at end of file +VIDEO_CHECK_ENABLED = bool( + str(config.get("ENABLE_VIDEO_CHECK", None)).lower() in ["true", "1", "t", "y", "yes"] +) +VIDEO_TITLE_SUFFIX = str(config.get("VIDEO_TITLE_SUFFIX", ""))