DaddyLiveHD 2026 [Updated 6-29-2026]

This is an example playlist, this will work after you start the app , it won`t work if you can`t open this link You do not have permission to view the full content of this post. Log in or register now.

Code:
#EXTM3U
# Part 3 of 7 (streams 401 to 600)
#EXTINF:-1 group-title="DLHD 24/7",Astro Cricket
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D370&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Antena 3 Spain
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D531&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sports Tenis Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D612&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",ACC Network USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D664&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",ãdül† Swim
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D295&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",A Sport PK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D269&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",AXN Movies Portugal
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D717&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arte DE
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D725&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",AXS TV USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D742&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",ABC NY USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D766&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Azteca 7 MX
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D844&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Altitude Sports
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D923&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Azteca Uno MX
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D934&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 5 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D940&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 6 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D941&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 7 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D942&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 8 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D943&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 9 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D944&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 10 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D945&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Arte France
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D958&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Automoto La chaîne
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D961&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Barca TV Spain
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D522&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Benfica TV PT
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D380&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Boomerang
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D648&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BNT 1 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D476&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BNT 2 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D477&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BNT 3 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D478&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BR Fernsehen DE
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D737&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",bTV Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D479&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",bTV Action Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D481&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",bTV Lady Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D484&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC America (BBCA)
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D305&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BET USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D306&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Bravo USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D307&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC News Channel HD
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D349&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC One UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D356&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC Two UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D357&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC Three UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D358&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BBC Four UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D359&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BIG TEN Network (BTN USA)
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D397&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",BFM TV France
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D957&redirect_stream=true

#EXTINF:-1 group-title="DLHD 24/7",Bandsports Brasil
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D275&redirect_stream=true

