diff --git a/dist/4khdhub/catalog.js b/dist/4khdhub/catalog.js
new file mode 100644
index 0000000..44e9eae
--- /dev/null
+++ b/dist/4khdhub/catalog.js
@@ -0,0 +1,22 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.genres = exports.catalog = void 0;
+exports.catalog = [
+ {
+ title: "Popular Movies",
+ filter: "/category/new-movies-10810.html",
+ },
+ {
+ title: "Latest TV Shows",
+ filter: "/category/new-series-10811.html",
+ },
+ {
+ title: "Anime",
+ filter: "/category/anime-10812.html",
+ },
+ {
+ title: "4K HDR",
+ filter: "/category/4k-hdr-10776.html",
+ },
+];
+exports.genres = [];
diff --git a/dist/4khdhub/meta.js b/dist/4khdhub/meta.js
new file mode 100644
index 0000000..f0ac9e0
--- /dev/null
+++ b/dist/4khdhub/meta.js
@@ -0,0 +1,97 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getMeta = void 0;
+const getMeta = function (_a) {
+ return __awaiter(this, arguments, void 0, function* ({ link, providerContext, }) {
+ try {
+ const { axios, cheerio, getBaseUrl } = providerContext;
+ const baseUrl = yield getBaseUrl("4khdhub");
+ const url = `${baseUrl}${link}`;
+ const res = yield axios.get(url);
+ const data = res.data;
+ const $ = cheerio.load(data);
+ const type = $(".season-content").length > 0 ? "series" : "movie";
+ const imdbId = "";
+ const title = $(".page-title").text() || "";
+ const image = $(".poster-image").find("img").attr("src") || "";
+ const synopsis = $(".content-section").find("p").first().text().trim() || "";
+ // Links
+ const links = [];
+ if (type === "series") {
+ $(".season-item").map((i, element) => {
+ const title = $(element).find(".episode-title").text();
+ let directLinks = [];
+ $(element)
+ .find(".episode-download-item")
+ .map((i, element) => {
+ const title = $(element)
+ .find(".episode-file-info")
+ .text()
+ .trim()
+ .replace("\n", " ");
+ const link = $(element)
+ .find(".episode-links")
+ .find("a:contains('HubDrive')")
+ .attr("href");
+ console.log("title⭐", title, "link", link);
+ if (title && link) {
+ directLinks.push({ title, link });
+ }
+ });
+ if (title && directLinks.length > 0) {
+ links.push({
+ title,
+ directLinks: directLinks,
+ });
+ }
+ });
+ }
+ else {
+ $(".download-item").map((i, element) => {
+ const title = $(element)
+ .find(".flex-1.text-left.font-semibold")
+ .text()
+ .trim();
+ const link = $(element)
+ .find(".grid.grid-cols-2.gap-2")
+ .find("a:contains('HubDrive')")
+ .attr("href");
+ // console.log("title⭐", title, "link", link);
+ if (title && link) {
+ links.push({ title, directLinks: [{ title, link }] });
+ }
+ });
+ }
+ // console.log('multi meta', links);
+ return {
+ title,
+ synopsis,
+ image,
+ imdbId,
+ type,
+ linkList: links,
+ };
+ }
+ catch (err) {
+ console.error(err);
+ return {
+ title: "",
+ synopsis: "",
+ image: "",
+ imdbId: "",
+ type: "movie",
+ linkList: [],
+ };
+ }
+ });
+};
+exports.getMeta = getMeta;
diff --git a/dist/4khdhub/posts.js b/dist/4khdhub/posts.js
new file mode 100644
index 0000000..b02b2eb
--- /dev/null
+++ b/dist/4khdhub/posts.js
@@ -0,0 +1,68 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getSearchPosts = exports.getPosts = void 0;
+const getPosts = function (_a) {
+ return __awaiter(this, arguments, void 0, function* ({ filter, page, signal, providerContext, }) {
+ const { getBaseUrl, cheerio } = providerContext;
+ const baseUrl = yield getBaseUrl("4khdhub");
+ const url = `${baseUrl + filter}/page/${page}.html`;
+ console.log("4khdhubGetPosts url", url);
+ return posts({ url, signal, cheerio });
+ });
+};
+exports.getPosts = getPosts;
+const getSearchPosts = function (_a) {
+ return __awaiter(this, arguments, void 0, function* ({ searchQuery, page, signal, providerContext, }) {
+ const { getBaseUrl, cheerio } = providerContext;
+ const baseUrl = yield getBaseUrl("4khdhub");
+ const url = `${baseUrl}/page/${page}.html?s=hin${searchQuery}`;
+ return posts({ url, signal, cheerio });
+ });
+};
+exports.getSearchPosts = getSearchPosts;
+function posts(_a) {
+ return __awaiter(this, arguments, void 0, function* ({ url, signal, cheerio, }) {
+ try {
+ const res = yield fetch(url, { signal });
+ const data = yield res.text();
+ const $ = cheerio.load(data);
+ const catalog = [];
+ $(".card-grid")
+ .children()
+ .map((i, element) => {
+ const title = $(element).find(".movie-card-title").text();
+ const link = $(element).attr("href");
+ const image = $(element).find("img").attr("src");
+ // console.log(
+ // "4khdhubGetPosts title",
+ // title,
+ // "link",
+ // link,
+ // "image",
+ // image
+ // );
+ if (title && link && image) {
+ catalog.push({
+ title: title,
+ link: link,
+ image: image,
+ });
+ }
+ });
+ return catalog;
+ }
+ catch (err) {
+ console.error("4khdhubGetPosts error ", err);
+ return [];
+ }
+ });
+}
diff --git a/dist/4khdhub/stream.js b/dist/4khdhub/stream.js
new file mode 100644
index 0000000..3d9790b
--- /dev/null
+++ b/dist/4khdhub/stream.js
@@ -0,0 +1,164 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getStream = getStream;
+exports.getRedirectLinks = getRedirectLinks;
+exports.decodeString = decodeString;
+function getStream(_a) {
+ return __awaiter(this, arguments, void 0, function* ({ link, signal, providerContext, }) {
+ var _b, _c, _d, _e;
+ const { axios, cheerio, extractors, commonHeaders: headers, } = providerContext;
+ const { hubcloudExtracter } = extractors;
+ let hubdriveLink = "";
+ if (link.includes("hubdrive")) {
+ const hubdriveRes = yield axios.get(link, { headers, signal });
+ const hubdriveText = hubdriveRes.data;
+ const $ = cheerio.load(hubdriveText);
+ hubdriveLink =
+ $(".btn.btn-primary.btn-user.btn-success1.m-1").attr("href") || link;
+ }
+ else {
+ const res = yield axios.get(link, { headers, signal });
+ const text = res.data;
+ const encryptedString = (_d = (_c = (_b = text.split("s('o','")) === null || _b === void 0 ? void 0 : _b[1]) === null || _c === void 0 ? void 0 : _c.split("',180")) === null || _d === void 0 ? void 0 : _d[0];
+ const decodedString = decodeString(encryptedString);
+ link = atob(decodedString === null || decodedString === void 0 ? void 0 : decodedString.o);
+ const redirectLink = yield getRedirectLinks(link, signal, headers);
+ const redirectLinkRes = yield axios.get(redirectLink, { headers, signal });
+ const redirectLinkText = redirectLinkRes.data;
+ const $ = cheerio.load(redirectLinkText);
+ hubdriveLink =
+ $('h3:contains("1080p")').find("a").attr("href") ||
+ redirectLinkText.match(/href="(https:\/\/hubcloud\.[^\/]+\/drive\/[^"]+)"/)[1];
+ if (hubdriveLink.includes("hubdrive")) {
+ const hubdriveRes = yield axios.get(hubdriveLink, { headers, signal });
+ const hubdriveText = hubdriveRes.data;
+ const $$ = cheerio.load(hubdriveText);
+ hubdriveLink =
+ $$(".btn.btn-primary.btn-user.btn-success1.m-1").attr("href") ||
+ hubdriveLink;
+ }
+ }
+ const hubdriveLinkRes = yield axios.get(hubdriveLink, { headers, signal });
+ const hubcloudText = hubdriveLinkRes.data;
+ const hubcloudLink = ((_e = hubcloudText.match(//i)) === null || _e === void 0 ? void 0 : _e[1]) || hubdriveLink;
+ try {
+ return yield hubcloudExtracter(hubcloudLink, signal);
+ }
+ catch (error) {
+ console.log("hd hub 4 getStream error: ", error);
+ return [];
+ }
+ });
+}
+const encode = function (value) {
+ return btoa(value.toString());
+};
+const decode = function (value) {
+ if (value === undefined) {
+ return "";
+ }
+ return atob(value.toString());
+};
+const pen = function (value) {
+ return value.replace(/[a-zA-Z]/g, function (_0x1a470e) {
+ return String.fromCharCode((_0x1a470e <= "Z" ? 90 : 122) >=
+ (_0x1a470e = _0x1a470e.charCodeAt(0) + 13)
+ ? _0x1a470e
+ : _0x1a470e - 26);
+ });
+};
+const abortableTimeout = (ms, { signal } = {}) => {
+ return new Promise((resolve, reject) => {
+ if (signal && signal.aborted) {
+ return reject(new Error("Aborted"));
+ }
+ const timer = setTimeout(resolve, ms);
+ if (signal) {
+ signal.addEventListener("abort", () => {
+ clearTimeout(timer);
+ reject(new Error("Aborted"));
+ });
+ }
+ });
+};
+function getRedirectLinks(link, signal, headers) {
+ return __awaiter(this, void 0, void 0, function* () {
+ try {
+ const res = yield fetch(link, { headers, signal });
+ const resText = yield res.text();
+ var regex = /ck\('_wp_http_\d+','([^']+)'/g;
+ var combinedString = "";
+ var match;
+ while ((match = regex.exec(resText)) !== null) {
+ // console.log(match[1]);
+ combinedString += match[1];
+ }
+ // console.log(decode(combinedString));
+ const decodedString = decode(pen(decode(decode(combinedString))));
+ // console.log(decodedString);
+ const data = JSON.parse(decodedString);
+ console.log(data);
+ const token = encode(data === null || data === void 0 ? void 0 : data.data);
+ const blogLink = (data === null || data === void 0 ? void 0 : data.wp_http1) + "?re=" + token;
+ // abort timeout on signal
+ let wait = abortableTimeout((Number(data === null || data === void 0 ? void 0 : data.total_time) + 3) * 1000, {
+ signal,
+ });
+ yield wait;
+ console.log("blogLink", blogLink);
+ let vcloudLink = "Invalid Request";
+ while (vcloudLink.includes("Invalid Request")) {
+ const blogRes = yield fetch(blogLink, { headers, signal });
+ const blogResText = (yield blogRes.text());
+ if (blogResText.includes("Invalid Request")) {
+ console.log(blogResText);
+ }
+ else {
+ vcloudLink = blogResText.match(/var reurl = "([^"]+)"/) || "";
+ break;
+ }
+ }
+ // console.log('vcloudLink', vcloudLink?.[1]);
+ return blogLink || link;
+ }
+ catch (err) {
+ console.log("Error in getRedirectLinks", err);
+ return link;
+ }
+ });
+}
+function rot13(str) {
+ return str.replace(/[a-zA-Z]/g, function (char) {
+ const charCode = char.charCodeAt(0);
+ const isUpperCase = char <= "Z";
+ const baseCharCode = isUpperCase ? 65 : 97;
+ return String.fromCharCode(((charCode - baseCharCode + 13) % 26) + baseCharCode);
+ });
+}
+function decodeString(encryptedString) {
+ try {
+ // First base64 decode
+ let decoded = atob(encryptedString);
+ // Second base64 decode
+ decoded = atob(decoded);
+ // ROT13 decode
+ decoded = rot13(decoded);
+ // Third base64 decode
+ decoded = atob(decoded);
+ // Parse JSON
+ return JSON.parse(decoded);
+ }
+ catch (error) {
+ console.error("Error decoding string:", error);
+ return null;
+ }
+}
diff --git a/manifest.json b/manifest.json
index 07ffdb5..a3b158d 100644
--- a/manifest.json
+++ b/manifest.json
@@ -31,6 +31,14 @@
"type": "global",
"disabled": false
},
+ {
+ "display_name": "4khdHub",
+ "value": "4khdhub",
+ "version": "1.0",
+ "icon": "",
+ "type": "global",
+ "disabled": false
+ },
{
"display_name": "World4uFree",
"value": "world4u",
diff --git a/providers/4khdhub/catalog.ts b/providers/4khdhub/catalog.ts
new file mode 100644
index 0000000..99734f6
--- /dev/null
+++ b/providers/4khdhub/catalog.ts
@@ -0,0 +1,20 @@
+export const catalog = [
+ {
+ title: "Popular Movies",
+ filter: "/category/new-movies-10810.html",
+ },
+ {
+ title: "Latest TV Shows",
+ filter: "/category/new-series-10811.html",
+ },
+ {
+ title: "Anime",
+ filter: "/category/anime-10812.html",
+ },
+ {
+ title: "4K HDR",
+ filter: "/category/4k-hdr-10776.html",
+ },
+];
+
+export const genres = [];
diff --git a/providers/4khdhub/meta.ts b/providers/4khdhub/meta.ts
new file mode 100644
index 0000000..fa8e57b
--- /dev/null
+++ b/providers/4khdhub/meta.ts
@@ -0,0 +1,92 @@
+import { Info, Link, ProviderContext } from "../types";
+
+export const getMeta = async function ({
+ link,
+ providerContext,
+}: {
+ link: string;
+ providerContext: ProviderContext;
+}): Promise {
+ try {
+ const { axios, cheerio, getBaseUrl } = providerContext;
+ const baseUrl = await getBaseUrl("4khdhub");
+ const url = `${baseUrl}${link}`;
+ const res = await axios.get(url);
+ const data = res.data;
+ const $ = cheerio.load(data);
+ const type = $(".season-content").length > 0 ? "series" : "movie";
+ const imdbId = "";
+ const title = $(".page-title").text() || "";
+ const image = $(".poster-image").find("img").attr("src") || "";
+ const synopsis =
+ $(".content-section").find("p").first().text().trim() || "";
+
+ // Links
+ const links: Link[] = [];
+
+ if (type === "series") {
+ $(".season-item").map((i, element) => {
+ const title = $(element).find(".episode-title").text();
+ let directLinks: Link["directLinks"] = [];
+ $(element)
+ .find(".episode-download-item")
+ .map((i, element) => {
+ const title = $(element)
+ .find(".episode-file-info")
+ .text()
+ .trim()
+ .replace("\n", " ");
+ const link = $(element)
+ .find(".episode-links")
+ .find("a:contains('HubDrive')")
+ .attr("href");
+ console.log("title⭐", title, "link", link);
+ if (title && link) {
+ directLinks.push({ title, link });
+ }
+ });
+ if (title && directLinks.length > 0) {
+ links.push({
+ title,
+ directLinks: directLinks,
+ });
+ }
+ });
+ } else {
+ $(".download-item").map((i, element) => {
+ const title = $(element)
+ .find(".flex-1.text-left.font-semibold")
+ .text()
+ .trim();
+ const link = $(element)
+ .find(".grid.grid-cols-2.gap-2")
+ .find("a:contains('HubDrive')")
+ .attr("href");
+ // console.log("title⭐", title, "link", link);
+ if (title && link) {
+ links.push({ title, directLinks: [{ title, link }] });
+ }
+ });
+ }
+ // console.log('multi meta', links);
+
+ return {
+ title,
+ synopsis,
+ image,
+ imdbId,
+ type,
+ linkList: links,
+ };
+ } catch (err) {
+ console.error(err);
+ return {
+ title: "",
+ synopsis: "",
+ image: "",
+ imdbId: "",
+ type: "movie",
+ linkList: [],
+ };
+ }
+};
diff --git a/providers/4khdhub/posts.ts b/providers/4khdhub/posts.ts
new file mode 100644
index 0000000..2436e49
--- /dev/null
+++ b/providers/4khdhub/posts.ts
@@ -0,0 +1,81 @@
+import { Post, ProviderContext } from "../types";
+
+export const getPosts = async function ({
+ filter,
+ page,
+ signal,
+ providerContext,
+}: {
+ filter: string;
+ page: number;
+ providerValue: string;
+ signal: AbortSignal;
+ providerContext: ProviderContext;
+}): Promise {
+ const { getBaseUrl, cheerio } = providerContext;
+ const baseUrl = await getBaseUrl("4khdhub");
+ const url = `${baseUrl + filter}/page/${page}.html`;
+ console.log("4khdhubGetPosts url", url);
+ return posts({ url, signal, cheerio });
+};
+
+export const getSearchPosts = async function ({
+ searchQuery,
+ page,
+ signal,
+ providerContext,
+}: {
+ searchQuery: string;
+ page: number;
+ providerValue: string;
+ signal: AbortSignal;
+ providerContext: ProviderContext;
+}): Promise {
+ const { getBaseUrl, cheerio } = providerContext;
+ const baseUrl = await getBaseUrl("4khdhub");
+ const url = `${baseUrl}/page/${page}.html?s=hin${searchQuery}`;
+ return posts({ url, signal, cheerio });
+};
+
+async function posts({
+ url,
+ signal,
+ cheerio,
+}: {
+ url: string;
+ signal: AbortSignal;
+ cheerio: ProviderContext["cheerio"];
+}): Promise {
+ try {
+ const res = await fetch(url, { signal });
+ const data = await res.text();
+ const $ = cheerio.load(data);
+ const catalog: Post[] = [];
+ $(".card-grid")
+ .children()
+ .map((i, element) => {
+ const title = $(element).find(".movie-card-title").text();
+ const link = $(element).attr("href");
+ const image = $(element).find("img").attr("src");
+ // console.log(
+ // "4khdhubGetPosts title",
+ // title,
+ // "link",
+ // link,
+ // "image",
+ // image
+ // );
+ if (title && link && image) {
+ catalog.push({
+ title: title,
+ link: link,
+ image: image,
+ });
+ }
+ });
+ return catalog;
+ } catch (err) {
+ console.error("4khdhubGetPosts error ", err);
+ return [];
+ }
+}
diff --git a/providers/4khdhub/stream.ts b/providers/4khdhub/stream.ts
new file mode 100644
index 0000000..62f2503
--- /dev/null
+++ b/providers/4khdhub/stream.ts
@@ -0,0 +1,188 @@
+import { ProviderContext } from "../types";
+
+export async function getStream({
+ link,
+ signal,
+ providerContext,
+}: {
+ link: string;
+ type: string;
+ signal: AbortSignal;
+ providerContext: ProviderContext;
+}) {
+ const {
+ axios,
+ cheerio,
+ extractors,
+ commonHeaders: headers,
+ } = providerContext;
+ const { hubcloudExtracter } = extractors;
+ let hubdriveLink = "";
+ if (link.includes("hubdrive")) {
+ const hubdriveRes = await axios.get(link, { headers, signal });
+ const hubdriveText = hubdriveRes.data;
+ const $ = cheerio.load(hubdriveText);
+ hubdriveLink =
+ $(".btn.btn-primary.btn-user.btn-success1.m-1").attr("href") || link;
+ } else {
+ const res = await axios.get(link, { headers, signal });
+ const text = res.data;
+ const encryptedString = text.split("s('o','")?.[1]?.split("',180")?.[0];
+ const decodedString: any = decodeString(encryptedString);
+ link = atob(decodedString?.o);
+ const redirectLink = await getRedirectLinks(link, signal, headers);
+ const redirectLinkRes = await axios.get(redirectLink, { headers, signal });
+ const redirectLinkText = redirectLinkRes.data;
+ const $ = cheerio.load(redirectLinkText);
+ hubdriveLink =
+ $('h3:contains("1080p")').find("a").attr("href") ||
+ redirectLinkText.match(
+ /href="(https:\/\/hubcloud\.[^\/]+\/drive\/[^"]+)"/
+ )[1];
+ if (hubdriveLink.includes("hubdrive")) {
+ const hubdriveRes = await axios.get(hubdriveLink, { headers, signal });
+ const hubdriveText = hubdriveRes.data;
+ const $$ = cheerio.load(hubdriveText);
+ hubdriveLink =
+ $$(".btn.btn-primary.btn-user.btn-success1.m-1").attr("href") ||
+ hubdriveLink;
+ }
+ }
+ const hubdriveLinkRes = await axios.get(hubdriveLink, { headers, signal });
+ const hubcloudText = hubdriveLinkRes.data;
+ const hubcloudLink =
+ hubcloudText.match(
+ //i
+ )?.[1] || hubdriveLink;
+ try {
+ return await hubcloudExtracter(hubcloudLink, signal);
+ } catch (error: any) {
+ console.log("hd hub 4 getStream error: ", error);
+ return [];
+ }
+}
+
+const encode = function (value: string) {
+ return btoa(value.toString());
+};
+const decode = function (value: string) {
+ if (value === undefined) {
+ return "";
+ }
+ return atob(value.toString());
+};
+const pen = function (value: string) {
+ return value.replace(/[a-zA-Z]/g, function (_0x1a470e: any) {
+ return String.fromCharCode(
+ (_0x1a470e <= "Z" ? 90 : 122) >=
+ (_0x1a470e = _0x1a470e.charCodeAt(0) + 13)
+ ? _0x1a470e
+ : _0x1a470e - 26
+ );
+ });
+};
+
+const abortableTimeout = (
+ ms: number,
+ { signal }: { signal?: AbortSignal } = {}
+) => {
+ return new Promise((resolve, reject) => {
+ if (signal && signal.aborted) {
+ return reject(new Error("Aborted"));
+ }
+
+ const timer = setTimeout(resolve, ms);
+
+ if (signal) {
+ signal.addEventListener("abort", () => {
+ clearTimeout(timer);
+ reject(new Error("Aborted"));
+ });
+ }
+ });
+};
+
+export async function getRedirectLinks(
+ link: string,
+ signal: AbortSignal,
+ headers: any
+) {
+ try {
+ const res = await fetch(link, { headers, signal });
+ const resText = await res.text();
+
+ var regex = /ck\('_wp_http_\d+','([^']+)'/g;
+ var combinedString = "";
+
+ var match;
+ while ((match = regex.exec(resText)) !== null) {
+ // console.log(match[1]);
+ combinedString += match[1];
+ }
+ // console.log(decode(combinedString));
+ const decodedString = decode(pen(decode(decode(combinedString))));
+ // console.log(decodedString);
+ const data = JSON.parse(decodedString);
+ console.log(data);
+ const token = encode(data?.data);
+ const blogLink = data?.wp_http1 + "?re=" + token;
+ // abort timeout on signal
+ let wait = abortableTimeout((Number(data?.total_time) + 3) * 1000, {
+ signal,
+ });
+
+ await wait;
+ console.log("blogLink", blogLink);
+
+ let vcloudLink = "Invalid Request";
+ while (vcloudLink.includes("Invalid Request")) {
+ const blogRes = await fetch(blogLink, { headers, signal });
+ const blogResText = (await blogRes.text()) as any;
+ if (blogResText.includes("Invalid Request")) {
+ console.log(blogResText);
+ } else {
+ vcloudLink = blogResText.match(/var reurl = "([^"]+)"/) || "";
+ break;
+ }
+ }
+
+ // console.log('vcloudLink', vcloudLink?.[1]);
+ return blogLink || link;
+ } catch (err) {
+ console.log("Error in getRedirectLinks", err);
+ return link;
+ }
+}
+
+function rot13(str: string) {
+ return str.replace(/[a-zA-Z]/g, function (char) {
+ const charCode = char.charCodeAt(0);
+ const isUpperCase = char <= "Z";
+ const baseCharCode = isUpperCase ? 65 : 97;
+ return String.fromCharCode(
+ ((charCode - baseCharCode + 13) % 26) + baseCharCode
+ );
+ });
+}
+
+export function decodeString(encryptedString: string) {
+ try {
+ // First base64 decode
+ let decoded = atob(encryptedString);
+
+ // Second base64 decode
+ decoded = atob(decoded);
+
+ // ROT13 decode
+ decoded = rot13(decoded);
+
+ // Third base64 decode
+ decoded = atob(decoded);
+
+ // Parse JSON
+ return JSON.parse(decoded);
+ } catch (error) {
+ console.error("Error decoding string:", error);
+ return null;
+ }
+}