mirror of
https://github.com/vega-org/vega-providers.git
synced 2026-04-17 15:41:45 +00:00
refactor: streamline provider testing utility and remove deprecated test configurations
This commit is contained in:
@@ -8,10 +8,8 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test-providers.js",
|
"test": "node test-providers.js",
|
||||||
|
"test:single": "node test-providers.js",
|
||||||
"test:provider": "node test-provider.js",
|
"test:provider": "node test-provider.js",
|
||||||
"test:provider:build": "npm run build && node test-provider.js",
|
|
||||||
"test:interactive": "npm run build && node interactive-test.js",
|
|
||||||
"test:quick": "npm run build && node quick-test.js",
|
|
||||||
"test:ui": "npm run test:interactive",
|
"test:ui": "npm run test:interactive",
|
||||||
"build": "node build-simple.js",
|
"build": "node build-simple.js",
|
||||||
"build:dev": "cross-env SKIP_MINIFY=true node build-simple.js",
|
"build:dev": "cross-env SKIP_MINIFY=true node build-simple.js",
|
||||||
|
|||||||
111
test-config.js
111
test-config.js
@@ -1,111 +0,0 @@
|
|||||||
// Common test configurations
|
|
||||||
// You can customize these and run them quickly
|
|
||||||
|
|
||||||
const testConfigs = {
|
|
||||||
// UHD Tests
|
|
||||||
uhdMeta: {
|
|
||||||
provider: "uhd",
|
|
||||||
module: "meta",
|
|
||||||
function: "getMeta",
|
|
||||||
params: {
|
|
||||||
link: "https://uhdmovies.email/download-squid-game-season-2-hindi-1080p-2160p-4k/",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// LuxMovies Tests
|
|
||||||
luxPosts: {
|
|
||||||
provider: "luxMovies",
|
|
||||||
module: "posts",
|
|
||||||
function: "getPosts",
|
|
||||||
params: {
|
|
||||||
url: "https://rogmovies.sbs/page/1/?s=pan",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// PrimeMirror Tests
|
|
||||||
primeMirrorEpisodes: {
|
|
||||||
provider: "primeMirror",
|
|
||||||
module: "episodes",
|
|
||||||
function: "getEpisodes",
|
|
||||||
params: {
|
|
||||||
url: "0KMA7H0RHEPJA51SUBXKN9V6VA",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
primeMirrorMeta: {
|
|
||||||
provider: "primeMirror",
|
|
||||||
module: "meta",
|
|
||||||
function: "getMeta",
|
|
||||||
params: {
|
|
||||||
link: "https://www.netflixmirror.com/title/82020512",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
primeMirrorSearch: {
|
|
||||||
provider: "primeMirror",
|
|
||||||
module: "posts",
|
|
||||||
function: "getSearchPosts",
|
|
||||||
params: {
|
|
||||||
searchQuery: "breaking",
|
|
||||||
page: 1,
|
|
||||||
providerValue: "primeMirror",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// CinemaLuxe Tests
|
|
||||||
cinemaLuxeEpisodes: {
|
|
||||||
provider: "cinemaLuxe",
|
|
||||||
module: "episodes",
|
|
||||||
function: "getEpisodes",
|
|
||||||
params: {
|
|
||||||
url: "https://cinemalux.net/?88fdac61e5=cVQxdnNXeGRIRXlZTEQ0bTZSZlFsT09qclNlQzExOUNwVk5JZ05JK1ZjbzVxSWt1SHZSZjdZUm5vVnZEOEd1QXlrdXhPdnNETHRHTnpPUUNFN3k3VVdpY0J0OW5rem10c1ZlZ2xRcjI2YjFWRm9Uc3FEeEd0aWZlNFBpOHJ6bms=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// Add more test configurations here as needed
|
|
||||||
// Template:
|
|
||||||
// yourTestName: {
|
|
||||||
// provider: 'providerName',
|
|
||||||
// module: 'moduleName',
|
|
||||||
// function: 'functionName',
|
|
||||||
// params: {
|
|
||||||
// // your parameters here
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Predefined test batches
|
|
||||||
const testBatches = {
|
|
||||||
// Test all meta functions
|
|
||||||
allMeta: [
|
|
||||||
testConfigs.uhdMeta,
|
|
||||||
testConfigs.primeMirrorMeta,
|
|
||||||
// Add more meta tests
|
|
||||||
],
|
|
||||||
|
|
||||||
// Test all posts/search functions
|
|
||||||
allPosts: [
|
|
||||||
testConfigs.luxPosts,
|
|
||||||
testConfigs.primeMirrorSearch,
|
|
||||||
// Add more posts tests
|
|
||||||
],
|
|
||||||
|
|
||||||
// Test all episode functions
|
|
||||||
allEpisodes: [
|
|
||||||
testConfigs.primeMirrorEpisodes,
|
|
||||||
testConfigs.cinemaLuxeEpisodes,
|
|
||||||
// Add more episode tests
|
|
||||||
],
|
|
||||||
|
|
||||||
// Quick smoke test - test one function from each major provider
|
|
||||||
smokeTest: [
|
|
||||||
testConfigs.uhdMeta,
|
|
||||||
testConfigs.luxPosts,
|
|
||||||
testConfigs.primeMirrorSearch,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
testConfigs,
|
|
||||||
testBatches,
|
|
||||||
};
|
|
||||||
@@ -1,188 +1,590 @@
|
|||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
|
const cheerio = require("cheerio");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
|
// Load extractors and utilities
|
||||||
|
let providerContext;
|
||||||
|
try {
|
||||||
|
const { getBaseUrl } = require("./dist/getBaseUrl.js");
|
||||||
|
const { hubcloudExtracter } = require("./dist/hubcloudExtractor.js");
|
||||||
|
const { gofileExtracter } = require("./dist/gofileExtracter.js");
|
||||||
|
const { superVideoExtractor } = require("./dist/superVideoExtractor.js");
|
||||||
|
const { gdFlixExtracter } = require("./dist/gdFlixExtractor.js");
|
||||||
|
|
||||||
|
providerContext = {
|
||||||
|
axios,
|
||||||
|
cheerio,
|
||||||
|
getBaseUrl,
|
||||||
|
commonHeaders: {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||||
|
},
|
||||||
|
extractors: {
|
||||||
|
hubcloudExtracter,
|
||||||
|
gofileExtracter,
|
||||||
|
superVideoExtractor,
|
||||||
|
gdFlixExtracter,
|
||||||
|
},
|
||||||
|
Crypto: {},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.log(
|
||||||
|
"⚠️ Could not load provider context. Run 'npm run build' first."
|
||||||
|
);
|
||||||
|
providerContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider testing utility
|
* Helper to pick random items from array
|
||||||
|
*/
|
||||||
|
function pickRandom(arr, count = 1) {
|
||||||
|
const shuffled = [...arr].sort(() => Math.random() - 0.5);
|
||||||
|
return count === 1 ? shuffled[0] : shuffled.slice(0, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep helper
|
||||||
|
*/
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider testing utility - Full integration test
|
||||||
*/
|
*/
|
||||||
class ProviderTester {
|
class ProviderTester {
|
||||||
constructor(serverUrl = "http://localhost:3001") {
|
constructor(options = {}) {
|
||||||
this.serverUrl = serverUrl;
|
this.timeout = options.timeout || 30000;
|
||||||
this.axios = axios.create({
|
this.postsToTest = options.postsToTest || 2;
|
||||||
baseURL: serverUrl,
|
this.linksToTest = options.linksToTest || 2;
|
||||||
timeout: 10000,
|
this.signal = new AbortController().signal;
|
||||||
});
|
this.results = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test server connectivity
|
* Load provider module
|
||||||
*/
|
*/
|
||||||
async testConnection() {
|
loadModule(providerName, moduleName) {
|
||||||
try {
|
try {
|
||||||
const response = await this.axios.get("/health");
|
const modulePath = `./dist/${providerName}/${moduleName}.js`;
|
||||||
console.log("✅ Server connection OK");
|
// Clear cache to get fresh module
|
||||||
return true;
|
delete require.cache[require.resolve(modulePath)];
|
||||||
|
return require(modulePath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ Server connection failed:", error.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test manifest endpoint
|
|
||||||
*/
|
|
||||||
async testManifest() {
|
|
||||||
try {
|
|
||||||
const response = await this.axios.get("/manifest.json");
|
|
||||||
const providers = response.data;
|
|
||||||
|
|
||||||
console.log(`✅ Manifest OK - Found ${providers.length} providers:`);
|
|
||||||
providers.forEach((p) => {
|
|
||||||
console.log(` 📦 ${p.display_name} (${p.value}) v${p.version}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
return providers;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("❌ Manifest test failed:", error.message);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test individual provider modules
|
* Load manifest to get enabled providers
|
||||||
|
*/
|
||||||
|
loadManifest() {
|
||||||
|
try {
|
||||||
|
const manifestPath = path.join(__dirname, "manifest.json");
|
||||||
|
if (!fs.existsSync(manifestPath)) {
|
||||||
|
console.log("⚠️ manifest.json not found");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
||||||
|
return manifest;
|
||||||
|
} catch (error) {
|
||||||
|
console.log("⚠️ Failed to load manifest:", error.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get available providers from dist folder (excluding disabled ones)
|
||||||
|
*/
|
||||||
|
getAvailableProviders() {
|
||||||
|
const distPath = path.join(__dirname, "dist");
|
||||||
|
if (!fs.existsSync(distPath)) {
|
||||||
|
console.log("❌ dist folder not found. Run 'npm run build' first.");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load manifest to check for disabled providers
|
||||||
|
const manifest = this.loadManifest();
|
||||||
|
const disabledProviders = manifest
|
||||||
|
.filter((p) => p.disabled === true)
|
||||||
|
.map((p) => p.value);
|
||||||
|
|
||||||
|
if (disabledProviders.length > 0) {
|
||||||
|
console.log(
|
||||||
|
`\n⏭️ Skipping disabled providers: ${disabledProviders.join(", ")}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const providers = fs
|
||||||
|
.readdirSync(distPath, { withFileTypes: true })
|
||||||
|
.filter((dirent) => dirent.isDirectory())
|
||||||
|
.map((dirent) => dirent.name)
|
||||||
|
.filter((name) => {
|
||||||
|
// Skip disabled providers
|
||||||
|
if (disabledProviders.includes(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check if it has required modules
|
||||||
|
const hasRequired = [
|
||||||
|
"catalog.js",
|
||||||
|
"posts.js",
|
||||||
|
"meta.js",
|
||||||
|
"stream.js",
|
||||||
|
].every((file) => fs.existsSync(path.join(distPath, name, file)));
|
||||||
|
return hasRequired;
|
||||||
|
});
|
||||||
|
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a single provider with full flow
|
||||||
*/
|
*/
|
||||||
async testProvider(providerName) {
|
async testProvider(providerName) {
|
||||||
console.log(`\n🧪 Testing provider: ${providerName}`);
|
console.log(`\n${"=".repeat(60)}`);
|
||||||
|
console.log(`🧪 Testing Provider: ${providerName}`);
|
||||||
|
console.log("=".repeat(60));
|
||||||
|
|
||||||
const modules = ["catalog", "posts", "meta", "stream", "episodes"];
|
const result = {
|
||||||
const results = {};
|
provider: providerName,
|
||||||
|
catalog: { success: false, data: null, error: null },
|
||||||
|
posts: { success: false, data: null, error: null },
|
||||||
|
meta: { success: false, data: null, error: null },
|
||||||
|
episodes: { success: false, data: null, error: null, skipped: false },
|
||||||
|
stream: { success: false, data: null, error: null, skipped: false },
|
||||||
|
summary: { passed: 0, failed: 0, skipped: 0 },
|
||||||
|
};
|
||||||
|
|
||||||
for (const module of modules) {
|
|
||||||
try {
|
try {
|
||||||
const response = await this.axios.get(
|
// Step 1: Load and test catalog
|
||||||
`/dist/${providerName}/${module}.js`
|
console.log("\n📂 Step 1: Loading Catalog...");
|
||||||
);
|
const catalogModule = this.loadModule(providerName, "catalog");
|
||||||
results[module] = {
|
if (!catalogModule) {
|
||||||
success: true,
|
throw new Error("Catalog module not found");
|
||||||
size: response.data.length,
|
}
|
||||||
hasExports: response.data.includes("exports."),
|
|
||||||
|
const catalog = catalogModule.catalog || [];
|
||||||
|
// const genres = catalogModule.genres || [];
|
||||||
|
const allFilters = [...catalog];
|
||||||
|
|
||||||
|
if (allFilters.length === 0) {
|
||||||
|
throw new Error("No filters found in catalog");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.catalog.success = true;
|
||||||
|
result.catalog.data = {
|
||||||
|
catalogCount: catalog.length,
|
||||||
};
|
};
|
||||||
console.log(` ✅ ${module}.js (${results[module].size} bytes)`);
|
console.log(` ✅ Found ${catalog.length} catalog items`);
|
||||||
} catch (error) {
|
|
||||||
results[module] = {
|
// Pick a random filter
|
||||||
success: false,
|
const randomFilter = pickRandom(allFilters);
|
||||||
error: error.response?.status === 404 ? "Not found" : error.message,
|
|
||||||
};
|
|
||||||
const isOptional = module === "episodes";
|
|
||||||
const icon = isOptional ? "⚠️ " : "❌";
|
|
||||||
console.log(
|
console.log(
|
||||||
` ${icon} ${module}.js - ${results[module].error}${
|
` 🎲 Selected random filter: "${randomFilter.title}" (${randomFilter.filter})`
|
||||||
isOptional ? " (optional)" : ""
|
);
|
||||||
|
|
||||||
|
// Step 2: Test getPosts with random filter
|
||||||
|
console.log("\n📝 Step 2: Testing getPosts...");
|
||||||
|
const postsModule = this.loadModule(providerName, "posts");
|
||||||
|
if (!postsModule || !postsModule.getPosts) {
|
||||||
|
throw new Error("getPosts function not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const posts = await postsModule.getPosts({
|
||||||
|
filter: randomFilter.filter,
|
||||||
|
page: 1,
|
||||||
|
providerValue: providerName,
|
||||||
|
signal: this.signal,
|
||||||
|
providerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!Array.isArray(posts) || posts.length === 0) {
|
||||||
|
throw new Error("getPosts returned empty or invalid result");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.posts.success = true;
|
||||||
|
result.posts.data = { count: posts.length };
|
||||||
|
console.log(` ✅ Got ${posts.length} posts`);
|
||||||
|
|
||||||
|
// Pick random posts to test
|
||||||
|
const postsToTest = pickRandom(
|
||||||
|
posts,
|
||||||
|
Math.min(this.postsToTest, posts.length)
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
` 🎲 Selected ${postsToTest.length} random posts for meta testing`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 3: Test getMeta with random posts
|
||||||
|
console.log("\n📋 Step 3: Testing getMeta...");
|
||||||
|
const metaModule = this.loadModule(providerName, "meta");
|
||||||
|
if (!metaModule || !metaModule.getMeta) {
|
||||||
|
throw new Error("getMeta function not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaResults = [];
|
||||||
|
for (const post of postsToTest) {
|
||||||
|
console.log(`\n 📌 Testing: "${post.title.substring(0, 50)}..."`);
|
||||||
|
console.log(` Link: ${post.link}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sleep(500); // Small delay between requests
|
||||||
|
const meta = await metaModule.getMeta({
|
||||||
|
link: post.link,
|
||||||
|
providerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!meta || !meta.linkList) {
|
||||||
|
console.log(
|
||||||
|
` ⚠️ Meta returned but linkList is empty/missing`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
metaResults.push({ post, meta });
|
||||||
|
console.log(
|
||||||
|
` ✅ Got meta: type=${meta.type}, links=${meta.linkList.length}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Show link structure
|
||||||
|
meta.linkList.forEach((link, i) => {
|
||||||
|
const hasEpisodes = !!link.episodesLink;
|
||||||
|
const hasDirectLinks =
|
||||||
|
link.directLinks && link.directLinks.length > 0;
|
||||||
|
console.log(
|
||||||
|
` [${i + 1}] ${link.title.substring(0, 30)} - ${
|
||||||
|
hasEpisodes ? "📺 Episodes" : ""
|
||||||
|
}${hasDirectLinks ? "🎬 Direct" : ""}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` ❌ Error: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaResults.length === 0) {
|
||||||
|
throw new Error("No valid meta data retrieved");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.meta.success = true;
|
||||||
|
result.meta.data = { testedCount: metaResults.length };
|
||||||
|
|
||||||
|
// Step 4: Test episodes OR stream based on meta content
|
||||||
|
console.log("\n🔗 Step 4: Testing Episodes/Stream...");
|
||||||
|
|
||||||
|
// Find links with episodes
|
||||||
|
const episodeLinks = [];
|
||||||
|
const directLinks = [];
|
||||||
|
|
||||||
|
for (const { meta } of metaResults) {
|
||||||
|
for (const link of meta.linkList) {
|
||||||
|
if (link.episodesLink) {
|
||||||
|
episodeLinks.push({ meta, link });
|
||||||
|
}
|
||||||
|
if (link.directLinks && link.directLinks.length > 0) {
|
||||||
|
directLinks.push({ meta, link });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test episodes if available
|
||||||
|
if (episodeLinks.length > 0) {
|
||||||
|
console.log(`\n 📺 Found ${episodeLinks.length} episode links`);
|
||||||
|
const episodesModule = this.loadModule(providerName, "episodes");
|
||||||
|
|
||||||
|
if (episodesModule && episodesModule.getEpisodes) {
|
||||||
|
const testEpisodeLink = pickRandom(episodeLinks);
|
||||||
|
console.log(
|
||||||
|
` 🎲 Testing episodes from: ${testEpisodeLink.link.title}`
|
||||||
|
);
|
||||||
|
console.log(` URL: ${testEpisodeLink.link.episodesLink}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const episodes = await episodesModule.getEpisodes({
|
||||||
|
url: testEpisodeLink.link.episodesLink,
|
||||||
|
providerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(episodes) && episodes.length > 0) {
|
||||||
|
result.episodes.success = true;
|
||||||
|
result.episodes.data = { count: episodes.length };
|
||||||
|
console.log(` ✅ Got ${episodes.length} episodes`);
|
||||||
|
|
||||||
|
// Show first few episodes
|
||||||
|
episodes.slice(0, 3).forEach((ep, i) => {
|
||||||
|
console.log(` [${i + 1}] ${ep.title}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test stream with random episode
|
||||||
|
console.log(`\n 🎬 Testing stream with random episode...`);
|
||||||
|
const randomEpisode = pickRandom(episodes);
|
||||||
|
console.log(` Episode: ${randomEpisode.title}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const streamModule = this.loadModule(providerName, "stream");
|
||||||
|
if (streamModule && streamModule.getStream) {
|
||||||
|
const streams = await streamModule.getStream({
|
||||||
|
link: randomEpisode.link,
|
||||||
|
type: "series",
|
||||||
|
signal: this.signal,
|
||||||
|
providerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(streams) && streams.length > 0) {
|
||||||
|
result.stream.success = true;
|
||||||
|
result.stream.data = {
|
||||||
|
count: streams.length,
|
||||||
|
type: "series",
|
||||||
|
};
|
||||||
|
console.log(` ✅ Got ${streams.length} stream(s)`);
|
||||||
|
streams.forEach((s, i) => {
|
||||||
|
console.log(
|
||||||
|
` [${i + 1}] ${s.server} - ${
|
||||||
|
s.quality || "unknown"
|
||||||
|
} quality`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠️ No streams returned`);
|
||||||
|
result.stream.error = "No streams returned";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` ❌ Stream error: ${err.message}`);
|
||||||
|
result.stream.error = err.message;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠️ No episodes returned`);
|
||||||
|
result.episodes.error = "No episodes returned";
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` ❌ Episodes error: ${err.message}`);
|
||||||
|
result.episodes.error = err.message;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠️ getEpisodes function not found`);
|
||||||
|
result.episodes.skipped = true;
|
||||||
|
result.episodes.error = "Function not available";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.episodes.skipped = true;
|
||||||
|
console.log(` ℹ️ No episode links found, skipping episodes test`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test direct links/stream if episodes not tested or no episode links
|
||||||
|
if (directLinks.length > 0 && !result.stream.success) {
|
||||||
|
console.log(`\n 🎬 Found ${directLinks.length} direct link entries`);
|
||||||
|
|
||||||
|
const testDirectLink = pickRandom(directLinks);
|
||||||
|
const linksToTest = pickRandom(
|
||||||
|
testDirectLink.link.directLinks,
|
||||||
|
Math.min(this.linksToTest, testDirectLink.link.directLinks.length)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
` 🎲 Testing ${linksToTest.length} random direct link(s)`
|
||||||
|
);
|
||||||
|
|
||||||
|
const streamModule = this.loadModule(providerName, "stream");
|
||||||
|
if (streamModule && streamModule.getStream) {
|
||||||
|
for (const directLink of Array.isArray(linksToTest)
|
||||||
|
? linksToTest
|
||||||
|
: [linksToTest]) {
|
||||||
|
console.log(`\n Testing: ${directLink.title}`);
|
||||||
|
console.log(` Link: ${directLink.link}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sleep(500);
|
||||||
|
const streams = await streamModule.getStream({
|
||||||
|
link: directLink.link,
|
||||||
|
type: directLink.type || "movie",
|
||||||
|
signal: this.signal,
|
||||||
|
providerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(streams) && streams.length > 0) {
|
||||||
|
result.stream.success = true;
|
||||||
|
result.stream.data = {
|
||||||
|
count: streams.length,
|
||||||
|
type: directLink.type || "movie",
|
||||||
|
};
|
||||||
|
console.log(` ✅ Got ${streams.length} stream(s)`);
|
||||||
|
streams.forEach((s, i) => {
|
||||||
|
console.log(
|
||||||
|
` [${i + 1}] ${s.server} - ${
|
||||||
|
s.quality || "unknown"
|
||||||
|
} quality`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break; // One success is enough
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠️ No streams returned`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` ❌ Stream error: ${err.message}`);
|
||||||
|
result.stream.error = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(` ❌ getStream function not found`);
|
||||||
|
result.stream.error = "Function not available";
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
!result.stream.success &&
|
||||||
|
directLinks.length === 0 &&
|
||||||
|
episodeLinks.length === 0
|
||||||
|
) {
|
||||||
|
result.stream.skipped = true;
|
||||||
|
console.log(` ℹ️ No links to test stream with`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`\n❌ Test failed: ${error.message}`);
|
||||||
|
|
||||||
|
// Determine which step failed
|
||||||
|
if (!result.catalog.success) {
|
||||||
|
result.catalog.error = error.message;
|
||||||
|
} else if (!result.posts.success) {
|
||||||
|
result.posts.error = error.message;
|
||||||
|
} else if (!result.meta.success) {
|
||||||
|
result.meta.error = error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate summary
|
||||||
|
const steps = ["catalog", "posts", "meta", "episodes", "stream"];
|
||||||
|
for (const step of steps) {
|
||||||
|
if (result[step].success) {
|
||||||
|
result.summary.passed++;
|
||||||
|
} else if (result[step].skipped) {
|
||||||
|
result.summary.skipped++;
|
||||||
|
} else if (result[step].error) {
|
||||||
|
result.summary.failed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print summary
|
||||||
|
console.log(`\n${"─".repeat(60)}`);
|
||||||
|
console.log(`📊 Provider Summary: ${providerName}`);
|
||||||
|
console.log("─".repeat(60));
|
||||||
|
console.log(` ✅ Passed: ${result.summary.passed}`);
|
||||||
|
console.log(` ❌ Failed: ${result.summary.failed}`);
|
||||||
|
console.log(` ⏭️ Skipped: ${result.summary.skipped}`);
|
||||||
|
|
||||||
|
// List which steps passed/failed/skipped
|
||||||
|
console.log("\n Step Results:");
|
||||||
|
for (const step of steps) {
|
||||||
|
if (result[step].success) {
|
||||||
|
console.log(` ✅ ${step}`);
|
||||||
|
} else if (result[step].skipped) {
|
||||||
|
console.log(` ⏭️ ${step} (skipped)`);
|
||||||
|
} else if (result[step].error) {
|
||||||
|
console.log(` ❌ ${step}: ${result[step].error}`);
|
||||||
|
} else {
|
||||||
|
console.log(` ⚪ ${step} (not tested)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusIcon = result.summary.failed === 0 ? "✅" : "❌";
|
||||||
|
console.log(
|
||||||
|
`\n ${statusIcon} Overall: ${
|
||||||
|
result.summary.failed === 0 ? "PASSED" : "FAILED"
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test all providers
|
* Test all providers
|
||||||
*/
|
*/
|
||||||
async testAllProviders() {
|
async testAllProviders() {
|
||||||
console.log("🚀 Starting comprehensive provider test...\n");
|
console.log("🚀 Starting comprehensive provider tests...\n");
|
||||||
|
|
||||||
// Test connection
|
if (!providerContext) {
|
||||||
const connected = await this.testConnection();
|
console.log("❌ Provider context not loaded. Run 'npm run build' first.");
|
||||||
if (!connected) return;
|
|
||||||
|
|
||||||
// Test manifest
|
|
||||||
const providers = await this.testManifest();
|
|
||||||
if (!providers) return;
|
|
||||||
|
|
||||||
// Test each provider
|
|
||||||
const results = {};
|
|
||||||
for (const provider of providers) {
|
|
||||||
results[provider.value] = await this.testProvider(provider.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Summary
|
|
||||||
console.log("\n📊 Test Summary:");
|
|
||||||
console.log("=".repeat(50));
|
|
||||||
|
|
||||||
let totalProviders = 0;
|
|
||||||
let passedProviders = 0;
|
|
||||||
|
|
||||||
for (const [providerName, modules] of Object.entries(results)) {
|
|
||||||
totalProviders++;
|
|
||||||
const requiredModules = ["catalog", "posts", "meta", "stream"];
|
|
||||||
const passedRequired = requiredModules.every(
|
|
||||||
(mod) => modules[mod]?.success
|
|
||||||
);
|
|
||||||
|
|
||||||
if (passedRequired) {
|
|
||||||
passedProviders++;
|
|
||||||
console.log(`✅ ${providerName} - All required modules OK`);
|
|
||||||
} else {
|
|
||||||
console.log(`❌ ${providerName} - Missing required modules`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`\n📈 Results: ${passedProviders}/${totalProviders} providers passed`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (passedProviders === totalProviders) {
|
|
||||||
console.log("🎉 All providers are ready for testing!");
|
|
||||||
} else {
|
|
||||||
console.log("⚠️ Some providers need attention before testing.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger rebuild on server
|
|
||||||
*/
|
|
||||||
async rebuild() {
|
|
||||||
try {
|
|
||||||
console.log("🔨 Triggering rebuild...");
|
|
||||||
const response = await this.axios.post("/build");
|
|
||||||
console.log("✅ Rebuild completed");
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(
|
|
||||||
"❌ Rebuild failed:",
|
|
||||||
error.response?.data?.error || error.message
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get server status
|
|
||||||
*/
|
|
||||||
async getStatus() {
|
|
||||||
try {
|
|
||||||
const response = await this.axios.get("/status");
|
|
||||||
const status = response.data;
|
|
||||||
|
|
||||||
console.log("📊 Server Status:");
|
|
||||||
console.log(` 🟢 Status: ${status.status}`);
|
|
||||||
console.log(` 🔌 Port: ${status.port}`);
|
|
||||||
console.log(` 📦 Providers: ${status.providers}`);
|
|
||||||
console.log(` 🕐 Last Build: ${status.buildTime || "Never"}`);
|
|
||||||
|
|
||||||
if (status.providerList.length > 0) {
|
|
||||||
console.log(" 📋 Available Providers:");
|
|
||||||
status.providerList.forEach((p) => console.log(` • ${p}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("❌ Failed to get status:", error.message);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const providers = this.getAvailableProviders();
|
||||||
|
if (providers.length === 0) {
|
||||||
|
console.log("❌ No providers found.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📦 Found ${providers.length} providers to test:`);
|
||||||
|
providers.forEach((p) => console.log(` • ${p}`));
|
||||||
|
|
||||||
|
const results = {};
|
||||||
|
let passed = 0;
|
||||||
|
let failed = 0;
|
||||||
|
|
||||||
|
for (const provider of providers) {
|
||||||
|
try {
|
||||||
|
results[provider] = await this.testProvider(provider);
|
||||||
|
if (results[provider].summary.failed === 0) {
|
||||||
|
passed++;
|
||||||
|
} else {
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(
|
||||||
|
`\n❌ Critical error testing ${provider}: ${error.message}`
|
||||||
|
);
|
||||||
|
failed++;
|
||||||
|
results[provider] = { error: error.message };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small delay between providers
|
||||||
|
await sleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final summary
|
||||||
|
console.log(`\n${"═".repeat(60)}`);
|
||||||
|
console.log("📊 FINAL TEST SUMMARY");
|
||||||
|
console.log("═".repeat(60));
|
||||||
|
console.log(` Total Providers: ${providers.length}`);
|
||||||
|
console.log(` ✅ Passed: ${passed}`);
|
||||||
|
console.log(` ❌ Failed: ${failed}`);
|
||||||
|
|
||||||
|
// List failed providers with details
|
||||||
|
if (failed > 0) {
|
||||||
|
console.log(`\n${"─".repeat(60)}`);
|
||||||
|
console.log("❌ FAILED PROVIDERS:");
|
||||||
|
console.log("─".repeat(60));
|
||||||
|
|
||||||
|
for (const [name, result] of Object.entries(results)) {
|
||||||
|
if (result.error) {
|
||||||
|
// Critical error
|
||||||
|
console.log(`\n ❌ ${name}`);
|
||||||
|
console.log(` Error: ${result.error}`);
|
||||||
|
} else if (result.summary?.failed > 0) {
|
||||||
|
// Step failures
|
||||||
|
console.log(`\n ❌ ${name}`);
|
||||||
|
const steps = ["catalog", "posts", "meta", "episodes", "stream"];
|
||||||
|
for (const step of steps) {
|
||||||
|
if (result[step]?.error && !result[step]?.skipped) {
|
||||||
|
console.log(` • ${step}: ${result[step].error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List passed providers
|
||||||
|
if (passed > 0) {
|
||||||
|
console.log(`\n${"─".repeat(60)}`);
|
||||||
|
console.log("✅ PASSED PROVIDERS:");
|
||||||
|
console.log("─".repeat(60));
|
||||||
|
const passedProviders = Object.entries(results)
|
||||||
|
.filter(([_, result]) => result.summary?.failed === 0 && !result.error)
|
||||||
|
.map(([name]) => name);
|
||||||
|
console.log(` ${passedProviders.join(", ")}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n${"═".repeat(60)}`);
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,53 +593,52 @@ class ProviderTester {
|
|||||||
*/
|
*/
|
||||||
async function main() {
|
async function main() {
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const command = args[0] || "test";
|
const providerName = args[0];
|
||||||
const providerName = args[1];
|
|
||||||
|
|
||||||
const tester = new ProviderTester();
|
// Check for options
|
||||||
|
const postsToTest =
|
||||||
|
parseInt(args.find((a) => a.startsWith("--posts="))?.split("=")[1]) || 2;
|
||||||
|
const linksToTest =
|
||||||
|
parseInt(args.find((a) => a.startsWith("--links="))?.split("=")[1]) || 2;
|
||||||
|
|
||||||
switch (command) {
|
const tester = new ProviderTester({ postsToTest, linksToTest });
|
||||||
case "test":
|
|
||||||
if (providerName) {
|
|
||||||
await tester.testProvider(providerName);
|
|
||||||
} else {
|
|
||||||
await tester.testAllProviders();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "status":
|
if (args.includes("--help") || args.includes("-h")) {
|
||||||
await tester.getStatus();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "rebuild":
|
|
||||||
await tester.rebuild();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "connection":
|
|
||||||
await tester.testConnection();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "manifest":
|
|
||||||
await tester.testManifest();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
console.log(`
|
console.log(`
|
||||||
Usage: node test-providers.js [command] [provider]
|
🎯 Vega Providers Integration Tester
|
||||||
|
=====================================
|
||||||
|
|
||||||
Commands:
|
Usage: node test-providers.js [provider] [options]
|
||||||
test [provider] - Test all providers or specific provider
|
|
||||||
status - Show server status
|
Arguments:
|
||||||
rebuild - Trigger rebuild
|
provider Name of specific provider to test (optional)
|
||||||
connection - Test server connection
|
If not provided, tests all providers
|
||||||
manifest - Test manifest endpoint
|
|
||||||
|
Options:
|
||||||
|
--posts=N Number of random posts to test (default: 2)
|
||||||
|
--links=N Number of random direct links to test (default: 2)
|
||||||
|
--help, -h Show this help message
|
||||||
|
|
||||||
|
Test Flow:
|
||||||
|
1. Load catalog → pick random filter
|
||||||
|
2. Call getPosts with filter
|
||||||
|
3. Pick random posts → call getMeta
|
||||||
|
4. If episodesLink → call getEpisodes → getStream
|
||||||
|
5. If directLinks → call getStream
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
node test-providers.js # Test all providers
|
node test-providers.js # Test all providers
|
||||||
node test-providers.js test vega # Test specific provider
|
node test-providers.js vega # Test only vega provider
|
||||||
node test-providers.js status # Show status
|
node test-providers.js mod --posts=3 # Test mod with 3 random posts
|
||||||
node test-providers.js rebuild # Rebuild and test
|
node test-providers.js --posts=1 --links=1 # Quick test all providers
|
||||||
`);
|
`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (providerName && !providerName.startsWith("--")) {
|
||||||
|
await tester.testProvider(providerName);
|
||||||
|
} else {
|
||||||
|
await tester.testAllProviders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user