fix(source): handle missing 4KHDHub episodes more gracefully

This commit is contained in:
WebStreamr 2025-09-08 09:01:49 +00:00
parent 6577eda289
commit c2983f0551
No known key found for this signature in database
8 changed files with 3641 additions and 6 deletions

View file

@ -50,4 +50,9 @@ describe('FourKHDHub', () => {
const streams = await source.handle(ctx, 'movie', new TmdbId(1948, undefined, undefined));
expect(streams).toMatchSnapshot();
});
test('handle lovely runner 2024 s01e01', async () => {
const streams = await source.handle(ctx, 'series', new TmdbId(230923, 1, 1));
expect(streams).toMatchSnapshot();
});
});

View file

@ -42,13 +42,14 @@ export class FourKHDHub extends Source {
return Promise.all(
$(`.episode-item`)
.filter((_i, el) => $('.episode-title', el).text().includes(`S${String(tmdbId.season).padStart(2, '0')}`))
.map(async (_i, el) => {
const downloadItemEl = $('.episode-download-item', el)
.map((_i, el) => ({
countryCodes: findCountryCodes($(el).html() as string),
downloadItem: $('.episode-download-item', el)
.filter((_i, el) => $(el).text().includes(`Episode-${String(tmdbId.episode).padStart(2, '0')}`))
.get(0);
return await this.extractSourceResults(ctx, $, downloadItemEl as BasicAcceptedElems<AnyNode>, findCountryCodes($(el).html() as string));
}).toArray(),
.get(0),
})).filter((_i, { downloadItem }) => downloadItem !== undefined)
.map(async (_id, { countryCodes, downloadItem }) => await this.extractSourceResults(ctx, $, downloadItem as BasicAcceptedElems<AnyNode>, countryCodes))
.toArray(),
);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,722 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>4KHDHub - High Quality Movies and TV Shows</title>
<script>
!function(){try{"light"===localStorage.getItem("theme")?(document.documentElement.classList.remove("dark"),document.documentElement.classList.add("light")):(document.documentElement.classList.add("dark"),document.documentElement.classList.remove("light"))}catch(e){console.error("Theme initialization failed:",e)}}();
</script>
<meta name="description" content="Download high quality movies and TV shows in UHD, 4K HDR, 1080p and more formats">
<!-- Font -->
<!-- Preload the logo -->
<link rel="preload" href="/images/4KHDHUB-Dark-Logo.png" as="image" type="image/png" />
<link rel="preload" href="/images/4KHDHUB-Bright-Logo.png" as="image" type="image/png" />
<!-- Theme script to prevent flash -->
<!-- Link to Google Fonts Stylesheets -->
<style type="text/css">@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/greek/400/normal.woff2);unicode-range:U+0370-03FF;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/cyrillic-ext/400/normal.woff2);unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/greek-ext/400/normal.woff2);unicode-range:U+1F00-1FFF;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/latin/400/normal.woff2);unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/hebrew/400/normal.woff2);unicode-range:U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/cyrillic/400/normal.woff2);unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/latin-ext/400/normal.woff2);unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF;font-display:swap;}@font-face {font-family:Open Sans;font-style:normal;font-weight:400;src:url(/cf-fonts/s/open-sans/5.0.20/vietnamese/400/normal.woff2);unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;font-display:swap;}</style>
<link href="https://fonts.cdnfonts.com/css/trebuchet-ms-2" rel="stylesheet">
<link rel="stylesheet" href="/css/styles.css?v=0.14.69c18">
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="4K-HDHub" />
<link rel="manifest" href="/site.webmanifest" />
<!-- JavaScript to apply font-display: swap -->
<script type="text/javascript">
!function(e,n,t){"use strict";var o="https://fonts.googleapis.com/css?family=Open+Sans",r="__3perf_googleFonts_5fd56";function c(e){(n.head||n.body).appendChild(e)}function a(){var e=n.createElement("link");e.href=o,e.rel="stylesheet",c(e)}function f(e){if(!n.getElementById(r)){var t=n.createElement("style");t.id=r,c(t)}n.getElementById(r).innerHTML=e}e.FontFace&&e.FontFace.prototype.hasOwnProperty("display")?(t[r]&&f(t[r]),fetch(o).then(function(e){return e.text()}).then(function(e){return e.replace(/@font-face {/g,"@font-face{font-display:swap;")}).then(function(e){return t[r]=e}).then(f).catch(a)):a()}(window,document,localStorage);
</script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LL0RL7VX47"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LL0RL7VX47');
</script>
</head>
<body>
<div class="flex min-h-screen flex-col">
<!-- Header -->
<!-- Header with truly unified navigation -->
<header class="sticky top-0 z-50 w-full">
<div class="header">
<div class="container flex h-14 items-center justify-between">
<!-- Logo and mobile menu toggle -->
<div class="flex items-center">
<button id="menu-toggle" class="menu-toggle md:hidden">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
<span class="sr-only">Toggle menu</span>
</button>
<a href="/" class="navbar-brand">
<img id="logo" class="h-8 w-auto" src="/images/4KHDHUB-Bright-Logo.png" alt="4KHDHub logo">
</a>
</div>
<!-- SINGLE Navigation - Visible on desktop, hidden on mobile -->
<nav id="main-nav" class="main-nav">
<ul class="nav-list">
<li class="nav-item"><a href="/" class="nav-link">Home</a></li>
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle">
Movies
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="dropdown-indicator h-4 w-4">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</a>
<ul class="dropdown-menu">
<li><a href="/category/new-movies-10810.html" class="dropdown-item">Latest Movies</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle">
Web Series
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="dropdown-indicator h-4 w-4">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</a>
<ul class="dropdown-menu">
<li><a href="/category/new-series-10811.html" class="dropdown-item">Latest Episodes</a></li>
</ul>
</li>
<li class="nav-item"><a href="/category/anime-10812.html" class="nav-link">Anime</a></li>
<li class="nav-item"><a href="/category/4k-hdr-10776.html" class="nav-link">4K HDR</a></li>
</ul>
</nav>
<!-- Search and Theme Toggle -->
<div class="flex items-center">
<button id="search-toggle" class="search-toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<span class="sr-only">Search</span>
</button>
<div class="search-container hidden md:flex">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="search-icon h-4 w-4">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
for
<input type="search" id="search" placeholder="Search movies & series" class="search-input">
</div>
<button id="theme-toggle" class="theme-toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="theme-icon h-5 w-5">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
<span class="sr-only">Toggle theme</span>
</button>
</div>
</div>
</div>
<!-- Mobile Menu Backdrop (only shown when menu is open) -->
<div id="mobile-menu-backdrop" class="fixed inset-0 bg-black/70 hidden"></div>
<!-- Close button for mobile menu (only shown when menu is open) -->
<button id="close-mobile-menu" class="fixed top-4 right-4 p-2 rounded-full z-[60] hidden">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<!-- Search Overlay -->
<div id="search-overlay" class="fixed inset-0 z-50 hidden">
<div class="fixed" id="search-backdrop"></div>
<button id="close-search" class="absolute right-4 top-4 p-2 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
<span class="sr-only">Close</span>
</button>
<form action="/" method="get" class="search-form">
<div class="search-input-container">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="search-icon-overlay">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="search" name="s" placeholder="Search Movies & TV-Shows" class="search-input-overlay" autofocus autocomplete="off">
</div>
<button type="submit" class="search-submit">
Search
</button>
</form>
</div>
</header>
<!-- Main Content -->
<main class="flex-1">
<div class="container">
<section class="latest-releases">
<div class="latest-releases-header">
<h2 class="latest-releases-title">
<span><svg style="vertical-align: bottom;" xmlns="http://www.w3.org/2000/svg" height="32px" viewBox="0 -960 960 960" width="32px" fill="#e3e3e3"><path d="M240-400q0 52 21 98.5t60 81.5q-1-5-1-9v-9q0-32 12-60t35-51l113-111 113 111q23 23 35 51t12 60v9q0 4-1 9 39-35 60-81.5t21-98.5q0-50-18.5-94.5T648-574q-20 13-42 19.5t-45 6.5q-62 0-107.5-41T401-690q-39 33-69 68.5t-50.5 72Q261-513 250.5-475T240-400Zm240 52-57 56q-11 11-17 25t-6 29q0 32 23.5 55t56.5 23q33 0 56.5-23t23.5-55q0-16-6-29.5T537-292l-57-56Zm0-492v132q0 34 23.5 57t57.5 23q18 0 33.5-7.5T622-658l18-22q74 42 117 117t43 163q0 134-93 227T480-80q-134 0-227-93t-93-227q0-129 86.5-245T480-840Z"/></svg></span> Latest Releases </h2>
</div>
<div class="card-grid">
<!-- Movie Cards -->
<a href="/lovely-runner-series-3379.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/xJQyrif5M4UMoVBrBlwUabtaRxB.jpg" alt="Lovely Runner" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Amazon Prime Video</span>
<span class="movie-card-format">Comedy</span>
<span class="movie-card-format">Drama</span>
<span class="movie-card-format">Hindi</span>
<span class="movie-card-format">Korean</span>
<span class="movie-card-format">Music</span>
<span class="movie-card-format">Mystery</span>
<span class="movie-card-format">Romance</span>
<span class="movie-card-format">Sci-Fi & Fantasy</span>
<span class="movie-card-format">Series</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Lovely Runner</h3>
<p class="movie-card-meta">2024 • S01 </p>
</div>
</a>
<a href="/gunner-movie-2319.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/cS2TXN1YlrCvkZmMxaevC1ZKtEz.jpg" alt="Gunner" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">1080p</span>
<span class="movie-card-format">10Bit</span>
<span class="movie-card-format">Action</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Crime</span>
<span class="movie-card-format">Dual Language</span>
<span class="movie-card-format">REMUX</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Gunner</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<a href="/blade-runner-2049-movie-862.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/gajva2L0rPYkEWjzgFlBXCAVBE5.jpg" alt="Blade Runner 2049" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Drama</span>
<span class="movie-card-format">Science Fiction</span>
<span class="movie-card-format">Movies</span>
<span class="movie-card-format">1080p</span>
<span class="movie-card-format">2160p</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Dual Language</span>
<span class="movie-card-format">HDR</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Blade Runner 2049</h3>
<p class="movie-card-meta">2017 </p>
</div>
</a>
<a href="/the-maze-runner-movie-488.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/ode14q7WtDugFDp78fo9lCsmay9.jpg" alt="The Maze Runner" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Action</span>
<span class="movie-card-format">Mystery</span>
<span class="movie-card-format">Science Fiction</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<span class="movie-card-format">2160p</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Dual Language</span>
<span class="movie-card-format">HDR</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">The Maze Runner</h3>
<p class="movie-card-meta">2014 </p>
</div>
</a>
<a href="/lonely-enough-to-love-series-2682.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/6qhKb5e9olZJ5XilDBkOdZpGXKq.jpg" alt="Lonely Enough to Love!" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Comedy</span>
<span class="movie-card-format">Drama</span>
<span class="movie-card-format">Hindi</span>
<span class="movie-card-format">Romance</span>
<span class="movie-card-format">Series</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Lonely Enough to Love!</h3>
<p class="movie-card-meta">2020 • S01 </p>
</div>
</a>
<a href="/maze-runner-the-scorch-trials-movie-492.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/mYw7ZyejqSCPFlrT2jHZOESZDU3.jpg" alt="Maze Runner: The Scorch Trials" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Action</span>
<span class="movie-card-format">Adventure</span>
<span class="movie-card-format">Science Fiction</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<span class="movie-card-format">HDR</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Dual Language</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Maze Runner: The Scorch Trials</h3>
<p class="movie-card-meta">2015 </p>
</div>
</a>
<a href="/maze-runner-the-death-cure-movie-493.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/drbERzlA4cuRWhsTXfFOY4mRR4f.jpg" alt="Maze Runner: The Death Cure" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Action</span>
<span class="movie-card-format">Adventure</span>
<span class="movie-card-format">Science Fiction</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<span class="movie-card-format">2160p</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Dual Language</span>
<span class="movie-card-format">HDR</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Maze Runner: The Death Cure</h3>
<p class="movie-card-meta">2018 </p>
</div>
</a>
<a href="/rust-movie-564.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/4pRZulxWOr3iVKT5q2tVOWPCMA9.jpg" alt="Rust" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">1080p</span>
<span class="movie-card-format">2160p</span>
<span class="movie-card-format">WEB-DL</span>
<span class="movie-card-format">Western</span>
<span class="movie-card-format">Movies</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Rust</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<a href="/unstoppable-movie-625.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/xanYKxuFkDPrMngvm1NSHVGOEjS.jpg" alt="Unstoppable" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">1080p</span>
<span class="movie-card-format">2160p</span>
<span class="movie-card-format">HDR</span>
<span class="movie-card-format">DDP</span>
<span class="movie-card-format">Documentary</span>
<span class="movie-card-format">Drama</span>
<span class="movie-card-format">English</span>
<span class="movie-card-format">Hindi</span>
<span class="movie-card-format">History</span>
<span class="movie-card-format">Movies</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Unstoppable</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<a href="/survive-movie-321.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/7fR3KxswtY8OHHZuOUB9td58CRX.jpg" alt="Survive" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">1080p</span>
<span class="movie-card-format">10Bit</span>
<span class="movie-card-format">Action</span>
<span class="movie-card-format">Adventure</span>
<span class="movie-card-format">BluRay</span>
<span class="movie-card-format">Science Fiction</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Survive</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<a href="/absolution-movie-416.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/gt70JOD9xsPlpJnuBJAWdOT4yRg.jpg" alt="Absolution" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Action</span>
<span class="movie-card-format">Crime</span>
<span class="movie-card-format">DDP</span>
<span class="movie-card-format">English</span>
<span class="movie-card-format">Family</span>
<span class="movie-card-format">Hindi</span>
<span class="movie-card-format">Mystery</span>
<span class="movie-card-format">Thriller</span>
<span class="movie-card-format">Movies</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">Absolution</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<a href="/appu-movie-1377.html" class="movie-card">
<div class="movie-card-image">
<img src="https://image.tmdb.org/t/p/w500/5ocNGfKViLyvNv6m52lW0LVzU2Q.jpg" alt="APPU" class="w-full h-full object-cover">
<div class="movie-card-overlay">
<div class="movie-card-formats">
<span class="movie-card-format">Animation</span>
<span class="movie-card-format">Comedy</span>
<span class="movie-card-format">Drama</span>
<span class="movie-card-format">Family</span>
<span class="movie-card-format">Movies</span>
<span class="movie-card-format">Dual Language</span>
<span class="movie-card-format">WEB-DL</span>
<!--<span class="movie-card-format">HEVC</span>-->
</div>
</div>
</div>
<div class="movie-card-content">
<h3 class="movie-card-title">APPU</h3>
<p class="movie-card-meta">2024 </p>
</div>
</a>
<!--<a href="movie-static-movie.html" class="movie-card">-->
<!-- <div class="movie-card-image">-->
<!-- <img src="images/placeholder.svg" alt="Dune: Part Two" class="w-full h-full object-cover">-->
<!-- <div class="movie-card-overlay">-->
<!-- <div class="movie-card-formats">-->
<!-- <span class="movie-card-format">2160p</span>-->
<!-- <span class="movie-card-format">4K HDR</span>-->
<!-- <span class="movie-card-format">HEVC</span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="movie-card-content">-->
<!-- <h3 class="movie-card-title">Dune: Part Two</h3>-->
<!-- <p class="movie-card-meta">2024</p>-->
<!-- </div>-->
<!--</a>-->
</div>
</section>
<!-- Pagination -->
<div class="pagination-container">
<div class="pagination-container">
<div class="pagination">
<!-- Previous Page Link -->
<a class='pagination-item active'>1</a><a href='/page/2.html?s=Lovely Runner 2024' class='pagination-item'>2</a><a href='/page/140.html?s=Lovely Runner 2024' class='pagination-item'>140</a>
<!-- Next Page Link -->
<a href="/page/2.html?s=Lovely Runner 2024" class="pagination-item pagination-next">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</a>
</div>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="border-t bg-background">
<div class="container py-8 md:py-12">
<div class="grid grid-cols-1 gap-8 md:grid-cols-4 justify-center text-center md:text-left">
<div class="space-y-4">
<h3 class="text-lg font-semibold">4KHDHub</h3>
<p class="text-sm text-muted-foreground">
Your one-stop destination for high-quality movies and TV shows in various formats.
</p>
</div>
<!-- Quick Links Section -->
<div class="space-y-4">
<h3 class="text-lg font-semibold">Quick Links</h3>
<ul class="flex flex-wrap justify-center gap-4 text-sm">
<li>
<a href="/about" class="text-muted-foreground hover:text-primary">
About Us
</a>
</li>
<li>
<a href="/contact" class="text-muted-foreground hover:text-primary">
Contact Us
</a>
</li>
<li>
<a href="/dmca" class="text-muted-foreground hover:text-primary">
DMCA
</a>
</li>
<li>
<a href="/privacy-policy" class="text-muted-foreground hover:text-primary">
Privacy Policy
</a>
</li>
</ul>
</div>
<div class="space-y-4">
<h3 class="text-lg font-semibold">Connect</h3>
<p class="text-sm text-muted-foreground">Stay updated with the latest releases and news.</p>
</div>
</div>
<!-- Footer Bottom -->
<div class="mt-8 border-t pt-8 text-center">
<p class="text-xs text-muted-foreground">© <span id="current-year">2025</span> 4KHDHub - All rights reserved.</p>
</div>
</div>
</footer>
<!-- Back to top button -->
<button id="back-to-top" class="fixed bottom-6 right-6 z-50 rounded-full shadow-md transition-opacity duration-300 opacity-0 pointer-events-none bg-primary text-primary-foreground p-2" aria-label="Back to top">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m18 15-6-6-6 6" />
</svg>
</button>
</div>
<script src="/js/main.js?v=0.14.69c18"></script>
</body>
</html>

View file

@ -0,0 +1 @@
{"adult":false,"backdrop_path":"/vUVPHEo4ayCO4kkNV4k0PbWPmZS.jpg","created_by":[{"id":4220681,"credit_id":"64de76d9371097011c53058f","name":"Kim Bbang","original_name":"Kim Bbang","gender":0,"profile_path":null}],"episode_run_time":[70],"first_air_date":"2024-04-08","genres":[{"id":18,"name":"Drama"},{"id":10765,"name":"Sci-Fi & Fantasy"},{"id":35,"name":"Comedy"},{"id":9648,"name":"Mystery"}],"homepage":"https://tvn.cjenm.com/ko/Lovely-Runner/","id":230923,"in_production":false,"languages":["ko"],"last_air_date":"2024-05-28","last_episode_to_air":{"id":5148777,"name":"I Remember Everything","overview":"Sun-jae's memory comes back and now he remembers everything that happened between Sol and him. Thanks to Tae-sung, the ill-fated relations are resolved and the couple can be together. Sun-jae wants to propose to Sol, but finding the right time is difficult. Sun-ae decides to attend Sols nephews first birthday party and meet Sols family.","vote_average":0.0,"vote_count":1,"air_date":"2024-05-28","episode_number":16,"episode_type":"finale","production_code":"","runtime":77,"season_number":1,"show_id":230923,"still_path":"/hcFyYk5LGmkqTSbxRnQqej3mszO.jpg"},"name":"Lovely Runner","next_episode_to_air":null,"networks":[{"id":866,"logo_path":"/aRDq8zBrX3YLpHSfueNQBkNnn7b.png","name":"tvN","origin_country":"KR"}],"number_of_episodes":16,"number_of_seasons":1,"origin_country":["KR"],"original_language":"ko","original_name":"선재 업고 튀어","overview":"Right after Ryu Sun-jae, a top star, ends his life, Im Sol, his top fan, somehow ends up at a time when they were in high school and tries to protect him. A fantasy romance unfolds where people who missed each other in time finally meet.","popularity":10.0734,"poster_path":"/xJQyrif5M4UMoVBrBlwUabtaRxB.jpg","production_companies":[{"id":36225,"logo_path":"/haNfBy6ZS1a1teY9JXNHHkFhZEj.png","name":"Bon Factory","origin_country":"KR"},{"id":199265,"logo_path":"/mv2yDqAgT1ea1eTXZMDr89zX95M.png","name":"CJ ENM Studios","origin_country":"KR"}],"production_countries":[{"iso_3166_1":"KR","name":"South Korea"}],"seasons":[{"air_date":"2024-04-08","episode_count":16,"id":349357,"name":"Season 1","overview":"Im Sol is devastated by the sudden and tragic death of her favorite star, Ryu Sun-jae, a former swimmer turned K-pop idol. But in the midst of her anguish, she magically time slips back to 2008 when Sun-jae is still only 19 years old! Delighted that she has a chance to help him avert his unhappy future fate, Sol makes it her mission to change the future... and maybe find love along the way.","poster_path":"/xJQyrif5M4UMoVBrBlwUabtaRxB.jpg","season_number":1,"vote_average":10.0}],"spoken_languages":[{"english_name":"Korean","iso_639_1":"ko","name":"한국어/조선말"}],"status":"Ended","tagline":"I will protect both you and me.","type":"Scripted","vote_average":8.578,"vote_count":210}

View file

@ -0,0 +1,20 @@
<html>
<head>
<title>Redirecting ...</title>
<meta name="referrer" content="no-referrer">
<meta name="robots" content="noindex, nofollow">
<meta name="author" content="s-b0t">
<meta name="googlebot" content="noindex,nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<style>#container{width:100%;aspect-ratio:100 / 29}@media only screen and (min-width: 992px){img{height:80%!important;width:50%!important}}@media only screen and (min-width: 1200px){img{height:80%!important;width:50%!important}}.relative{position:relative}.bottom-left{position:absolute}.PurpleTxt{color:#7e41ff!important;font-weight:600;margin-left:.5ch;margin-right:.5ch}</style>
</head>
<body>
Redirecting ..
<script type="text/javascript">
function stck(e,t,i){let n="";if(i){let o=new Date;o.setTime(o.getTime()+6e4*i),n="; expires="+o.toUTCString()}document.cookie=`${e}=${t}; path=/; SameSite=None; Secure${n}`}
function s(e,t,i){let n=new Date,m={value:t,expiry:n.getTime()+i};window.localStorage.setItem(e,JSON.stringify(m));stck('xla',"s4t",4);}s('o','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9UQk1TbE0yVEVwWE1XOVVhbXhCVURWM2J6SXhjRmt5ZFdsdlNrbG1URW8xZUUxTFYzQlpiRlptVm5vNGRrSjJWM1ZHVTFacVREQjFRVUY0YXpWQ1NqbDRTVEJqWkV4NGNEVmFTV05SUVV0TmRtOUpTVEpLZUhWWWNGUkZaMGxMVFVGSlZFRTBTbm8xWWtGU01VeHVWVVZOYjBsTU1reDVSVlJ5UmxjNQ==',180*1000);setTimeout(()=>window.location.href='https://taazabull24.com/homelander/', 2000);
</script>
</body></html>

View file

@ -0,0 +1,20 @@
<html>
<head>
<title>Redirecting ...</title>
<meta name="referrer" content="no-referrer">
<meta name="robots" content="noindex, nofollow">
<meta name="author" content="s-b0t">
<meta name="googlebot" content="noindex,nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<style>#container{width:100%;aspect-ratio:100 / 29}@media only screen and (min-width: 992px){img{height:80%!important;width:50%!important}}@media only screen and (min-width: 1200px){img{height:80%!important;width:50%!important}}.relative{position:relative}.bottom-left{position:absolute}.PurpleTxt{color:#7e41ff!important;font-weight:600;margin-left:.5ch;margin-right:.5ch}</style>
</head>
<body>
Redirecting ..
<script type="text/javascript">
function stck(e,t,i){let n="";if(i){let o=new Date;o.setTime(o.getTime()+6e4*i),n="; expires="+o.toUTCString()}document.cookie=`${e}=${t}; path=/; SameSite=None; Secure${n}`}
function s(e,t,i){let n=new Date,m={value:t,expiry:n.getTime()+i};window.localStorage.setItem(e,JSON.stringify(m));stck('xla',"s4t",4);}s('o','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9UQk1TbE0yVEVwWE1XOVVhbXhCVURWM2J6SXhjRmt5ZFdsdlNrbG1URW8xZUUxTFYzQlpiRlptVm5vNGRrSjJWM1ZHVTFacVREQjFRVUY0YXpWQ1NqbDRTVEJqWkV4NGNEVmFTV05SUVV0TmRtOUpTVEpLZUhWWWNGUkZaMGxMVFVOR1UxSnRURWxGVkhBeVFXaHZVVTl1V2pJNGEwZDZNVXB4ZGxjNQ==',180*1000);setTimeout(()=>window.location.href='https://taazabull24.com/homelander/', 2000);
</script>
</body></html>

View file

@ -239,6 +239,35 @@ exports[`FourKHDHub handle dexter resurrection 2025 s01e01 1`] = `
]
`;
exports[`FourKHDHub handle lovely runner 2024 s01e01 1`] = `
[
{
"meta": {
"bytes": 3586297692,
"countryCodes": [
"hi",
"ko",
],
"height": 1080,
"title": "Lovely.Runner.S01E01.1080p.AMZN.WEB-DL.Hindi.DDP2.0-Korean.DDP2.0.H.264-4kHdHub.Com.mkv",
},
"url": "https://hubcloud.one/drive/8t7i1lrytgz56eo",
},
{
"meta": {
"bytes": 10340133765,
"countryCodes": [
"hi",
"ko",
],
"height": 1080,
"title": "Lovely Runner S01E01 1080p WEB-DL [Hindi DDP 2.0 + Korean DDP 5.1] x264 (PandaMoon-LUMiX).mkv",
},
"url": "https://hubcloud.one/drive/171fxx1xmbezm1r",
},
]
`;
exports[`FourKHDHub handle non-existent devil's bath 2024 gracefully 1`] = `[]`;
exports[`FourKHDHub handle superman 2025 1`] = `