From 5a859323a5454bd56e83199e3a043148d7a0e34e Mon Sep 17 00:00:00 2001 From: Pari Malam Date: Sat, 27 Jun 2026 10:13:14 +0800 Subject: [PATCH] released v1.3.5 --- src/RunMe.sh | 40 +++++---- src/modules/generate_orig_urls.py | 135 ++++++++++++++++++++++++++++ src/{o11.cfg => test_providers.cfg} | 26 +++--- 3 files changed, 171 insertions(+), 30 deletions(-) create mode 100644 src/modules/generate_orig_urls.py rename src/{o11.cfg => test_providers.cfg} (98%) diff --git a/src/RunMe.sh b/src/RunMe.sh index a8da23a..1a9ff9d 100644 --- a/src/RunMe.sh +++ b/src/RunMe.sh @@ -57,8 +57,8 @@ GOMEMLIMIT="${GOMEMLIMIT:-2GiB}" KEEP_FALSE=true MAX_STREAMS="${MAX_STREAMS:-0}" HTTPS="${HTTPS:-false}" -ADMIN_USER="${ADMIN_USER:-}" -ADMIN_PASS="${ADMIN_PASS:-}" +ADMIN_USER="${ADMIN_USER:-admin}" +ADMIN_PASS="${ADMIN_PASS:-admin1337}" # Working directory (where binary and configs live) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -213,9 +213,7 @@ if [ "$MONITOR" = "true" ]; then echo " Audit log: logs/audit.log" echo " Alert log: logs/audit_alerts.log" fi -echo " (use 127.0.0.1 instead of 127.0.0.1 in your browser)" -echo "" -echo "Login: admin / " +echo ".++===========================================================================================++." echo "" # FIX: Unified background PID tracking + cleanup (replaces separate handlers) @@ -250,7 +248,7 @@ if [ "$MONITOR" = "true" ] || [ "$HLS_PROXY" = "true" ]; then while [ $_O11_TRIES -lt 30 ]; do _O11_TRIES=$((_O11_TRIES + 1)) if python3 -c "import socket; s=socket.socket(); s.settimeout(1); s.connect(('127.0.0.1',$PORT)); s.close()" 2>/dev/null; then - echo "o11pro is ready" + echo ".++===========================================================================================++." break fi if [ $_O11_TRIES -eq 30 ]; then @@ -265,18 +263,26 @@ if [ "$MONITOR" = "true" ] || [ "$HLS_PROXY" = "true" ]; then if [ "$HLS_PROXY" = "true" ]; then if [ ! -f "modules/hls_proxy.py" ]; then echo "WARNING: modules/hls_proxy.py not found skipping HLS proxy" - elif [ ! -f "$HLS_PROXY_CONFIG" ]; then - echo "WARNING: HLS proxy config not found at $HLS_PROXY_CONFIG skipping HLS proxy" - echo " Run setup.sh to auto-generate it from provider config" else - echo "Starting HLS Proxy on port $HLS_PROXY_PORT..." - python3 modules/hls_proxy.py \ - --config "$HLS_PROXY_CONFIG" \ - --port "$HLS_PROXY_PORT" \ - --bind "$HLS_PROXY_BIND" & - HLS_PID=$! - _BG_PIDS="$_BG_PIDS $HLS_PID" - echo "HLS Proxy started (PID $HLS_PID)" + # Auto-generate orig_urls.json from provider .cfg files + if [ -f "modules/generate_orig_urls.py" ]; then + echo "Generating HLS proxy config from providers..." + python3 modules/generate_orig_urls.py \ + --dir "$PROJECT_ROOT/providers" \ + --output "$HLS_PROXY_CONFIG" || true + fi + if [ ! -f "$HLS_PROXY_CONFIG" ]; then + echo "WARNING: HLS proxy config not found at $HLS_PROXY_CONFIG skipping HLS proxy" + else + echo "Starting HLS Proxy on port $HLS_PROXY_PORT..." + python3 modules/hls_proxy.py \ + --config "$HLS_PROXY_CONFIG" \ + --port "$HLS_PROXY_PORT" \ + --bind "$HLS_PROXY_BIND" & + HLS_PID=$! + _BG_PIDS="$_BG_PIDS $HLS_PID" + echo "HLS Proxy started (PID $HLS_PID)" + fi fi fi diff --git a/src/modules/generate_orig_urls.py b/src/modules/generate_orig_urls.py new file mode 100644 index 0000000..b8543e3 --- /dev/null +++ b/src/modules/generate_orig_urls.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +"""Scan provider .cfg files and generate cache/orig_urls.json for HLS proxy. + +Usage: + python3 generate_orig_urls.py + python3 generate_orig_urls.py --dir ../providers (custom provider dir) + python3 generate_orig_urls.py --output ../../cache/orig_urls.json +""" +import json +import os +import sys +import glob +import argparse + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +PROJECT_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, '..', '..')) +DEFAULT_PROVIDERS_DIR = os.path.join(PROJECT_DIR, 'providers') +DEFAULT_OUTPUT = os.path.join(PROJECT_DIR, 'cache', 'orig_urls.json') + +HLS_OUTPUT_MODES = {'directhls', 'hls', 'hlsts', 'hlsfmp4'} +HLS_RUNNING_MODES = {'internalremuxer', 'hls'} + +def find_cfg_files(providers_dir): + if not os.path.isdir(providers_dir): + return [] + return glob.glob(os.path.join(providers_dir, '*.cfg')) + +def extract_hls_streams(cfg_path): + try: + with open(cfg_path) as f: + data = json.load(f) + except (json.JSONDecodeError, OSError) as e: + print(f' SKIP: {os.path.basename(cfg_path)} parse error: {e}', file=sys.stderr) + return [] + + streams = [] + provider_name = data.get('Name', os.path.splitext(os.path.basename(cfg_path))[0]) + + # Check if this provider is HLS-capable + output_mode = data.get('OutputMode', '') + running_mode = data.get('RunningMode', '') + + for s in data.get('Streams', []): + manifest = s.get('Manifest', '') + if not manifest: + continue + + # Determine if stream is HLS — check OutputMode, RunningMode, or manifest URL + stream_output = s.get('OutputMode', output_mode) + stream_running = s.get('RunningMode', running_mode) + is_hls = ( + stream_output.lower() in HLS_OUTPUT_MODES + or stream_running.lower() in HLS_RUNNING_MODES + or '.m3u8' in manifest.lower() + ) + if not is_hls: + continue + + name = s.get('Name', '').strip() + if not name: + continue + + # Check for auth params + auth = None + script_user = s.get('ScriptAccountsUser', '') + script_params = s.get('ScriptParams', '') + if script_user and script_params and ':' in script_params: + parts = script_params.split() + for p in parts: + if ':' in p and not p.startswith('-'): + auth = p.split(':', 1) + break + + streams.append({ + 'name': name, + 'url': manifest, + 'auth': auth, + 'provider': provider_name, + }) + + return streams + +def generate(providers_dir, output_path): + cfg_files = find_cfg_files(providers_dir) + + if not cfg_files: + print(f'No .cfg files found in {providers_dir}') + print('Providers directory will be created at runtime by RunMe.sh') + return False + + all_streams = [] + for path in sorted(cfg_files): + streams = extract_hls_streams(path) + if streams: + all_streams.extend(streams) + print(f' {os.path.basename(path)}: {len(streams)} HLS streams') + + if not all_streams: + print('No HLS streams found in any config files') + return False + + # Build the output map + channel_map = {} + for s in all_streams: + if s['auth']: + channel_map[s['name']] = { + 'url': s['url'], + 'auth': s['auth'] + } + else: + channel_map[s['name']] = s['url'] + + os.makedirs(os.path.dirname(output_path), exist_ok=True) + with open(output_path, 'w') as f: + json.dump(channel_map, f, indent=2, ensure_ascii=False) + + print(f'\nGenerated {len(channel_map)} channels -> {output_path}') + return True + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Generate orig_urls.json for HLS proxy from provider .cfg files') + parser.add_argument('--dir', default=DEFAULT_PROVIDERS_DIR, + help=f'Provider configs directory (default: {DEFAULT_PROVIDERS_DIR})') + parser.add_argument('--output', default=DEFAULT_OUTPUT, + help=f'Output path (default: {DEFAULT_OUTPUT})') + args = parser.parse_args() + + print(f'Providers dir: {args.dir}') + print(f'Output: {args.output}') + print() + success = generate(args.dir, args.output) + if not success: + print('\nTip: place .cfg provider files in the providers/ directory and re-run') + sys.exit(1) diff --git a/src/o11.cfg b/src/test_providers.cfg similarity index 98% rename from src/o11.cfg rename to src/test_providers.cfg index cc2706b..3d40e5d 100644 --- a/src/o11.cfg +++ b/src/test_providers.cfg @@ -672,11 +672,11 @@ "Video": "", "Audio": "", "Subtitles": "", - "VideoList": null, - "AudioList": null, - "SubtitlesList": null, + "VideoList": [], + "AudioList": [], + "SubtitlesList": [], "IgnoreKid": false, - "Keys": null, + "Keys": [], "Drm": { "Vendor": null }, @@ -768,11 +768,11 @@ "Video": "", "Audio": "", "Subtitles": "", - "VideoList": null, - "AudioList": null, - "SubtitlesList": null, + "VideoList": [], + "AudioList": [], + "SubtitlesList": [], "IgnoreKid": false, - "Keys": null, + "Keys": [], "Drm": { "Vendor": null }, @@ -864,11 +864,11 @@ "Video": "", "Audio": "", "Subtitles": "", - "VideoList": null, - "AudioList": null, - "SubtitlesList": null, + "VideoList": [], + "AudioList": [], + "SubtitlesList": [], "IgnoreKid": false, - "Keys": null, + "Keys": [], "Drm": { "Vendor": null }, @@ -994,7 +994,7 @@ ], "SubtitlesList": [], "IgnoreKid": false, - "Keys": null, + "Keys": [], "Drm": { "Vendor": null },