From 7b6f5ff7dc99cfde3b578eca1fe4714c09e8c21d Mon Sep 17 00:00:00 2001 From: sebastien durand <101456991+sebastiendurand78@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:22:12 +0100 Subject: [PATCH 1/4] Improved URL resolving. radio garden urls are actually holders or links, to other sources. This fix for example playing correctly the playlist with player such as Winamp (that doesn't auto resolve links) and provide the real URLs of the streams. --- main.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index cffb78e..4bc11af 100644 --- a/main.py +++ b/main.py @@ -10,8 +10,7 @@ parser.add_argument('--country', help='Country name', type=str, required=True) parser.add_argument('--state', help='State or province name', type=str, required=False) args = parser.parse_args() - -BASE_URL = "http://radio.garden/api" +BASE_URL = "https://radio.garden/api" def get_places(): @@ -25,6 +24,14 @@ def get_places(): return sorted(list) +def resolve_final_stream_url(rg_proxy_url): + try: + # Make a HEAD request to follow redirects but not download stream content + response = requests.get(rg_proxy_url, allow_redirects=True, stream=True, timeout=10) + return response.url # This is the final resolved stream URL + except Exception as e: + print(f"[ERROR] Couldn't resolve URL for {rg_proxy_url}: {e}") + return rg_proxy_url # fallback to original def get_stations(place_id): list = [] @@ -47,9 +54,9 @@ def m3u(stations): for station in stations: station_name = station[0] - stream_url = get_stream_url(station[1]) + resolved_url = resolve_final_stream_url(get_stream_url(station[1])) f.write(f'#EXTINF:-1 tvg-name="{station_name}", {station_name}\n') - f.write(f'{stream_url}\n') + f.write(f'{resolved_url}\n') f.close() def main(): From 8d8b80a776b7127aefc452f0d64b04cebdc959cf Mon Sep 17 00:00:00 2001 From: sebastien durand <101456991+sebastiendurand78@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:41:39 +0100 Subject: [PATCH 2/4] this is an additional argument to filter out not working streams/not responding streams. very useful to end with a clean working m3u --- main.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 4bc11af..1823384 100644 --- a/main.py +++ b/main.py @@ -8,6 +8,8 @@ parser = argparse.ArgumentParser( parser.add_argument('--country', help='Country name', type=str, required=True) parser.add_argument('--state', help='State or province name', type=str, required=False) +parser.add_argument('--onlinestream', help='Only working stream w. response 200.', type=str, required=False) + args = parser.parse_args() BASE_URL = "https://radio.garden/api" @@ -27,8 +29,14 @@ def get_places(): def resolve_final_stream_url(rg_proxy_url): try: # Make a HEAD request to follow redirects but not download stream content - response = requests.get(rg_proxy_url, allow_redirects=True, stream=True, timeout=10) - return response.url # This is the final resolved stream URL + response_api = requests.get(rg_proxy_url, allow_redirects=True, stream=True, timeout=10) + response_stream = requests.get(response_api.url, stream=True) + + if args.onlinestream : + if response_stream.status_code != 200 : + return + return response_stream.url # This is the final resolved stream URL + except Exception as e: print(f"[ERROR] Couldn't resolve URL for {rg_proxy_url}: {e}") return rg_proxy_url # fallback to original @@ -46,7 +54,7 @@ def get_stream_url(station_id): def m3u(stations): - f = open('radio.m3u','a', encoding='utf-8') + f = open('d:/radio.m3u','a', encoding='utf-8') # if the file is empty, write the header if os.path.getsize("radio.m3u") == 0: @@ -60,7 +68,7 @@ def m3u(stations): f.close() def main(): - open('radio.m3u', 'w').close() + open('d:/radio.m3u', 'w').close() if not args.state: places = get_places() for place in places: From cfbc9a0e44af9c88fde1e42aa63c89fa6e1bfa6e Mon Sep 17 00:00:00 2001 From: sebastien durand <101456991+sebastiendurand78@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:42:31 +0100 Subject: [PATCH 3/4] reversed D:/ --- main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 1823384..ba6889d 100644 --- a/main.py +++ b/main.py @@ -54,7 +54,7 @@ def get_stream_url(station_id): def m3u(stations): - f = open('d:/radio.m3u','a', encoding='utf-8') + f = open('radio.m3u','a', encoding='utf-8') # if the file is empty, write the header if os.path.getsize("radio.m3u") == 0: @@ -68,7 +68,7 @@ def m3u(stations): f.close() def main(): - open('d:/radio.m3u', 'w').close() + open('radio.m3u', 'w').close() if not args.state: places = get_places() for place in places: From e41ecdb99a1be1d15bf924f5650f08428f43e60c Mon Sep 17 00:00:00 2001 From: sebastien durand <101456991+sebastiendurand78@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:48:34 +0100 Subject: [PATCH 4/4] bollean flag argument --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index ba6889d..bd4fa61 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,7 @@ parser = argparse.ArgumentParser( parser.add_argument('--country', help='Country name', type=str, required=True) parser.add_argument('--state', help='State or province name', type=str, required=False) -parser.add_argument('--onlinestream', help='Only working stream w. response 200.', type=str, required=False) +parser.add_argument('--onlinestream', help='Only include working streams (status 200)', action='store_true') args = parser.parse_args()