Compare commits
12 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
720c9bb651 | ||
|
|
f05cf5040c | ||
|
|
65191cfc8d | ||
|
|
bd2dec0392 | ||
|
|
5f9fbbb30d | ||
|
|
43f04455f1 | ||
|
|
43637a2ff4 | ||
|
|
b87bf62362 | ||
|
|
89e57d48d9 | ||
|
|
ad47aecea3 | ||
|
|
f192fd0b75 | ||
|
|
557efd2079 |
50 changed files with 30077 additions and 161 deletions
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
".": "0.68.0"
|
".": "0.69.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
CHANGELOG.md
33
CHANGELOG.md
|
|
@ -1,5 +1,38 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.69.1](https://github.com/webstreamr/webstreamr/compare/v0.69.0...v0.69.1) (2026-03-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **source:** exclude ad videos in HDHub4u ([65191cf](https://github.com/webstreamr/webstreamr/commit/65191cfc8dad8f58b44e2c355b9adc600b99b2bf))
|
||||||
|
* **source:** remove stray console.log ([bd2dec0](https://github.com/webstreamr/webstreamr/commit/bd2dec03925d8b7760044dbfaaaec00b48f7cb66))
|
||||||
|
|
||||||
|
## [0.69.0](https://github.com/webstreamr/webstreamr/compare/v0.68.0...v0.69.0) (2026-03-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* **deps:** update dependency axios to v1.14.0 ([#800](https://github.com/webstreamr/webstreamr/issues/800)) ([ad47aec](https://github.com/webstreamr/webstreamr/commit/ad47aecea3f3d34700add442e023bd54f73451c8))
|
||||||
|
* **extractor:** detect languages from HubCloud title ([89e57d4](https://github.com/webstreamr/webstreamr/commit/89e57d48d95a6f8dd6446048ae72de51dd481f37))
|
||||||
|
* **extractor:** detect resolution from HubCloud title ([f192fd0](https://github.com/webstreamr/webstreamr/commit/f192fd0b7523094746148989e0cf06717db8152e))
|
||||||
|
* remove duplicate URLs ([b87bf62](https://github.com/webstreamr/webstreamr/commit/b87bf62362f3cd6b3ea055ecdaec44511bf2ec84))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **source:** add HDHub4u ([43f0445](https://github.com/webstreamr/webstreamr/commit/43f04455f17063e459df7e7a34af44de36afd6fc))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **extractor:** don't fail for HubDrive if HubCloud link is missing ([557efd2](https://github.com/webstreamr/webstreamr/commit/557efd207945ea7ada0bcaf475b0b9b9d60d8f5b))
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* **source:** extract hd hub link redirect resolver ([43637a2](https://github.com/webstreamr/webstreamr/commit/43637a2ff4280db208ec9c94c0a5d52a49dc6672))
|
||||||
|
|
||||||
## [0.68.0](https://github.com/webstreamr/webstreamr/compare/v0.67.0...v0.68.0) (2026-03-26)
|
## [0.68.0](https://github.com/webstreamr/webstreamr/compare/v0.67.0...v0.68.0) (2026-03-26)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ A public instance is available at https://webstreamr.hayd.uk. Hosting infrastruc
|
||||||
|
|
||||||
## Known issues / limitations
|
## Known issues / limitations
|
||||||
|
|
||||||
|
- PixelServer / pixeldrain has a daily limit of 6 GB per IP: https://pixeldrain.dev
|
||||||
- Dropload and SuperVideo on Android do not work because Stremio does not use the `Referer` header properly via HLS playlists: https://github.com/Stremio/stremio-bugs/issues/2389, maybe https://github.com/Stremio/stremio-bugs/issues/1579
|
- Dropload and SuperVideo on Android do not work because Stremio does not use the `Referer` header properly via HLS playlists: https://github.com/Stremio/stremio-bugs/issues/2389, maybe https://github.com/Stremio/stremio-bugs/issues/1579
|
||||||
- MediaFlow proxy has to be used in an inefficient way because Stremio on Android or its players cannot deal with HLS playlist with redirects: https://github.com/Stremio/stremio-bugs/issues/1574
|
- MediaFlow proxy has to be used in an inefficient way because Stremio on Android or its players cannot deal with HLS playlist with redirects: https://github.com/Stremio/stremio-bugs/issues/1574
|
||||||
- FlareSolverr cookies cannot be used because Cloudflare does techniques like TLS fingerprinting most likely. But FlareSolverr uses a session per host and should be quick.
|
- FlareSolverr cookies cannot be used because Cloudflare does techniques like TLS fingerprinting most likely. But FlareSolverr uses a session per host and should be quick.
|
||||||
|
|
|
||||||
23
package-lock.json
generated
23
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "webstreamr",
|
"name": "webstreamr",
|
||||||
"version": "0.68.0",
|
"version": "0.69.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "webstreamr",
|
"name": "webstreamr",
|
||||||
"version": "0.68.0",
|
"version": "0.69.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@keyv/sqlite": "^4.0.5",
|
"@keyv/sqlite": "^4.0.5",
|
||||||
|
|
@ -2961,14 +2961,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.13.6",
|
"version": "1.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
|
||||||
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
|
"integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.11",
|
"follow-redirects": "^1.15.11",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios-cache-interceptor": {
|
"node_modules/axios-cache-interceptor": {
|
||||||
|
|
@ -9197,10 +9197,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pstree.remy": {
|
"node_modules/pstree.remy": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "webstreamr",
|
"name": "webstreamr",
|
||||||
"description": "Provides HTTP URLs from streaming websites.",
|
"description": "Provides HTTP URLs from streaming websites.",
|
||||||
"version": "0.68.0",
|
"version": "0.69.1",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyse": "tsc --noEmit --project ./tsconfig.dev.json",
|
"analyse": "tsc --noEmit --project ./tsconfig.dev.json",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import bytes from 'bytes';
|
import bytes from 'bytes';
|
||||||
import * as cheerio from 'cheerio';
|
import * as cheerio from 'cheerio';
|
||||||
import { Context, Format, InternalUrlResult, Meta } from '../types';
|
import { Context, Format, InternalUrlResult, Meta } from '../types';
|
||||||
|
import { findCountryCodes, findHeight } from '../utils';
|
||||||
import { Extractor } from './Extractor';
|
import { Extractor } from './Extractor';
|
||||||
|
|
||||||
export class HubCloud extends Extractor {
|
export class HubCloud extends Extractor {
|
||||||
|
|
@ -25,6 +26,10 @@ export class HubCloud extends Extractor {
|
||||||
const linksHtml = await this.fetcher.text(ctx, new URL(redirectUrlMatch[1] as string), { headers: { Referer: url.href } });
|
const linksHtml = await this.fetcher.text(ctx, new URL(redirectUrlMatch[1] as string), { headers: { Referer: url.href } });
|
||||||
const $ = cheerio.load(linksHtml);
|
const $ = cheerio.load(linksHtml);
|
||||||
|
|
||||||
|
const title = $('title').text().trim();
|
||||||
|
const countryCodes = [...new Set([...meta.countryCodes ?? [], ...findCountryCodes(title)])];
|
||||||
|
const height = meta.height ?? findHeight(title);
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
...$('a')
|
...$('a')
|
||||||
.filter((_i, el) => {
|
.filter((_i, el) => {
|
||||||
|
|
@ -42,7 +47,9 @@ export class HubCloud extends Extractor {
|
||||||
...meta,
|
...meta,
|
||||||
bytes: bytes.parse($('#size').text()) as number,
|
bytes: bytes.parse($('#size').text()) as number,
|
||||||
extractorId: `${this.id}_fsl`,
|
extractorId: `${this.id}_fsl`,
|
||||||
title: $('title').text().trim(),
|
countryCodes,
|
||||||
|
height,
|
||||||
|
title,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}).toArray(),
|
}).toArray(),
|
||||||
|
|
@ -62,7 +69,9 @@ export class HubCloud extends Extractor {
|
||||||
...meta,
|
...meta,
|
||||||
bytes: bytes.parse($('#size').text()) as number,
|
bytes: bytes.parse($('#size').text()) as number,
|
||||||
extractorId: `${this.id}_fslv2`,
|
extractorId: `${this.id}_fslv2`,
|
||||||
title: $('title').text().trim(),
|
countryCodes,
|
||||||
|
height,
|
||||||
|
title,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}).toArray(),
|
}).toArray(),
|
||||||
|
|
@ -81,7 +90,9 @@ export class HubCloud extends Extractor {
|
||||||
...meta,
|
...meta,
|
||||||
bytes: bytes.parse($('#size').text()) as number,
|
bytes: bytes.parse($('#size').text()) as number,
|
||||||
extractorId: `${this.id}_pixelserver`,
|
extractorId: `${this.id}_pixelserver`,
|
||||||
title: $('title').text().trim(),
|
countryCodes,
|
||||||
|
height,
|
||||||
|
title,
|
||||||
},
|
},
|
||||||
requestHeaders: { Referer: userUrl.href },
|
requestHeaders: { Referer: userUrl.href },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,8 @@ describe('HubDrive', () => {
|
||||||
test('handle avatar', async () => {
|
test('handle avatar', async () => {
|
||||||
expect(await extractorRegistry.handle(ctx, new URL('https://hubdrive.space/file/7283903021'))).toMatchSnapshot();
|
expect(await extractorRegistry.handle(ctx, new URL('https://hubdrive.space/file/7283903021'))).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('handle missing hubcloud', async () => {
|
||||||
|
expect(await extractorRegistry.handle(ctx, new URL('https://hubdrive.space/file/2243124026'))).toMatchSnapshot();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,10 @@ export class HubDrive extends Extractor {
|
||||||
const html = await this.fetcher.text(ctx, url, { headers });
|
const html = await this.fetcher.text(ctx, url, { headers });
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
const hubCloudUrl = new URL($('a:contains("HubCloud")').attr('href') as string);
|
const hubCloudUrl = $('a:contains("HubCloud")')
|
||||||
|
.map((_i, el) => new URL($(el).attr('href') as string))
|
||||||
|
.get(0);
|
||||||
|
|
||||||
return this.hubCloud.extract(ctx, hubCloudUrl, meta);
|
return hubCloudUrl ? this.hubCloud.extract(ctx, hubCloudUrl, meta) : [];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
512
src/extractor/__fixtures__/HubDrive/https:hubdrive.spacefile2243124026
generated
Normal file
512
src/extractor/__fixtures__/HubDrive/https:hubdrive.spacefile2243124026
generated
Normal file
|
|
@ -0,0 +1,512 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name='admaven-placement' content=BrHCGpjC9>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="googlebot" content="noindex,nofollow">
|
||||||
|
<meta name="referrer" content="no-referrer"/>
|
||||||
|
<meta name="referrer" content="none"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta property="og:image" content="/assets/img/favicon.png">
|
||||||
|
<meta property="og:type" content="website"/>
|
||||||
|
<meta name="author" content="HubDrive">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="googlebot" content="noindex,nofollow">
|
||||||
|
<title>HubDrive | Back.to.the.Future.Part.III.1990.1080p.BluRay.Hindi.English.DD.5.1.x264.ESubs.Untouched.mkv</title>
|
||||||
|
<!-- Custom fonts for this template-->
|
||||||
|
<script src="https://cdn.jsdelivr.net/clipboard.js/1.5.12/clipboard.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/sweetalert@2.1.2/dist/sweetalert.min.js"></script>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||||
|
<script async="async" type="text/javascript" src="/assets/js/neodrivev2.5.min.js?v=3"></script>
|
||||||
|
<script src="https://use.fontawesome.com/746f656c7a.js"></script>
|
||||||
|
<link href="/assets/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="/assets/css/sb-admin-2.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
|
||||||
|
<link rel="icon" href="/assets/img/favicon.png">
|
||||||
|
<script data-cfasync="false" type="text/javascript" id="AdsCoreLoader100829" src="https://sads.adsboosters.xyz/801bbfc2f5f34af99c45dabeb76aa5ef.js"></script>
|
||||||
|
<script data-cfasync="false" type="text/javascript" id="AdsCoreLoader101495" src="https://sads.adsboosters.xyz/df182342f761a3795c0c8cfad378c7a4.js"></script>
|
||||||
|
<div class="clever-core-ads-100829></div>
|
||||||
|
<div class="clever-core-ads-101495></div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h4, .h4 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
#sticky-footer2 {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.Blink {
|
||||||
|
animation: blinker 0.3s cubic-bezier(.5, 0, 1, 1) infinite alternate;
|
||||||
|
}
|
||||||
|
@keyframes blinker {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
.sidebar .sidebar-brand {
|
||||||
|
font-size: .65rem;
|
||||||
|
}
|
||||||
|
.sidebar .nav-item .nav-link span {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
.sidebar .sidebar-brand i {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
background-color: #171717!important;
|
||||||
|
}
|
||||||
|
.container, .container-fluid {
|
||||||
|
background-color: transparent !IMPORTANT;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
#wrapper #content-wrapper #content {
|
||||||
|
background-color: transparent !IMPORTANT;
|
||||||
|
}
|
||||||
|
#wrapper #content-wrapper {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
.text-primary {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
.card-body {
|
||||||
|
background-color: transparent !IMPORTANT;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid rgb(49, 49, 49);
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
color: rgb(217, 217, 217);
|
||||||
|
}
|
||||||
|
.bg-gradient-primary {
|
||||||
|
background-image: linear-gradient(180deg,rgb(0, 28, 67)10%,rgb(0, 28, 67) 100%);
|
||||||
|
}
|
||||||
|
.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
|
||||||
|
color: rgb(130, 182, 255);
|
||||||
|
background-color: rgb(0, 28, 67);
|
||||||
|
}
|
||||||
|
footer.sticky-footer {
|
||||||
|
border: 2px solid rgb(49, 49, 49);
|
||||||
|
}
|
||||||
|
.navbar {
|
||||||
|
border-bottom: 2px solid hsl(213deg 69.03% 35.03% / 68%);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background-color: rgb(0 63 151);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.text-gray-800 {
|
||||||
|
color: rgb(130, 182, 255);
|
||||||
|
}
|
||||||
|
.card-file{
|
||||||
|
color: rgb(217, 217, 217);
|
||||||
|
}
|
||||||
|
.h5 {
|
||||||
|
color:rgb(130, 182, 255) !Important;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border: 1px solid rgb(255 255 255 / 23%);
|
||||||
|
}
|
||||||
|
.text-gray-400 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-500 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-600 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-700 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-800 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-900 {
|
||||||
|
color: rgb(130, 182, 255) !important;
|
||||||
|
}
|
||||||
|
.dropdown-menu {
|
||||||
|
background-color: #171717;
|
||||||
|
border: 2px solid rgb(49, 49, 49);
|
||||||
|
}
|
||||||
|
.form-control {
|
||||||
|
background-color: rgb(239 239 239);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: #171717;
|
||||||
|
}
|
||||||
|
.btn-info {
|
||||||
|
border-radius: 0.25rem !important;
|
||||||
|
background-color: #1a73e8 !important;
|
||||||
|
border-color: #1a73e8 !important;
|
||||||
|
}
|
||||||
|
.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, .show > .btn-info.dropdown-toggle {
|
||||||
|
background-color: #093d94 !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
.btn-info:hover {
|
||||||
|
background-color: #093d94 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8QTNRD0R4M"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
|
||||||
|
gtag('config', 'G-8QTNRD0R4M');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body id="page-top">
|
||||||
|
|
||||||
|
<!-- Page Wrapper -->
|
||||||
|
<div id="wrapper">
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion toggled" id="accordionSidebar">
|
||||||
|
<!-- Sidebar - Brand -->
|
||||||
|
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="https://hubdrive.space">
|
||||||
|
<div class="sidebar-brand-icon rotate-n-15">
|
||||||
|
<i class="fas fa-laugh-wink"></i>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-brand-text mx-3">HubDrive</div>
|
||||||
|
</a>
|
||||||
|
<!-- Divider -->
|
||||||
|
|
||||||
|
<hr class="sidebar-divider my-0">
|
||||||
|
<!-- Nav Item - Dashboard -->
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/sign">
|
||||||
|
<i class="fas fa-fw fa-sign-in-alt"></i>
|
||||||
|
<span>Login</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/page/privacy-policy">
|
||||||
|
<i class="fas fa-fw fa-user-secret"></i>
|
||||||
|
<span>Privacy Policy</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/page/terms-conditions">
|
||||||
|
<i class="fas fa-fw fa-align-justify"></i>
|
||||||
|
<span>Terms & Conditions</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/page/copyright-policy">
|
||||||
|
<i class="fas fa-fw fa-copyright"></i>
|
||||||
|
<span>Copyright Policy</span></a>
|
||||||
|
</li>
|
||||||
|
<!-- Divider -->
|
||||||
|
<hr class="sidebar-divider d-none d-md-block">
|
||||||
|
<!-- Sidebar Toggler (Sidebar) -->
|
||||||
|
<div class="text-center d-none d-md-inline">
|
||||||
|
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
<!-- End of Sidebar -->
|
||||||
|
<!-- Content Wrapper -->
|
||||||
|
<div id="content-wrapper" class="d-flex flex-column">
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div id="content">
|
||||||
|
<!-- Topbar -->
|
||||||
|
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
||||||
|
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="navbar-nav ml-auto">
|
||||||
|
<div style="display: flex; justify-content: center; align-items: center;margin-right: -27rem;">
|
||||||
|
<a href="/" style="display: flex; align-items: center;text-decoration: none;">
|
||||||
|
<i class="fab fa-artstation" style="font-size: 50px; color: #5090F0;"></i>
|
||||||
|
<img class="img-profile" src="https://catimages.org/images/2024/04/23/1b1be1f6932ecf270.png" style="width: 25%; filter: invert(1); margin-left: 5px;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="topbar-divider d-none d-sm-block" style="margin-left: -2px;"></div>
|
||||||
|
</ul>
|
||||||
|
</nav> <style>
|
||||||
|
.btn.btn-primary.btn-user1 {
|
||||||
|
background-color: #a10dff;
|
||||||
|
border-color: #ba50fd;
|
||||||
|
}
|
||||||
|
.btn-primary.btn-user1:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #b542ff;
|
||||||
|
}
|
||||||
|
.btn-primary.btn-user1:not(:disabled):not(.disabled):active, .btn-primary.btn-user1:not(:disabled):not(.disabled).active, .show > .btn-primary.btn-user1.dropdown-toggle {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #8102d1;
|
||||||
|
border-color:#ba50fd;
|
||||||
|
}
|
||||||
|
.btn-primary.btn-user1:focus, .btn-primary.btn-user1.focus {
|
||||||
|
box-shadow: 0 0 0 .25rem rgba(151, 51, 215, .5);
|
||||||
|
}
|
||||||
|
.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
|
||||||
|
color: rgb(255 255 255);
|
||||||
|
background-color: rgb(13 60 125);
|
||||||
|
border-color: rgb(13 60 125);
|
||||||
|
}
|
||||||
|
.nav-tabs {
|
||||||
|
border-bottom: rgb(49, 49, 49);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- http://caniuse.com/#feat=referrer-policy -->
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="googlebot" content="noindex,nofollow">
|
||||||
|
<meta name="referrer" content="no-referrer" />
|
||||||
|
<!-- For Edge and Safari -->
|
||||||
|
<meta name="referrer" content="none" />
|
||||||
|
<script>(function(s){s.dataset.zone='9824726',s.src='https://llvpn.com/tag.min.js'})([document.documentElement, document.body].filter(Boolean).pop().appendChild(document.createElement('script')))</script>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div id="down-id" hidden="true">2243124026</div>
|
||||||
|
<!-- Content Row -->
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-9 col-md-9 mb-4">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
|
||||||
|
<div class="card-header py-3" style="line-break: auto; word-break: break-all; white-space: normal;">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary" align="center" style="font-size: 1.2rem;">Back.to.the.Future.Part.III.1990.1080p.BluRay.Hindi.English.DD.5.1.x264.ESubs.Untouched.mkv</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-borderless" id="dataTable" width="100%" cellspacing="0" style="line-break: auto; word-break: initial; white-space: initial;">
|
||||||
|
<tbody>
|
||||||
|
<tr style="border-bottom: 2px solid rgb(63 63 63); line-height: 1.8em;">
|
||||||
|
<td>File Size</td>
|
||||||
|
<td align="right">3.77 GB</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 2px solid rgb(63 63 63); line-height: 1.8em;">
|
||||||
|
<td>File Type</td>
|
||||||
|
<td align="right">video/x-matroska</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>File Owner</td>
|
||||||
|
<td align="right">dhub 2</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="text" align="center">
|
||||||
|
<form action="/gsign.php" method="GET">
|
||||||
|
<input name="r" value="https://hubdrive.space/file/2243124026" type="hidden">
|
||||||
|
<button class="btn btn-primary btn-user" type="submit"><i class="fa fa-sign-in fa-lg"></i> GDrive [Login]</button>
|
||||||
|
<!--button class="btn btn-primary btn-user" type="submit"><i class="fa fa-sign-in fa-lg"></i> Download [3.77 GB] [Login]</button-->
|
||||||
|
</form>
|
||||||
|
<div>
|
||||||
|
<button onclick="myDirectDownload()" id="dl-down" type="button" class="btn btn-primary btn-user1" style="margin:10px;"><i class="fas fa-file-download fa-lg"></i> Direct/Instant Download</button>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text" align="left">
|
||||||
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="#" onclick="copyLink()" role="tab" data-toggle="tab"><i class="fa fa-copy"></i> Copy Link</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!-- Tab panes -->
|
||||||
|
<div class="tab-content">
|
||||||
|
<div role="tabpanel" class="tab-pane fade show active" id="link">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<p id="copyText" style="text-align:left; color:rgb(116 174 255);">https://hubdrive.space/file/2243124026</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function copyLink() {
|
||||||
|
var copyText = document.getElementById("copyText");
|
||||||
|
var textArea = document.createElement("textarea");
|
||||||
|
textArea.value = copyText.textContent;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Link Copied",
|
||||||
|
icon: "success",
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 1500
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.container-fluid -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
alert("please enable JavaScript in your browser");
|
||||||
|
</noscript>
|
||||||
|
<script>
|
||||||
|
function myDownloadV2() {
|
||||||
|
var e = document.getElementById("down-id").innerHTML;
|
||||||
|
document.getElementById("down").innerHTML = '<i class="fa fa-spinner fa-spin"></i> Downloading.. !',
|
||||||
|
document.getElementById("down").disabled = !0;
|
||||||
|
var b = window.setTimeout(function() {
|
||||||
|
document.getElementById("down").innerHTML = '<i class="fa fa-cog fa-spin fa-lg"></i> Generating Link.. !'
|
||||||
|
}, 6e3);
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$.ajax({
|
||||||
|
url: "/ajax.php?ajax=download",
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: "id=" + e,
|
||||||
|
success: function(a) {
|
||||||
|
if ("200" == a.code) {
|
||||||
|
window.clearTimeout(b);
|
||||||
|
localStorage.setItem("dls", JSON.stringify(a?.data));
|
||||||
|
// window.location.href = a.file;
|
||||||
|
window.location.href = "/newdl";
|
||||||
|
|
||||||
|
} else swal.fire("Code : " + a.code, "Message : " + a.file, "error");
|
||||||
|
},
|
||||||
|
error: function(e, a, t) {
|
||||||
|
alert("Status: " + a + "\n" + t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function myDirectDownload() {
|
||||||
|
var a = document.getElementById("down-id").innerHTML;
|
||||||
|
document.getElementById("dl-down").innerHTML = '<i class="fa fa-spinner fa-spin"></i> Generating Link ...';
|
||||||
|
document.getElementById("dl-down").disabled = !0;
|
||||||
|
|
||||||
|
var b = window.setTimeout(function() {
|
||||||
|
document.getElementById("dl-down").innerHTML = '<i class="fa fa-cog fa-spin fa-lg"></i>Downloading .. !';
|
||||||
|
}, 6e3);
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$.ajax({
|
||||||
|
url: "/ajax.php?ajax=direct-download",
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: "id=" + a,
|
||||||
|
success: function(a) {
|
||||||
|
if ("200" == a.code) {
|
||||||
|
window.clearTimeout(b);
|
||||||
|
localStorage.setItem("dls", JSON.stringify(a?.data));
|
||||||
|
// window.location.href = a.file;
|
||||||
|
window.location.href = "/newdl";
|
||||||
|
|
||||||
|
} else swal.fire("Code : " + a.code, "Message : " + a.file, "error");
|
||||||
|
},
|
||||||
|
error: function(a, b, c) {
|
||||||
|
alert("Status: " + b + "\n" + c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main class="min-h-screen flex flex-col" >
|
||||||
|
<header class="container mx-auto px-4 py-4 lg:text-center lg:flex lg:items-center lg:justify-between">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
<script src='https://kit.fontawesome.com/a076d05399.js' crossorigin='anonymous'></script>
|
||||||
|
<!--
|
||||||
|
<footer class="sticky-footer bg-white">
|
||||||
|
<div class="container my-auto">
|
||||||
|
<div class="copyright text-center my-auto">
|
||||||
|
<span>Copyright © HubDrive 2026</span>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="copyright text-center my-auto" style="font-size: 15px; font-weight: 600;">
|
||||||
|
<span><a href="/page/privacy-policy"><i class="fa fa-bullhorn text-danger"></i> Privacy Policy</a> | <a href="/page/terms-conditions"><i class="fa fa-book text-info"></i> Terms & Conditions</a> | <a href="/page/copyright-policy"><i class="fa fa-copyright text-warning"></i> Copyright Policy</a> | <a href="/page/contact-us"><i class="fa fa-envelope text-success"></i> Contact Us</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End of Content Wrapper -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End of Page Wrapper -->
|
||||||
|
|
||||||
|
<!-- Scroll to Top Button-->
|
||||||
|
<a class="scroll-to-top rounded" href="#page-top">
|
||||||
|
<i class="fas fa-angle-up"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Logout Modal-->
|
||||||
|
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">Are you sure?</h5>
|
||||||
|
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||||
|
<a class="btn btn-primary" href="/login.php?action=logout">Logout</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript-->
|
||||||
|
<script src="/assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Core plugin JavaScript-->
|
||||||
|
<script src="/assets/vendor/jquery-easing/jquery.easing.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Custom scripts for all pages-->
|
||||||
|
<script src="/assets/js/sb-admin-2.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Page level plugins -->
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -7,7 +7,12 @@ exports[`HubCloud handle crayon shin-chan 1993 1`] = `
|
||||||
"label": "HubCloud (FSL)",
|
"label": "HubCloud (FSL)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 28550795100,
|
"bytes": 28550795100,
|
||||||
|
"countryCodes": [
|
||||||
|
"hi",
|
||||||
|
"ja",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_fsl",
|
"extractorId": "hubcloud_fsl",
|
||||||
|
"height": 1080,
|
||||||
"title": "Crayon Shinchan Action Kamen vs Demon (1993) 1080p BluRay REMUX AVC [Hindi DD 2.0 + Japanese FLAC 2.0] (PitiPati-Ionicboy) (4kHDHub.com).mkv",
|
"title": "Crayon Shinchan Action Kamen vs Demon (1993) 1080p BluRay REMUX AVC [Hindi DD 2.0 + Japanese FLAC 2.0] (PitiPati-Ionicboy) (4kHDHub.com).mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
@ -23,7 +28,12 @@ exports[`HubCloud handle dark 2017 s03e08 1`] = `
|
||||||
"label": "HubCloud (FSL)",
|
"label": "HubCloud (FSL)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 3382286745,
|
"bytes": 3382286745,
|
||||||
|
"countryCodes": [
|
||||||
|
"de",
|
||||||
|
"en",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_fsl",
|
"extractorId": "hubcloud_fsl",
|
||||||
|
"height": 1080,
|
||||||
"title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv",
|
"title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
@ -34,7 +44,12 @@ exports[`HubCloud handle dark 2017 s03e08 1`] = `
|
||||||
"label": "HubCloud (PixelServer)",
|
"label": "HubCloud (PixelServer)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 3382286745,
|
"bytes": 3382286745,
|
||||||
|
"countryCodes": [
|
||||||
|
"de",
|
||||||
|
"en",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_pixelserver",
|
"extractorId": "hubcloud_pixelserver",
|
||||||
|
"height": 1080,
|
||||||
"title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv",
|
"title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv",
|
||||||
},
|
},
|
||||||
"requestHeaders": {
|
"requestHeaders": {
|
||||||
|
|
@ -53,7 +68,9 @@ exports[`HubCloud handle dexter original sin 2024 s01e01 1`] = `
|
||||||
"label": "HubCloud (FSL)",
|
"label": "HubCloud (FSL)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 5733781340,
|
"bytes": 5733781340,
|
||||||
|
"countryCodes": [],
|
||||||
"extractorId": "hubcloud_fsl",
|
"extractorId": "hubcloud_fsl",
|
||||||
|
"height": 2160,
|
||||||
"title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv",
|
"title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
@ -64,7 +81,9 @@ exports[`HubCloud handle dexter original sin 2024 s01e01 1`] = `
|
||||||
"label": "HubCloud (PixelServer)",
|
"label": "HubCloud (PixelServer)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 5733781340,
|
"bytes": 5733781340,
|
||||||
|
"countryCodes": [],
|
||||||
"extractorId": "hubcloud_pixelserver",
|
"extractorId": "hubcloud_pixelserver",
|
||||||
|
"height": 2160,
|
||||||
"title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv",
|
"title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv",
|
||||||
},
|
},
|
||||||
"requestHeaders": {
|
"requestHeaders": {
|
||||||
|
|
@ -83,7 +102,12 @@ exports[`HubCloud handle goat 2026 1`] = `
|
||||||
"label": "HubCloud (FSL)",
|
"label": "HubCloud (FSL)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 19091129630,
|
"bytes": 19091129630,
|
||||||
|
"countryCodes": [
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_fsl",
|
"extractorId": "hubcloud_fsl",
|
||||||
|
"height": 2160,
|
||||||
"title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv",
|
"title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
@ -94,7 +118,12 @@ exports[`HubCloud handle goat 2026 1`] = `
|
||||||
"label": "HubCloud (FSLv2)",
|
"label": "HubCloud (FSLv2)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 19091129630,
|
"bytes": 19091129630,
|
||||||
|
"countryCodes": [
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_fslv2",
|
"extractorId": "hubcloud_fslv2",
|
||||||
|
"height": 2160,
|
||||||
"title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv",
|
"title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,12 @@ exports[`HubDrive handle avatar 1`] = `
|
||||||
"label": "HubCloud (FSL)",
|
"label": "HubCloud (FSL)",
|
||||||
"meta": {
|
"meta": {
|
||||||
"bytes": 64649995223,
|
"bytes": 64649995223,
|
||||||
|
"countryCodes": [
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
"extractorId": "hubcloud_fsl",
|
"extractorId": "hubcloud_fsl",
|
||||||
|
"height": 2160,
|
||||||
"title": "Avatar (2009) Extended Collector's Edition IMAX 2160p UHD BluRay REMUX DV HDR 10bit HEVC [Hindi DDP 5.1 + English DTS-HD MA 5.1] x265 (LM-LUMiX) 4KHDHUB.[Com].mkv",
|
"title": "Avatar (2009) Extended Collector's Edition IMAX 2160p UHD BluRay REMUX DV HDR 10bit HEVC [Hindi DDP 5.1 + English DTS-HD MA 5.1] x265 (LM-LUMiX) 4KHDHUB.[Com].mkv",
|
||||||
},
|
},
|
||||||
"ttl": 43200000,
|
"ttl": 43200000,
|
||||||
|
|
@ -15,3 +20,5 @@ exports[`HubDrive handle avatar 1`] = `
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`HubDrive handle missing hubcloud 1`] = `[]`;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import { BasicAcceptedElems, CheerioAPI } from 'cheerio';
|
||||||
import { AnyNode } from 'domhandler';
|
import { AnyNode } from 'domhandler';
|
||||||
import levenshtein from 'fast-levenshtein';
|
import levenshtein from 'fast-levenshtein';
|
||||||
import memoize from 'memoizee';
|
import memoize from 'memoizee';
|
||||||
import rot13Cipher from 'rot13-cipher';
|
|
||||||
import { ContentType } from 'stremio-addon-sdk';
|
import { ContentType } from 'stremio-addon-sdk';
|
||||||
import { Context, CountryCode, Meta } from '../types';
|
import { Context, CountryCode, Meta } from '../types';
|
||||||
import { Fetcher, findCountryCodes, getTmdbId, getTmdbNameAndYear, Id, TmdbId } from '../utils';
|
import { Fetcher, findCountryCodes, getTmdbId, getTmdbNameAndYear, Id, TmdbId } from '../utils';
|
||||||
|
import { resolveRedirectUrl } from './hd-hub-helper';
|
||||||
import { Source, SourceResult } from './Source';
|
import { Source, SourceResult } from './Source';
|
||||||
|
|
||||||
export class FourKHDHub extends Source {
|
export class FourKHDHub extends Source {
|
||||||
|
|
@ -115,7 +115,7 @@ export class FourKHDHub extends Source {
|
||||||
.get(0);
|
.get(0);
|
||||||
|
|
||||||
if (redirectUrlHubCloud) {
|
if (redirectUrlHubCloud) {
|
||||||
return { url: await this.resolveRedirectUrl(ctx, redirectUrlHubCloud), meta };
|
return { url: await resolveRedirectUrl(ctx, this.fetcher, redirectUrlHubCloud), meta };
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirectUrlHubDrive = $('a', el)
|
const redirectUrlHubDrive = $('a', el)
|
||||||
|
|
@ -123,17 +123,9 @@ export class FourKHDHub extends Source {
|
||||||
.map((_i, el) => new URL($(el).attr('href') as string))
|
.map((_i, el) => new URL($(el).attr('href') as string))
|
||||||
.get(0) as URL;
|
.get(0) as URL;
|
||||||
|
|
||||||
return { url: await this.resolveRedirectUrl(ctx, redirectUrlHubDrive), meta };
|
return { url: await resolveRedirectUrl(ctx, this.fetcher, redirectUrlHubDrive), meta };
|
||||||
};
|
};
|
||||||
|
|
||||||
private async resolveRedirectUrl(ctx: Context, redirectUrl: URL): Promise<URL> {
|
|
||||||
const redirectHtml = await this.fetcher.text(ctx, redirectUrl);
|
|
||||||
const redirectDataMatch = redirectHtml.match(/'o','(.*?)'/) as string[];
|
|
||||||
const redirectData = JSON.parse(atob(rot13Cipher(atob(atob(redirectDataMatch[1] as string))))) as { o: string };
|
|
||||||
|
|
||||||
return new URL(atob(redirectData['o']));
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly getBaseUrl = async (ctx: Context): Promise<URL> => {
|
private readonly getBaseUrl = async (ctx: Context): Promise<URL> => {
|
||||||
return await this.fetcher.getFinalRedirectUrl(ctx, new URL(this.baseUrl));
|
return await this.fetcher.getFinalRedirectUrl(ctx, new URL(this.baseUrl));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
33
src/source/HDHub4u.test.ts
Normal file
33
src/source/HDHub4u.test.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { createTestContext } from '../test';
|
||||||
|
import { FetcherMock, ImdbId } from '../utils';
|
||||||
|
import { HDHub4u } from './HDHub4u';
|
||||||
|
|
||||||
|
const ctx = createTestContext();
|
||||||
|
|
||||||
|
describe('HDHub4u', () => {
|
||||||
|
let source: HDHub4u;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
source = new HDHub4u(new FetcherMock(`${__dirname}/__fixtures__/HDHub4u`));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle superman 2025', async () => {
|
||||||
|
const streams = await source.handle(ctx, 'movie', new ImdbId('tt5950044', undefined, undefined));
|
||||||
|
expect(streams).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle the bone temple 2026', async () => {
|
||||||
|
const streams = await source.handle(ctx, 'movie', new ImdbId('tt32141377', undefined, undefined));
|
||||||
|
expect(streams).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle stranger things s05e01', async () => {
|
||||||
|
const streams = await source.handle(ctx, 'series', new ImdbId('tt4574334', 5, 1));
|
||||||
|
expect(streams).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle stranger things s05e08', async () => {
|
||||||
|
const streams = await source.handle(ctx, 'series', new ImdbId('tt4574334', 5, 8));
|
||||||
|
expect(streams).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
119
src/source/HDHub4u.ts
Normal file
119
src/source/HDHub4u.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import { ContentType } from 'stremio-addon-sdk';
|
||||||
|
import { Context, CountryCode, Meta } from '../types';
|
||||||
|
import { Fetcher, findCountryCodes, getImdbId, Id, ImdbId } from '../utils';
|
||||||
|
import { resolveRedirectUrl } from './hd-hub-helper';
|
||||||
|
import { Source, SourceResult } from './Source';
|
||||||
|
|
||||||
|
interface SearchResponsePartial {
|
||||||
|
hits: {
|
||||||
|
document: {
|
||||||
|
imdb_id: string;
|
||||||
|
permalink: string;
|
||||||
|
post_title: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HDHub4u extends Source {
|
||||||
|
public readonly id = 'hdhub4u';
|
||||||
|
|
||||||
|
public readonly label = 'HDHub4u';
|
||||||
|
|
||||||
|
public readonly contentTypes: ContentType[] = ['movie', 'series'];
|
||||||
|
|
||||||
|
public readonly countryCodes: CountryCode[] = [CountryCode.multi, CountryCode.gu, CountryCode.hi, CountryCode.ml, CountryCode.pa, CountryCode.ta, CountryCode.te];
|
||||||
|
|
||||||
|
public readonly baseUrl = 'https://new5.hdhub4u.fo';
|
||||||
|
|
||||||
|
private readonly searchUrl = 'https://search.pingora.fyi';
|
||||||
|
|
||||||
|
private readonly fetcher: Fetcher;
|
||||||
|
|
||||||
|
public constructor(fetcher: Fetcher) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.fetcher = fetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async handleInternal(ctx: Context, _type: string, id: Id): Promise<SourceResult[]> {
|
||||||
|
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||||
|
|
||||||
|
const pageUrls = await this.fetchPageUrls(ctx, imdbId);
|
||||||
|
|
||||||
|
return (await Promise.all(
|
||||||
|
pageUrls.map(async (pageUrl) => {
|
||||||
|
return await this.handlePage(ctx, pageUrl, imdbId);
|
||||||
|
}),
|
||||||
|
)).flat();
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly handlePage = async (ctx: Context, pageUrl: URL, imdbId: ImdbId): Promise<SourceResult[]> => {
|
||||||
|
const html = await this.fetcher.text(ctx, pageUrl);
|
||||||
|
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
countryCodes: [CountryCode.multi, ...findCountryCodes($('div:contains("Language"):not(:has(div)):first').text())],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!imdbId.episode) {
|
||||||
|
return [
|
||||||
|
...this.extractHubDriveUrlResults(html, meta),
|
||||||
|
...(await Promise.all(
|
||||||
|
$('a[href*="gadgetsweb"]').map((_i, el) => this.handleHubLinks(ctx, new URL($(el).attr('href') as string), pageUrl, meta)),
|
||||||
|
)).flat(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
...(await Promise.all(
|
||||||
|
$(`a:contains("EPiSODE ${imdbId.episode}"), a:contains("EPiSODE ${String(imdbId.episode).padStart(2, '0')}")`)
|
||||||
|
.map(async (_i, el) => this.handleHubLinks(ctx, new URL($(el).attr('href') as string), pageUrl, meta)),
|
||||||
|
)).flat(),
|
||||||
|
...this.extractHubDriveUrlResults(
|
||||||
|
$(`h4:contains("EPiSODE ${imdbId.episode}"), h4:contains("EPiSODE ${String(imdbId.episode).padStart(2, '0')}")`)
|
||||||
|
.first()
|
||||||
|
.nextUntil('hr')
|
||||||
|
.map((_i, el) => $.html(el))
|
||||||
|
.get()
|
||||||
|
.join(''),
|
||||||
|
meta,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly handleHubLinks = async (ctx: Context, redirectUrl: URL, refererUrl: URL, meta: Meta): Promise<SourceResult[]> => {
|
||||||
|
const hubLinksUrl = await resolveRedirectUrl(ctx, this.fetcher, redirectUrl);
|
||||||
|
const hubLinksHtml = await this.fetcher.text(ctx, hubLinksUrl, { headers: { Referer: refererUrl.href } });
|
||||||
|
|
||||||
|
return [
|
||||||
|
...this.extractHubDriveUrlResults(hubLinksHtml, { ...meta, referer: hubLinksUrl.href }),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly extractHubDriveUrlResults = (html: string, meta: Meta): SourceResult[] => {
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
|
return $('a[href*="hubdrive"]:not(:contains("⚡"))')
|
||||||
|
.map((_i, el) => ({ url: new URL($(el).attr('href') as string), meta }))
|
||||||
|
.toArray();
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly fetchPageUrls = async (ctx: Context, imdbId: ImdbId): Promise<URL[]> => {
|
||||||
|
const searchUrl = new URL(`/collections/post/documents/search?query_by=imdb_id&q=${encodeURIComponent(imdbId.id)}`, this.searchUrl);
|
||||||
|
const searchResponse = await this.fetcher.json(ctx, searchUrl, { headers: { Referer: this.baseUrl } }) as SearchResponsePartial;
|
||||||
|
|
||||||
|
return searchResponse.hits
|
||||||
|
.filter(hit =>
|
||||||
|
hit.document.imdb_id === imdbId.id
|
||||||
|
&& (
|
||||||
|
!imdbId.season
|
||||||
|
|| hit.document.post_title.includes(`Season ${imdbId.season}`)
|
||||||
|
|| hit.document.post_title.includes(`S${String(imdbId.season)}`)
|
||||||
|
|| hit.document.post_title.includes(`S${String(imdbId.season).padStart(2, '0')}`)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.map(hit => new URL(hit.document.permalink, this.baseUrl));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkVGSU5VaE5iVVZCVFcwd09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkVGSU5VaE5iVVZDUkVjd09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkVGSU5VaE5iVVZDU0Vjd09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkVGSU5VaE5iVVZCY1cwd09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkhKU01WSklSMU5DY25oSU9WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkhKU01WSklSMU5DY25oU09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkhKU01WSkhTM1ZCU1ZSbU9WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkhKU01WSkhTM1ZCU1ZSd09WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
|
@ -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','Y214WE0xWjNZbXRhVUdwMmIxQldObFo2ZFRCeFZVOXRRbmxxYVV0UU9YZHdZWGxxY1ZRNVkyOWhRV05OTW5Vd2NHdzFiVzVMUlhsTFVEbGliekl4ZVc5VVUyaE5WRWxzUzFBNGRsbFFWMmxXZDJKMlRFaDFSbHBVUVZaSFIwMWFja2Q1YVVwS01UUndWRmRuY1ZWaldtOUpWMkpLZUZvMWJsUkJaMGQ2T1hWS1UyTm1URE40TkhKU01WSkdTMk5CU1ZSbU9WWmhNRDA9',180*1000);setTimeout(()=>window.location.href='https://cryptoinsights.site/homelander/', 2000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
373
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives102319
generated
Normal file
373
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives102319
generated
Normal file
File diff suppressed because one or more lines are too long
363
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives103118
generated
Normal file
363
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives103118
generated
Normal file
File diff suppressed because one or more lines are too long
363
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives103119
generated
Normal file
363
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives103119
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives104570
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives104570
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives104571
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives104571
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95882
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95882
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95883
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95883
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95884
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95884
generated
Normal file
File diff suppressed because one or more lines are too long
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95885
generated
Normal file
365
src/source/__fixtures__/HDHub4u/https:hblinks.dadarchives95885
generated
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
5343
src/source/__fixtures__/HDHub4u/https:new5.hdhub4u.fostranger-things-season-5-hindi-webrip-all-episodes
generated
Normal file
5343
src/source/__fixtures__/HDHub4u/https:new5.hdhub4u.fostranger-things-season-5-hindi-webrip-all-episodes
generated
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3079
src/source/__fixtures__/HDHub4u/https:new5.hdhub4u.fosuperman-2025-hindi-webrip-full-movie
generated
Normal file
3079
src/source/__fixtures__/HDHub4u/https:new5.hdhub4u.fosuperman-2025-hindi-webrip-full-movie
generated
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
{"facet_counts":[],"found":2,"hits":[{"document":{"category":["300MB Movies","Dual Audio","HD Movies","Hindi Dubbed","HollyWood","Horror","Sci-Fi","Thriller"],"director":["Nia DaCosta"],"id":"183681","imdb_id":"tt32141377","permalink":"/28-years-later-the-bone-temple-2026-hindi-webrip-full-movie/","post_date":"February 17, 2026","post_thumbnail":"https://image.tmdb.org/t/p/w500/fVlbHQvKgZHF1uEIYePZqpfDqaJ.jpg","post_title":"28 Years Later: The Bone Temple (2026) WEB-DL [Hindi (DD5.1) & English] 4K 1080p 720p & 480p Dual Audio [x264/10Bit-HEVC] | Full Movie","post_type":"post","sort_by_date":1771333131,"stars":["Ralph Fiennes","Jack O'Connell","Alfie Williams"]},"highlight":{"imdb_id":{"matched_tokens":["tt32141377"],"snippet":"<mark>tt32141377</mark>"}},"highlights":[{"field":"imdb_id","matched_tokens":["tt32141377"],"snippet":"<mark>tt32141377</mark>"}],"text_match":578730123365711993,"text_match_info":{"best_field_score":"1108091339008","best_field_weight":15,"fields_matched":1,"num_tokens_dropped":0,"score":"578730123365711993","tokens_matched":1,"typo_prefix_score":0}},{"document":{"category":["HollyWood","Horror","Sci-Fi","Thriller"],"director":["Nia DaCosta"],"id":"182051","imdb_id":"tt32141377","permalink":"/28-years-later-the-bone-temple-2026-hdtc-hindi-full-movie/","post_date":"January 19, 2026","post_thumbnail":"https://image.tmdb.org/t/p/w400/kK1BGkG3KAvWB0WMV1DfOx9yTMZ.jpg","post_title":"28 Years Later: The Bone Temple (2026) HDTC [Hindi (Clean)] 1080p 720p & 480p [x264] | Full Movie","post_type":"post","sort_by_date":1768822585,"stars":["Ralph Fiennes","Jack O'Connell","Alfie Williams"]},"highlight":{"imdb_id":{"matched_tokens":["tt32141377"],"snippet":"<mark>tt32141377</mark>"}},"highlights":[{"field":"imdb_id","matched_tokens":["tt32141377"],"snippet":"<mark>tt32141377</mark>"}],"text_match":578730123365711993,"text_match_info":{"best_field_score":"1108091339008","best_field_weight":15,"fields_matched":1,"num_tokens_dropped":0,"score":"578730123365711993","tokens_matched":1,"typo_prefix_score":0}}],"out_of":13464,"page":1,"request_params":{"collection_name":"post","first_q":"tt32141377","per_page":10,"q":"tt32141377"},"search_cutoff":false,"search_time_ms":0}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
{"facet_counts":[],"found":1,"hits":[{"document":{"category":["300MB Movies","Action","Adventure","Dual Audio","HD Movies","Hindi Dubbed","HollyWood","Sci-Fi"],"director":["James Gunn"],"id":"174394","imdb_id":"tt5950044","permalink":"/superman-2025-hindi-webrip-full-movie/","post_date":"August 24, 2025","post_thumbnail":"https://image.tmdb.org/t/p/w500/1H9hdeRoniz30RKhyr1uLdBTfpG.jpg","post_title":"Superman (2025) iMAX DS4K WEB-DL [Hindi (DD5.1) & English] 4K 1080p 720p & 480p Dual Audio [x264/10Bit-HEVC] | Full Movie","post_type":"post","sort_by_date":1756030053,"stars":["David Corenswet","Rachel Brosnahan","Nicholas Hoult"]},"highlight":{"imdb_id":{"matched_tokens":["tt5950044"],"snippet":"<mark>tt5950044</mark>"}},"highlights":[{"field":"imdb_id","matched_tokens":["tt5950044"],"snippet":"<mark>tt5950044</mark>"}],"text_match":578730123365711993,"text_match_info":{"best_field_score":"1108091339008","best_field_weight":15,"fields_matched":1,"num_tokens_dropped":0,"score":"578730123365711993","tokens_matched":1,"typo_prefix_score":0}}],"out_of":13464,"page":1,"request_params":{"collection_name":"post","first_q":"tt5950044","per_page":10,"q":"tt5950044"},"search_cutoff":false,"search_time_ms":0}
|
||||||
304
src/source/__snapshots__/HDHub4u.test.ts.snap
Normal file
304
src/source/__snapshots__/HDHub4u.test.ts.snap
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
|
exports[`HDHub4u handle stranger things s05e01 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2452204677",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/1788432714",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`HDHub4u handle stranger things s05e08 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/1793632174",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2655940410",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2007803192",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2913823672",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/1898122266",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/3043520687",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/4664307676",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/102319",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/8835271729",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`HDHub4u handle superman 2025 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2048323831",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/1931317982",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/7875454809",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/3608508909",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/95885",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2171324800",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/95884",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/1866728891",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/95883",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/3938026297",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/95882",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2823990434",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`HDHub4u handle the bone temple 2026 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2165806385",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2777734670",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/6051118182",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/13783802255",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/104571",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2026023433",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"en",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/104570",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/4232622187",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2298599706",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/103118",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2291074311",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"countryCodes": [
|
||||||
|
"multi",
|
||||||
|
"hi",
|
||||||
|
],
|
||||||
|
"referer": "https://hblinks.dad/archives/103119",
|
||||||
|
},
|
||||||
|
"url": "https://hubdrive.space/file/2244066767",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
11
src/source/hd-hub-helper.ts
Normal file
11
src/source/hd-hub-helper.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import rot13Cipher from 'rot13-cipher';
|
||||||
|
import { Context } from '../types';
|
||||||
|
import { Fetcher } from '../utils';
|
||||||
|
|
||||||
|
export const resolveRedirectUrl = async (ctx: Context, fetcher: Fetcher, redirectUrl: URL): Promise<URL> => {
|
||||||
|
const redirectHtml = await fetcher.text(ctx, redirectUrl);
|
||||||
|
const redirectDataMatch = redirectHtml.match(/'o','(.*?)'/) as string[];
|
||||||
|
const redirectData = JSON.parse(atob(rot13Cipher(atob(atob(redirectDataMatch[1] as string))))) as { o: string };
|
||||||
|
|
||||||
|
return new URL(atob(redirectData['o']));
|
||||||
|
};
|
||||||
|
|
@ -6,6 +6,7 @@ import { Eurostreaming } from './Eurostreaming';
|
||||||
import { FourKHDHub } from './FourKHDHub';
|
import { FourKHDHub } from './FourKHDHub';
|
||||||
import { Frembed } from './Frembed';
|
import { Frembed } from './Frembed';
|
||||||
import { FrenchCloud } from './FrenchCloud';
|
import { FrenchCloud } from './FrenchCloud';
|
||||||
|
import { HDHub4u } from './HDHub4u';
|
||||||
import { HomeCine } from './HomeCine';
|
import { HomeCine } from './HomeCine';
|
||||||
import { KinoGer } from './KinoGer';
|
import { KinoGer } from './KinoGer';
|
||||||
import { Kokoshka } from './Kokoshka';
|
import { Kokoshka } from './Kokoshka';
|
||||||
|
|
@ -28,6 +29,7 @@ export const createSources = (fetcher: Fetcher): Source[] => {
|
||||||
return [
|
return [
|
||||||
// multi
|
// multi
|
||||||
new FourKHDHub(fetcher),
|
new FourKHDHub(fetcher),
|
||||||
|
new HDHub4u(fetcher),
|
||||||
new VixSrc(fetcher),
|
new VixSrc(fetcher),
|
||||||
new VidSrc(),
|
new VidSrc(),
|
||||||
new RgShows(fetcher),
|
new RgShows(fetcher),
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ describe('resolve', () => {
|
||||||
protected readonly extractInternal = async (): Promise<UrlResult[]> =>
|
protected readonly extractInternal = async (): Promise<UrlResult[]> =>
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
url: new URL('https://example.com'),
|
url: new URL('https://example1.com'),
|
||||||
format: Format.unknown,
|
format: Format.unknown,
|
||||||
isExternal: true,
|
isExternal: true,
|
||||||
label: 'hoster.com',
|
label: 'hoster.com',
|
||||||
|
|
@ -137,106 +137,11 @@ describe('resolve', () => {
|
||||||
countryCodes: [CountryCode.de],
|
countryCodes: [CountryCode.de],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new BlockedError(new URL('https://example.com'), BlockedReason.cloudflare_challenge, {}),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new BlockedError(new URL('https://example.com'), BlockedReason.cloudflare_censor, {}),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new BlockedError(new URL('https://example.com'), BlockedReason.media_flow_proxy_auth, {}),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new BlockedError(new URL('https://example.com'), BlockedReason.unknown, {}),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://working2.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
label: 'working1',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new TooManyRequestsError(new URL('https://example.com'), 10),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new TooManyTimeoutsError(new URL('https://example.com')),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://working1.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
label: 'working2',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: new URL('https://example2.com'),
|
|
||||||
format: Format.unknown,
|
|
||||||
isExternal: true,
|
|
||||||
error: new TypeError(),
|
|
||||||
label: 'hoster.com',
|
|
||||||
ttl: this.ttl,
|
|
||||||
meta: {
|
|
||||||
countryCodes: [CountryCode.de],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
url: new URL('https://example2.com'),
|
url: new URL('https://example2.com'),
|
||||||
format: Format.unknown,
|
format: Format.unknown,
|
||||||
isExternal: true,
|
isExternal: true,
|
||||||
error: new TimeoutError(new URL('https://example2.com')),
|
error: new BlockedError(new URL('https://example2.com'), BlockedReason.cloudflare_challenge, {}),
|
||||||
label: 'hoster.com',
|
label: 'hoster.com',
|
||||||
ttl: this.ttl,
|
ttl: this.ttl,
|
||||||
meta: {
|
meta: {
|
||||||
|
|
@ -247,7 +152,7 @@ describe('resolve', () => {
|
||||||
url: new URL('https://example3.com'),
|
url: new URL('https://example3.com'),
|
||||||
format: Format.unknown,
|
format: Format.unknown,
|
||||||
isExternal: true,
|
isExternal: true,
|
||||||
error: new QueueIsFullError(new URL('https://example3.com')),
|
error: new BlockedError(new URL('https://example3.com'), BlockedReason.cloudflare_censor, {}),
|
||||||
label: 'hoster.com',
|
label: 'hoster.com',
|
||||||
ttl: this.ttl,
|
ttl: this.ttl,
|
||||||
meta: {
|
meta: {
|
||||||
|
|
@ -258,7 +163,7 @@ describe('resolve', () => {
|
||||||
url: new URL('https://example4.com'),
|
url: new URL('https://example4.com'),
|
||||||
format: Format.unknown,
|
format: Format.unknown,
|
||||||
isExternal: true,
|
isExternal: true,
|
||||||
error: new HttpError(new URL('https://example4.com'), 500, 'Internal Server Error', { 'x-foo': 'bar' }),
|
error: new BlockedError(new URL('https://example4.com'), BlockedReason.media_flow_proxy_auth, {}),
|
||||||
label: 'hoster.com',
|
label: 'hoster.com',
|
||||||
ttl: this.ttl,
|
ttl: this.ttl,
|
||||||
meta: {
|
meta: {
|
||||||
|
|
@ -269,7 +174,102 @@ describe('resolve', () => {
|
||||||
url: new URL('https://example5.com'),
|
url: new URL('https://example5.com'),
|
||||||
format: Format.unknown,
|
format: Format.unknown,
|
||||||
isExternal: true,
|
isExternal: true,
|
||||||
error: new HttpError(new URL('https://example5.com'), 418, 'I\'m a tea pot', { 'x-foo': 'bar' }),
|
error: new BlockedError(new URL('https://example5.com'), BlockedReason.unknown, {}),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example6.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
label: 'working1',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example7.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new TooManyRequestsError(new URL('https://example7.com'), 10),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example8.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new TooManyTimeoutsError(new URL('https://example8.com')),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example9.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
label: 'working2',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example10.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new TypeError(),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example11.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new TimeoutError(new URL('https://example11.com')),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example12.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new QueueIsFullError(new URL('https://example12.com')),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example13.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new HttpError(new URL('https://example13.com'), 500, 'Internal Server Error', { 'x-foo': 'bar' }),
|
||||||
|
label: 'hoster.com',
|
||||||
|
ttl: this.ttl,
|
||||||
|
meta: {
|
||||||
|
countryCodes: [CountryCode.de],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: new URL('https://example14.com'),
|
||||||
|
format: Format.unknown,
|
||||||
|
isExternal: true,
|
||||||
|
error: new HttpError(new URL('https://example14.com'), 418, 'I\'m a tea pot', { 'x-foo': 'bar' }),
|
||||||
label: 'hoster.com',
|
label: 'hoster.com',
|
||||||
ttl: this.ttl,
|
ttl: this.ttl,
|
||||||
meta: {
|
meta: {
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,10 @@ export class StreamResolver {
|
||||||
|
|
||||||
streams.push(
|
streams.push(
|
||||||
...urlResults.filter(urlResult => (!urlResult.error || showErrors(ctx.config)) && !isResolutionExcluded(ctx.config, getClosestResolution(urlResult.meta?.height)))
|
...urlResults.filter(urlResult => (!urlResult.error || showErrors(ctx.config)) && !isResolutionExcluded(ctx.config, getClosestResolution(urlResult.meta?.height)))
|
||||||
|
.filter((urlResult, index, self) =>
|
||||||
|
// Remove duplicate URLs
|
||||||
|
index === self.findIndex(t => t.url.href === urlResult.url.href),
|
||||||
|
)
|
||||||
.map(urlResult => ({
|
.map(urlResult => ({
|
||||||
...this.buildUrl(urlResult),
|
...this.buildUrl(urlResult),
|
||||||
name: this.buildName(ctx, urlResult),
|
name: this.buildName(ctx, urlResult),
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ exports[`resolve adds error info 1`] = `
|
||||||
},
|
},
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 working1",
|
"title": "🔗 working1",
|
||||||
"url": "https://working2.com/",
|
"url": "https://example6.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
|
|
@ -19,14 +19,14 @@ exports[`resolve adds error info 1`] = `
|
||||||
},
|
},
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 working2",
|
"title": "🔗 working2",
|
||||||
"url": "https://working1.com/",
|
"url": "https://example9.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example1.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com",
|
"title": "🔗 hoster.com",
|
||||||
},
|
},
|
||||||
|
|
@ -43,47 +43,47 @@ exports[`resolve adds error info 2`] = `
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example5.com/",
|
"externalUrl": "https://example14.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
❌ Request to example5.com failed with status 418 (I'm a tea pot). Request-id: test.",
|
❌ Request to example14.com failed with status 418 (I'm a tea pot). Request-id: test.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example4.com/",
|
"externalUrl": "https://example13.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
❌ Remote server example4.com has issues. We can't fix this, please try later again.",
|
❌ Remote server example13.com has issues. We can't fix this, please try later again.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example3.com/",
|
"externalUrl": "https://example12.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
⏳ Request queue for example3.com is full. Please try again later or consider self-hosting.",
|
⏳ Request queue for example12.com is full. Please try again later or consider self-hosting.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example2.com/",
|
"externalUrl": "https://example11.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
🐢 Request to example2.com timed out.",
|
🐢 Request to example11.com timed out.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example2.com/",
|
"externalUrl": "https://example10.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
❌ Request failed. Request-id: test.",
|
❌ Request failed. Request-id: test.",
|
||||||
|
|
@ -93,37 +93,37 @@ exports[`resolve adds error info 2`] = `
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example8.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
🚦 Too many recent timeouts when requesting example.com. Please try again later.",
|
🚦 Too many recent timeouts when requesting example8.com. Please try again later.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example7.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
🚦 Request to example.com was rate-limited. Please try again later or consider self-hosting.",
|
🚦 Request to example7.com was rate-limited. Please try again later or consider self-hosting.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example5.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
⚠️ Request to example.com was blocked. Reason: unknown",
|
⚠️ Request to example5.com was blocked. Reason: unknown",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example4.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
⚠️ MediaFlow Proxy authentication failed. Please set the correct password.",
|
⚠️ MediaFlow Proxy authentication failed. Please set the correct password.",
|
||||||
|
|
@ -133,20 +133,20 @@ exports[`resolve adds error info 2`] = `
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example3.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
⚠️ Request to example.com was blocked. Reason: cloudflare_censor",
|
⚠️ Request to example3.com was blocked. Reason: cloudflare_censor",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example2.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com
|
"title": "🔗 hoster.com
|
||||||
⚠️ Request to example.com was blocked. Reason: cloudflare_challenge",
|
⚠️ Request to example2.com was blocked. Reason: cloudflare_challenge",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
|
|
@ -155,7 +155,7 @@ exports[`resolve adds error info 2`] = `
|
||||||
},
|
},
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 working1",
|
"title": "🔗 working1",
|
||||||
"url": "https://working2.com/",
|
"url": "https://example6.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
|
|
@ -164,14 +164,14 @@ exports[`resolve adds error info 2`] = `
|
||||||
},
|
},
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 working2",
|
"title": "🔗 working2",
|
||||||
"url": "https://working1.com/",
|
"url": "https://example9.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"behaviorHints": {
|
"behaviorHints": {
|
||||||
"bingeGroup": "webstreamr-undefined-undefined-de",
|
"bingeGroup": "webstreamr-undefined-undefined-de",
|
||||||
"notWebReady": true,
|
"notWebReady": true,
|
||||||
},
|
},
|
||||||
"externalUrl": "https://example.com/",
|
"externalUrl": "https://example1.com/",
|
||||||
"name": "WebStreamr 🇩🇪",
|
"name": "WebStreamr 🇩🇪",
|
||||||
"title": "🔗 hoster.com",
|
"title": "🔗 hoster.com",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ exports[`buildManifest default manifest 1`] = `
|
||||||
"config": [
|
"config": [
|
||||||
{
|
{
|
||||||
"key": "multi",
|
"key": "multi",
|
||||||
"title": "Multi 🌐 (4KHDHub, RgShows, VidSrc, VixSrc)",
|
"title": "Multi 🌐 (4KHDHub, HDHub4u, RgShows, VidSrc, VixSrc)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -34,9 +34,14 @@ exports[`buildManifest default manifest 1`] = `
|
||||||
"title": "French 🇫🇷 (Frembed, FrenchCloud, Movix)",
|
"title": "French 🇫🇷 (Frembed, FrenchCloud, Movix)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "gu",
|
||||||
|
"title": "Gujarati 🇮🇳 (HDHub4u)",
|
||||||
|
"type": "checkbox",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "hi",
|
"key": "hi",
|
||||||
"title": "Hindi 🇮🇳 (4KHDHub)",
|
"title": "Hindi 🇮🇳 (4KHDHub, HDHub4u)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -44,19 +49,29 @@ exports[`buildManifest default manifest 1`] = `
|
||||||
"title": "Italian 🇮🇹 (Eurostreaming, MostraGuarda, VixSrc)",
|
"title": "Italian 🇮🇹 (Eurostreaming, MostraGuarda, VixSrc)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "ml",
|
||||||
|
"title": "Malayalam 🇮🇳 (HDHub4u)",
|
||||||
|
"type": "checkbox",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "mx",
|
"key": "mx",
|
||||||
"title": "Latin American Spanish 🇲🇽 (CineHDPlus, Cuevana, HomeCine, VerHdLink)",
|
"title": "Latin American Spanish 🇲🇽 (CineHDPlus, Cuevana, HomeCine, VerHdLink)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "pa",
|
||||||
|
"title": "Punjabi 🇮🇳 (HDHub4u)",
|
||||||
|
"type": "checkbox",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "ta",
|
"key": "ta",
|
||||||
"title": "Tamil 🇮🇳 (4KHDHub)",
|
"title": "Tamil 🇮🇳 (4KHDHub, HDHub4u)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "te",
|
"key": "te",
|
||||||
"title": "Telugu 🇮🇳 (4KHDHub)",
|
"title": "Telugu 🇮🇳 (4KHDHub, HDHub4u)",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -134,9 +149,9 @@ exports[`buildManifest default manifest 1`] = `
|
||||||
],
|
],
|
||||||
"description": "Provides HTTP URLs from streaming websites. Configure add-on for additional languages. Add MediaFlow proxy for more URLs.
|
"description": "Provides HTTP URLs from streaming websites. Configure add-on for additional languages. Add MediaFlow proxy for more URLs.
|
||||||
|
|
||||||
Supported languages: Albanian, German, Castilian Spanish, French, Hindi, Italian, Latin American Spanish, Tamil, Telugu
|
Supported languages: Albanian, German, Castilian Spanish, French, Gujarati, Hindi, Italian, Malayalam, Latin American Spanish, Punjabi, Tamil, Telugu
|
||||||
|
|
||||||
Supported sources: 4KHDHub, CineHDPlus, Cuevana, Einschalten, Eurostreaming, Frembed, FrenchCloud, HomeCine, KinoGer, Kokoshka, MegaKino, MeineCloud, MostraGuarda, Movix, RgShows, StreamKiste, VerHdLink, VidSrc, VixSrc
|
Supported sources: 4KHDHub, CineHDPlus, Cuevana, Einschalten, Eurostreaming, Frembed, FrenchCloud, HDHub4u, HomeCine, KinoGer, Kokoshka, MegaKino, MeineCloud, MostraGuarda, Movix, RgShows, StreamKiste, VerHdLink, VidSrc, VixSrc
|
||||||
|
|
||||||
Supported extractors: ",
|
Supported extractors: ",
|
||||||
"id": "webstreamr",
|
"id": "webstreamr",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const typedEntries = <T extends object>(obj: T): [keyof T, T[keyof T]][] => (Obj
|
||||||
export const buildManifest = (sources: Source[], extractors: Extractor[], config: Config): CustomManifest => {
|
export const buildManifest = (sources: Source[], extractors: Extractor[], config: Config): CustomManifest => {
|
||||||
const manifest: CustomManifest = {
|
const manifest: CustomManifest = {
|
||||||
id: envGetAppId(),
|
id: envGetAppId(),
|
||||||
version: '0.68.0', // x-release-please-version
|
version: '0.69.1', // x-release-please-version
|
||||||
name: envGetAppName(),
|
name: envGetAppName(),
|
||||||
description: 'Provides HTTP URLs from streaming websites. Configure add-on for additional languages. Add MediaFlow proxy for more URLs.',
|
description: 'Provides HTTP URLs from streaming websites. Configure add-on for additional languages. Add MediaFlow proxy for more URLs.',
|
||||||
resources: [
|
resources: [
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,11 @@ export const getClosestResolution = (height: number | undefined) => {
|
||||||
return Math.abs(curr - height) < Math.abs(prev - height) ? curr : prev;
|
return Math.abs(curr - height) < Math.abs(prev - height) ? curr : prev;
|
||||||
})}p`;
|
})}p`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const findHeight = (value: string): number | undefined => {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
const height = parseInt(RESOLUTIONS.find(res => value.toLowerCase().includes(res))?.replace('p', '') ?? '', 10);
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
return isNaN(height) ? undefined : height;
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue