Skip to content

Commit 9d06e01

Browse files
committed
feat: Use CORS proxies
1 parent ed3b05d commit 9d06e01

File tree

20 files changed

+353
-491
lines changed

20 files changed

+353
-491
lines changed

anify-backend/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@
2323
"epub-gen-memory": "^1.1.2",
2424
"eventemitter2": "latest",
2525
"fastest-levenshtein": "^1.0.16",
26-
"https-proxy-agent": "^7.0.6",
2726
"ioredis": "^5.4.1",
2827
"jimp": "^0.22.12",
2928
"lru-cache": "^11.0.2",
3029
"node-fetch": "^3.3.2",
3130
"p-limit": "^6.2.0",
3231
"pdfkit": "^0.13.0",
3332
"pg": "^8.13.1",
34-
"undici": "^7.3.0",
3533
"zod": "^3.23.8"
3634
},
3735
"devDependencies": {

anify-backend/src/env.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ const envSchema = z.object({
4949
*/
5050
DEBUG: booleanFromEnv.optional().default("false"),
5151

52+
/**
53+
* @description Optional, but highly recommended as
54+
* Censys is used for scraping proxies.
55+
*/
56+
/**
57+
* The API ID for the Censys API.
58+
*/
59+
CENSYS_API_ID: z.string().optional(),
60+
/**
61+
* The API key for the Censys API.
62+
*/
63+
CENSYS_API_SECRET: z.string().optional(),
64+
5265
/**
5366
* @description Optional, additional environment variables
5467
*/

anify-backend/src/proxies/impl/manager/impl/check/impl/runProxyChecks.ts

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -87,57 +87,89 @@ export const runProxyChecks = async (providers: MediaProvider[], verbose: boolea
8787
// Check proxies in parallel with concurrency limiting:
8888
let checkResults: (IProxy | null)[] = [];
8989
try {
90+
const startTime = Date.now();
9091
checkResults = await Promise.all(
9192
proxiesToCheck.map((proxy) =>
9293
limit(async () => {
93-
const url = `http://${proxy.ip}:${proxy.port}`;
94-
let isValid = false;
94+
// Add timeout for the entire proxy check process
95+
const proxyCheckPromise = (async () => {
96+
const url = `http://${proxy.ip}:${proxy.port}`;
97+
let isValid = false;
98+
99+
try {
100+
// Check if proxy is valid
101+
const timeoutPromise = new Promise<Response>((_, reject) => {
102+
setTimeout(() => reject(new Error("Request timed out")), 15000);
103+
});
104+
105+
const fetchPromise = fetch(`${url}/iscorsneeded`, {
106+
headers: {
107+
Origin: "https://anify.tv",
108+
},
109+
});
110+
111+
const response = await Promise.race([fetchPromise, timeoutPromise]);
112+
113+
if (response.status === 200 && (await response.text()) === "no") {
114+
const providerCheckPromise = provider.proxyCheck(url);
115+
const providerTimeoutPromise = new Promise<boolean>((_, reject) => {
116+
setTimeout(() => reject(new Error("Provider check timed out")), 15000);
117+
});
118+
119+
try {
120+
const check = await Promise.race([providerCheckPromise, providerTimeoutPromise]);
121+
isValid = check ?? false;
122+
} catch (error) {
123+
if (env.DEBUG && verbose) {
124+
console.error(`Provider check failed for ${url}: ${error instanceof Error ? error.message : String(error)}`);
125+
}
126+
isValid = false;
127+
}
128+
} else {
129+
isValid = false;
130+
}
131+
} catch {
132+
isValid = false;
133+
}
134+
135+
// Update progress counters
136+
checkedCount += 1;
137+
if (isValid) {
138+
validCount += 1;
139+
} else {
140+
invalidCount += 1;
141+
}
95142

96-
try {
97-
isValid = (await provider.proxyCheck(url)) ?? false;
98-
} catch (error) {
99-
// Log the error but don't let it crash the script
100143
if (env.DEBUG && verbose) {
101-
console.error(`Error checking proxy ${url}: ${error instanceof Error ? error.message : String(error)}`);
144+
throttledProgressUpdate(
145+
colors.yellow(`Provider: ${provider.providerType} ${provider.id} | ` + `${checkedCount}/${proxiesToCheck.length} checked, ` + `${validCount} valid, ` + `${invalidCount} invalid | ` + `Time elapsed: ${((Date.now() - startTime) / 1000).toFixed(1)}s`),
146+
);
102147
}
103-
isValid = false;
104-
}
105148

106-
// Update progress counters
149+
return isValid ? proxy : null;
150+
})();
151+
152+
// Global timeout for entire proxy check
153+
const globalTimeout = new Promise<null>((_, reject) => {
154+
setTimeout(() => reject(new Error("Global proxy check timeout")), 30000);
155+
});
156+
157+
return Promise.race([proxyCheckPromise, globalTimeout]);
158+
}).catch(() => {
107159
checkedCount += 1;
108-
if (isValid) {
109-
validCount += 1;
110-
} else {
111-
invalidCount += 1;
112-
}
113-
114-
// Throttled progress update:
115-
if (env.DEBUG && verbose) {
116-
throttledProgressUpdate(colors.yellow(`Provider: ${provider.providerType} ${provider.id} | ` + `${checkedCount}/${proxiesToCheck.length} checked, ` + `${validCount} valid, ` + `${invalidCount} invalid`));
117-
}
118-
119-
// Return the proxy if valid, otherwise null
120-
return isValid ? proxy : null;
121-
}).catch((error) => {
122-
// Catch any errors that might occur in the limit wrapper
123-
if (env.DEBUG && verbose) {
124-
console.error(`Error in proxy check: ${error instanceof Error ? error.message : String(error)}`);
125-
}
160+
invalidCount += 1;
126161
return null;
127162
}),
128163
),
129-
).catch((error) => {
130-
// Catch any errors in Promise.all
131-
if (env.DEBUG && verbose) {
132-
console.error(`Error in proxy batch check: ${error instanceof Error ? error.message : String(error)}`);
133-
}
134-
return [];
135-
});
164+
);
136165
} catch (error) {
137166
if (env.DEBUG && verbose) {
138167
console.error(`Error in proxy batch check: ${error instanceof Error ? error.message : String(error)}`);
139168
}
140169
continue;
170+
} finally {
171+
// Ensure we clear any remaining tasks in the limit queue
172+
limit.clearQueue();
141173
}
142174

143175
// After finishing all checks, print a new line to avoid overwriting

anify-backend/src/proxies/impl/manager/impl/check/index.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { MediaProvider } from "../../../../../types/impl/mappings/impl/mediaProvider";
2-
import proxies from "../scrape";
32
import colors from "colors";
43
import { runProxyChecks } from "./impl/runProxyChecks";
54
import { saveProxies } from "../file/saveProxies";
@@ -63,32 +62,6 @@ export const checkProxies = async (providers: MediaProvider[], verbose: boolean
6362
}
6463
}
6564

66-
// Now scrape for new proxies
67-
for (const scrape of Object.values(proxies)) {
68-
const newProxies = await scrape();
69-
70-
if (newProxies.length === 0) {
71-
if (env.DEBUG && verbose) {
72-
console.log(colors.red("No new proxies found from scraper"));
73-
}
74-
continue;
75-
}
76-
77-
// Merge new proxies with existing ones, preserving metrics
78-
for (const newProxy of newProxies) {
79-
const existingProxy = existingProxies.find((p) => p.ip === newProxy.ip && p.port === newProxy.port);
80-
if (!existingProxy) {
81-
existingProxies.push(newProxy);
82-
}
83-
}
84-
85-
await saveProxies(existingProxies);
86-
87-
if (env.DEBUG && verbose) {
88-
console.log(colors.green(`Found ${newProxies.length} new proxies. Total proxies after merge: ${existingProxies.length}`));
89-
}
90-
}
91-
9265
// Preload the proxies into cache before running checks
9366
await preloadProxies();
9467

anify-backend/src/proxies/impl/manager/impl/file/preloadProxies.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { proxyCache } from "../..";
22
import { PROVIDERS } from "../../../../../mappings";
33
import type { IProxy } from "../../../../../types/impl/proxies";
4-
import { ProxyType } from "../../../../../types/impl/proxies";
54
import { loadJSON } from "../../../helper/loadJSON";
65
import { emitter } from "../../../../../events";
76
import { Events } from "../../../../../types/impl/events";
@@ -81,8 +80,6 @@ export async function preloadProxies(): Promise<void> {
8180
convertedProxies.forEach((typeProxy) => {
8281
const existingProxy = proxyCache.proxies.find((p) => p.ip === typeProxy.ip && p.port === typeProxy.port);
8382
if (existingProxy) {
84-
// Merge provider metrics and preserve type
85-
existingProxy.type = typeProxy.type || existingProxy.type;
8683
existingProxy.providerMetrics = {
8784
...existingProxy.providerMetrics,
8885
[provider.id]: typeProxy.providerMetrics[provider.id],
@@ -91,7 +88,6 @@ export async function preloadProxies(): Promise<void> {
9188
// Only include the metrics for this specific provider but preserve all other properties
9289
const newProxy = {
9390
...typeProxy,
94-
type: typeProxy.type || ProxyType.HTTP, // Ensure type is preserved
9591
providerMetrics: {
9692
[provider.id]: typeProxy.providerMetrics[provider.id],
9793
},

anify-backend/src/proxies/impl/manager/impl/file/saveProviderProxies.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { proxyCache } from "../..";
22
import { ProviderType } from "../../../../../types";
33
import { saveJSON } from "../../../helper/saveJSON";
44
import type { IProxy } from "../../../../../types/impl/proxies";
5-
import { ProxyType } from "../../../../../types/impl/proxies";
65
import { env } from "../../../../../env";
76
import colors from "colors";
87

@@ -23,7 +22,6 @@ export async function saveProviderProxies(providerType: ProviderType): Promise<v
2322
// If this is a new proxy, add it to our final list with proper type
2423
finalProxies[key] = {
2524
...proxy,
26-
type: proxy.type || ProxyType.HTTP, // Default to HTTP if type is not set
2725
providerMetrics: {
2826
[providerId]: {
2927
healthScore: 50,
@@ -50,8 +48,6 @@ export async function saveProviderProxies(providerType: ProviderType): Promise<v
5048
latencyScore: 50,
5149
};
5250
} else {
53-
// If this proxy already exists, update the provider metrics and ensure type is preserved
54-
finalProxies[key].type = proxy.type || finalProxies[key].type;
5551
finalProxies[key].providerMetrics[providerId] = proxy.providerMetrics?.[providerId] || {
5652
healthScore: 50,
5753
consecutiveFailures: 0,

anify-backend/src/proxies/impl/manager/impl/scrape/impl/monosans.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

anify-backend/src/proxies/impl/manager/impl/scrape/impl/proxyList.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

anify-backend/src/proxies/impl/manager/impl/scrape/impl/proxyListPlus.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)