If a stream does not work and you try to open it for a while, you will get rate-limited for 5 minutes or so and won`t be able to open dlhd.pk site. System will lock you out for 5 minutes or so.
 
Here is a Python script to convert from the main m3u8 file to EasyProxy format

Code:
#!/usr/bin/env python3
"""
convert_m3u8.py

Converts an M3U8 playlist from DaddyLiveHD to the local extractor format.
Usage:
    python convert_m3u8.py [input_file_or_url] [output_file]

If no input is given, reads from stdin.
If no output is given, prints to stdout.
"""

import sys
import re
import urllib.parse
from urllib.request import urlopen
from urllib.error import URLError

PROXY_BASE = "http://127.0.0.1:7860/extractor/video.m3u8"
HOST = "dlstreams"
REDIRECT = "true"

def convert_url(original_url):
    """Convert a dlhd.pk watch URL to the local proxy URL."""
    # URL-encode the original URL for the 'd' parameter
    encoded_d = urllib.parse.quote(original_url, safe='')
    return f"{PROXY_BASE}?host={HOST}&d={encoded_d}&redirect_stream={REDIRECT}"

def process_m3u8(content):
    """Process each line of the M3U8 content."""
    lines = content.splitlines()
    out_lines = []
    # Pattern to match the original stream URLs exactly
    # We'll look for lines that are only the URL (no extra text)
    # Typically in M3U8, URLs appear on their own line, but sometimes they might have whitespace.
    # We'll match lines that start with http:// or https:// and contain dlhd.pk/watch.php
    url_pattern = re.compile(r'^https?://dlhd\.pk/watch\.php\?id=\d+$')
    for line in lines:
        stripped = line.strip()
        if url_pattern.match(stripped):
            # Replace with the converted URL
            out_lines.append(convert_url(stripped))
        else:
            out_lines.append(line)
    return "\n".join(out_lines)

def read_input(source):
    """Read content from a file path, URL, or stdin."""
    if source is None:
        # Read from stdin
        return sys.stdin.read()
    # Check if it's a URL (starts with http:// or https://)
    if source.startswith(('http://', 'https://')):
        try:
            with urlopen(source) as response:
                return response.read().decode('utf-8')
        except URLError as e:
            sys.stderr.write(f"Error fetching URL: {e}\n")
            sys.exit(1)
    else:
        # Treat as local file
        try:
            with open(source, 'r', encoding='utf-8') as f:
                return f.read()
        except FileNotFoundError as e:
            sys.stderr.write(f"File not found: {e}\n")
            sys.exit(1)

def main():
    input_source = None
    output_file = None
    # Parse command line arguments
    args = sys.argv[1:]
    if len(args) >= 1:
        input_source = args[0]
    if len(args) >= 2:
        output_file = args[1]
    
    content = read_input(input_source)
    converted = process_m3u8(content)
    
    if output_file:
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(converted)
    else:
        sys.stdout.write(converted)

if __name__ == "__main__":
    main()


You can name it convert_m3u8.py

# From a local file
python convert_m3u8.py dlhd.m3u8 converted.m3u8

# From a URL (e.g., the GitHub raw URL)
python convert_m3u8.py You do not have permission to view the full content of this post. Log in or register now. output.m3u8

# Pipe from curl
curl -s You do not have permission to view the full content of this post. Log in or register now. | python convert_m3u8.py > output.m3u8
 
Code:
#!/usr/bin/env python3
"""
create_dlhd_playlist.py - Scrape dlhd.pk channels with rate-limit protection.
"""

import re
import sys
import time
import random
import requests
from datetime import datetime
from urllib.parse import urljoin, urlparse, parse_qs

# ---------- CONFIGURATION ----------
BASE_URL = "https://dlhd.pk"
MAX_CHANNELS = None          # Set to integer to limit, e.g., 50
REQUEST_DELAY_MIN = 4.0      # Minimum seconds between requests
REQUEST_DELAY_MAX = 8.0      # Maximum seconds between requests
MAX_RETRIES = 5              # Retry attempts for a single URL
BACKOFF_FACTOR = 2           # Exponential backoff multiplier
# -----------------------------------

# Rotating user agents
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
]

def get_headers():
    """Return headers with a random User-Agent."""
    return {
        "User-Agent": random.choice(USER_AGENTS),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
    }

def fetch_with_retries(session, url, retries=MAX_RETRIES, delay=1):
    """
    Fetch a URL with exponential backoff and jitter.
    Returns HTML string or None on persistent failure.
    """
    headers = get_headers()
    for attempt in range(1, retries + 1):
        try:
            resp = session.get(url, headers=headers, timeout=15)
            resp.raise_for_status()
            return resp.text
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
            if attempt == retries:
                print(f"  [!] Failed after {retries} attempts: {e}")
                return None
            # Exponential backoff with jitter
            sleep_time = (delay * (BACKOFF_FACTOR ** (attempt - 1))) + random.uniform(0, 1)
            print(f"  [Retry {attempt}/{retries}] Connection issue, waiting {sleep_time:.1f}s...")
            time.sleep(sleep_time)
        except requests.exceptions.RequestException as e:
            # Non-retryable error (e.g., 404)
            print(f"  [!] Request error: {e}")
            return None
    return None

def extract_watch_links(html, base_url):
    """
    Extract all watch.php?id=... links from HTML.
    Returns a list of (channel_id, channel_name, full_url) tuples.
    """
    links = set()
    pattern = r'href\s*=\s*["\']([^"\']*watch\.php[^"\']*)["\']'
    for match in re.finditer(pattern, html, re.IGNORECASE):
        raw_url = match.group(1)
        full_url = urljoin(base_url, raw_url)
        parsed = urlparse(full_url)
        params = parse_qs(parsed.query)
        if 'id' in params:
            cid = params['id'][0]
            links.add((cid, f"Channel {cid}", full_url))
    return list(links)

def get_channel_name(html, default_id):
    """Extract channel name from <title> tag."""
    match = re.search(r'<title>(.*?)</title>', html, re.IGNORECASE | re.DOTALL)
    if match:
        title = match.group(1).strip()
        title = re.sub(r'\s*[-|]\s*dlhd\..*$', '', title, flags=re.IGNORECASE)
        title = re.sub(r'\s*[-|]\s*Watch\s*.*$', '', title, flags=re.IGNORECASE)
        if title:
            return title
    return f"Channel_{default_id}"

def build_m3u8_playlist(channel_data):
    """Build M3U8 content from list of (name, url) tuples."""
    lines = ["#EXTM3U"]
    for name, url in channel_data:
        clean_name = re.sub(r'\s+', ' ', name).strip()
        lines.append(f'#EXTINF:-1,{clean_name}')
        lines.append(url)
    return "\n".join(lines)

def main():
    print("=" * 60)
    print("dlhd.pk - Generate M3U8 Playlist (Rate-Limit Protected)")
    print("=" * 60)

    # Use a session for connection reuse
    session = requests.Session()
    session.headers.update(get_headers())

    # Step 1: Fetch main page
    print(f"\n[1] Fetching main page: {BASE_URL}")
    main_html = fetch_with_retries(session, BASE_URL)
    if not main_html:
        print("Failed to fetch main page. Exiting.")
        sys.exit(1)

    # Step 2: Extract watch.php links
    print("[2] Extracting watch.php?id= links...")
    channels = extract_watch_links(main_html, BASE_URL)

    # Try alternative paths if needed
    if not channels:
        for path in ["/channels.php", "/index.php", "/home"]:
            alt_url = urljoin(BASE_URL, path)
            alt_html = fetch_with_retries(session, alt_url)
            if alt_html:
                channels = extract_watch_links(alt_html, alt_url)
                if channels:
                    break

    if not channels:
        print("No watch.php links found. Site structure may have changed.")
        sys.exit(1)

    # Remove duplicates by id
    seen = set()
    unique = []
    for cid, name, url in channels:
        if cid not in seen:
            seen.add(cid)
            unique.append((cid, name, url))

    print(f"[+] Found {len(unique)} unique channel(s).")
    if MAX_CHANNELS and len(unique) > MAX_CHANNELS:
        print(f"[!] Limiting to first {MAX_CHANNELS}.")
        unique = unique[:MAX_CHANNELS]

    # Step 3: Fetch each channel page for the title
    print("\n[3] Fetching channel titles (with delays to avoid rate-limit)...")
    channel_data = []  # (name, watch_url)
    total = len(unique)
    for idx, (cid, _, url) in enumerate(unique, 1):
        print(f"  [{idx}/{total}] ID {cid} ... ", end="", flush=True)
        # Add random delay before each request (except maybe first)
        if idx > 1:
            delay = random.uniform(REQUEST_DELAY_MIN, REQUEST_DELAY_MAX)
            time.sleep(delay)

        page_html = fetch_with_retries(session, url)
        if page_html:
            name = get_channel_name(page_html, cid)
            channel_data.append((name, url))
            print("OK")
        else:
            # Fallback to generic name
            channel_data.append((f"Channel_{cid}", url))
            print("FAIL (using default name)")

    # Step 4: Build and save playlist
    print("\n[4] Building M3U8 playlist...")
    playlist = build_m3u8_playlist(channel_data)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"dlhd_playlist_{timestamp}.m3u8"
    with open(filename, "w", encoding="utf-8") as f:
        f.write(playlist)

    print(f"\n[+] Playlist saved to: {filename}")
    print(f"    Total entries: {len(channel_data)}")
    print("\nDone.")

if __name__ == "__main__":
    main()

Here is another script to fetch updated channels from dlhd.pk in case the ids for the channel change, this also includes the events but event names and some channel names would be missing, could not fix it yet.
 
Thanks a lot st1905 you are a great person and thank you Metroid
You are welcome, Here is a script, which will fetch the events and 7/24 channels with proper names
Code:
#!/usr/bin/env python3
"""
dlhd_combined.py - Scrape dlhd.st (events) + dlhd.st/24-7-channels.php (permanent channels)
and generate a combined M3U8 playlist.
"""

import re
import sys
import time
import random
import requests
from datetime import datetime
from urllib.parse import urljoin, urlparse, parse_qs

try:
    from bs4 import BeautifulSoup
except ImportError:
    print("Install beautifulsoup4: pip install beautifulsoup4")
    sys.exit(1)

# ---------- CONFIG ----------
MAIN_URL = "https://dlhd.st"                # main page with events
CHANNELS_247_URL = "https://dlhd.st/24-7-channels.php"   # 24/7 channels
MAX_CHANNELS = None          # set to e.g., 100 to limit total entries
REQUEST_DELAY = 1.0          # seconds between page-title fetches (if used)
MAX_RETRIES = 3
# ---------------------------

USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
]

def get_headers():
    return {"User-Agent": random.choice(USER_AGENTS),
            "Accept": "text/html,application/xhtml+xml",
            "Accept-Language": "en-US,en;q=0.5"}

def fetch_url(session, url, retries=MAX_RETRIES):
    for attempt in range(1, retries+1):
        try:
            resp = session.get(url, headers=get_headers(), timeout=15)
            resp.raise_for_status()
            return resp.text
        except:
            if attempt == retries:
                return None
            time.sleep(2 ** attempt + random.uniform(0,1))
    return None

def is_generic(name):
    """Return True if name is likely generic (e.g., 'Tennis Stream')"""
    name_lower = name.lower().strip()
    generic_terms = {"tennis stream", "football stream", "basketball stream", "cricket stream",
                     "live stream", "watch", "stream", "channel", "sport", "event"}
    for term in generic_terms:
        if term in name_lower:
            return True
    if ' vs ' in name_lower or ':' in name or any(ord(c) > 0x1F000 for c in name):
        return False
    if len(name) < 8:
        return True
    return False

def extract_event_name_from_schedule_event(container, channel_name):
    """Extract event name from schedule__event container (used on main page)."""
    header = container.find('div', class_=re.compile(r'schedule__eventHeader', re.I))
    if header:
        data_title = header.get('data-title')
        if data_title:
            cleaned = re.sub(r'^\d{1,2}:\d{2}\s*', '', data_title)
            cleaned = re.sub(r'\s*' + re.escape(channel_name) + r'\s*$', '', cleaned, flags=re.I)
            return cleaned.strip()
        header_text = header.get_text(separator=' ', strip=True)
        header_text = re.sub(r'^\d{1,2}:\d{2}\s*', '', header_text)
        header_text = re.sub(r'\s*' + re.escape(channel_name) + r'\s*$', '', header_text, flags=re.I)
        return header_text.strip()
    full_text = container.get_text(separator=' ', strip=True)
    full_text = re.sub(r'\s*' + re.escape(channel_name) + r'\s*', '', full_text, flags=re.I)
    full_text = re.sub(r'\b\d{1,2}:\d{2}\b\s*', '', full_text)
    return full_text.strip()

def extract_channels_from_page(html, base_url, is_247=False):
    """
    Extract all watch.php links with best possible names.
    If is_247=True, we assume the page is the 24/7 channels page,
    where the names are likely the anchor text or title attribute.
    """
    soup = BeautifulSoup(html, 'html.parser')
    channels = []
    for a in soup.find_all('a', href=True):
        href = a['href']
        if 'watch.php' not in href:
            continue
        full_url = urljoin(base_url, href)
        parsed = urlparse(full_url)
        params = parse_qs(parsed.query)
        if 'id' not in params:
            continue
        cid = params['id'][0]
        # For 24/7 page, just take the anchor text or title
        if is_247:
            name = a.get('title')
            if not name:
                name = a.get_text(strip=True)
            if not name:
                name = f"Channel {cid}"
            channels.append((cid, name, full_url))
            continue
        # Otherwise, use the event-extraction logic (for main page)
        # Try to find a schedule__event ancestor
        container = a
        found_event = False
        for _ in range(6):
            if container and container.name == 'div' and container.get('class') and 'schedule__event' in container.get('class'):
                found_event = True
                break
            container = container.parent
        if found_event:
            channel_name = a.get_text(strip=True) or f"Channel {cid}"
            event_name = extract_event_name_from_schedule_event(container, channel_name)
            if not event_name:
                event_name = channel_name
        else:
            # Fallback: use title or text
            title_attr = a.get('title')
            if title_attr:
                event_name = title_attr.strip()
            else:
                event_name = a.get_text(strip=True)
            if not event_name:
                event_name = f"Channel {cid}"
        channels.append((cid, event_name, full_url))
    return channels

def get_page_title(session, url):
    """Fallback: fetch page title if needed (not used in this combined version)."""
    # We'll keep it for completeness, but we won't call it by default.
    pass

def main():
    print("=" * 60)
    print("dlhd.st - Combined: Events + 24/7 Channels")
    print("=" * 60)

    session = requests.Session()
    session.headers.update(get_headers())

    # 1. Scrape main page (events)
    print(f"\n[1] Fetching main page: {MAIN_URL}")
    main_html = fetch_url(session, MAIN_URL)
    channels = []
    if main_html:
        print("[2] Extracting event channels...")
        channels += extract_channels_from_page(main_html, MAIN_URL, is_247=False)
    else:
        print("Warning: Could not fetch main page.")

    # 2. Scrape 24/7 channels page
    print(f"\n[3] Fetching 24/7 channels page: {CHANNELS_247_URL}")
    channels_247_html = fetch_url(session, CHANNELS_247_URL)
    if channels_247_html:
        print("[4] Extracting 24/7 channels...")
        channels += extract_channels_from_page(channels_247_html, CHANNELS_247_URL, is_247=True)
    else:
        print("Warning: Could not fetch 24/7 channels page.")

    if not channels:
        print("No channels found from either source. Exiting.")
        sys.exit(1)

    # Deduplicate by id (keep first occurrence, which usually has better name)
    seen = set()
    unique = []
    for cid, name, url in channels:
        if cid not in seen:
            seen.add(cid)
            unique.append((cid, name, url))

    print(f"[+] Found {len(unique)} unique channels (after merging).")
    if MAX_CHANNELS and len(unique) > MAX_CHANNELS:
        unique = unique[:MAX_CHANNELS]
        print(f"[!] Limiting to {MAX_CHANNELS}.")

    # (Optional) Refine generic names by fetching page titles – disabled for speed.
    # If you want to enable, uncomment the loop below.
    refined = []
    for cid, name, url in unique:
        # Simple cleanup
        clean_name = re.sub(r'\s+', ' ', name).strip()
        refined.append((clean_name, url))

    # Build playlist
    print("\n[5] Generating M3U8 playlist...")
    m3u = ["#EXTM3U"]
    for name, url in refined:
        m3u.append(f'#EXTINF:-1,{name}')
        m3u.append(url)

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"dlhd_combined_{timestamp}.m3u8"
    with open(filename, "w", encoding="utf-8") as f:
        f.write("\n".join(m3u))

    print(f"\n[+] Playlist saved to: {filename}")
    print(f"    Total entries: {len(refined)}")
    print("Done.")

if __name__ == "__main__":
    main()

dlhd.pk is now You do not have permission to view the full content of this post. Log in or register now.
 
Thanks for the info! Now I have to update the channels.
If you can automate it in the repo, it would be great, maybe with huggingface or github actions, dlhd_combined.py now fetches all events and 7/24 streams together.

This is an example playlist which includes everything for EasyProxy format. You do not have permission to view the full content of this post. Log in or register now.
 
If you can automate it in the repo, it would be great, maybe with huggingface or github actions, dlhd_combined.py now fetches all events and 7/24 streams together.

This is an example playlist which includes everything for EasyProxy format. You do not have permission to view the full content of this post. Log in or register now.
pwede ba sya sa ott?
Streamable not reachable daw
 

About this Thread

  • 19
    Replies
  • 455
    Views
  • 8
    Participants
Last reply from:
nodge

Online now

Members online
1,267
Guests online
2,034
Total visitors
3,301

Forum statistics

Threads
2,286,250
Posts
29,036,609
Members
1,217,847
Latest member
19drk
Back
Top