You are an advanced o1 engineer designed to analyze files and provide edit instructions based on user requests. Your task is to:

1. Understand the User Request: Carefully interpret what the user wants to achieve with the modification.
2. Analyze the File(s): Review the content of the provided file(s).
3. Generate Edit Instructions: Provide clear, step-by-step instructions on how to modify the file(s) to address the user's request.

Your response should be in the following format:

```
File: [file_path]
Instructions:
1. [First edit instruction]
2. [Second edit instruction]
...

File: [another_file_path]
Instructions:
1. [First edit instruction]
2. [Second edit instruction]
...
```

Only provide instructions for files that need changes. Be specific and clear in your instructions.

User request: Added files:
File: index.ts
Content:
import { checkProxyArchive } from "./providers/checkerProxyArchive";
import { github } from "./providers/github";
import * as fs from "fs";
import http from "http";
import path from "path";
import { Worker, isMainThread, parentPort, workerData } from "worker_threads";
import { Elysia } from "elysia";
import cp from "child_process";

let proxies: string[];

async function scrapeProxies() {
  const [one, two] = await Promise.all([checkProxyArchive(), github()]);

  proxies = [...one, ...two];

  proxies = [...new Set(proxies)];

  fs.writeFileSync("proxies.txt", proxies.join("\n"));

  console.log(`Scraped ${proxies.length.toLocaleString("en-US")} proxy(ies)`);
}

const dataPath = "data.json";
if (!fs.existsSync(dataPath)) {
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: "" }));
}
const data = JSON.parse(fs.readFileSync(dataPath, "utf8"));

if (data.lastScrape === "" || Date.now() - data.lastScrape > 10 * 60 * 1000) {
  scrapeProxies();
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: Date.now() }));
} else {
  proxies = fs.readFileSync("proxies.txt", "utf8").split("\n");
  proxies = [...new Set(proxies)];

  console.log(`Loaded ${proxies.length.toLocaleString("en-US")} proxy(ies)`);

  fs.writeFileSync("proxies.txt", proxies.join("\n"));
}

const app = new Elysia();

app.get("/getProxy", () => {
  const workingProxiesPath = "working_proxies.json";
  if (!fs.existsSync(workingProxiesPath)) {
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
  }
  const workingProxies = JSON.parse(
    fs.readFileSync(workingProxiesPath, "utf8")
  );

  const recentProxies = Object.entries(workingProxies).filter(
    ([_, data]: [string, any]) => Date.now() - data.lastChecked < 60 * 1000
  );

  if (recentProxies.length === 0) {
    return null;
  }

  const [selectedProxy] =
    recentProxies[Math.floor(Math.random() * recentProxies.length)];
  return selectedProxy;
});

app.listen(1111);

const configPath = path.join(__dirname, "config.json");

interface Config {
  Threads: number;
  InputFile: string;
  MaxTimeout: number;
  Hosts: string[];
}

const defaultConfig: Config = {
  Threads: 1,
  InputFile: "proxies.txt",
  MaxTimeout: 1000,
  Hosts: ["example.com"],
};

if (!fs.existsSync(configPath)) {
  fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4));
}

const config: Config = JSON.parse(fs.readFileSync(configPath, "utf-8"));

let validProxies: string[] = [];

function getRandomHost(): string {
  const hosts = config.Hosts;
  return hosts[Math.floor(Math.random() * hosts.length)];
}

export async function checkProxy(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  const [host, port] = proxy.split(":");
  const targetHost = getRandomHost();
  const proxyUrl = `http://${host}:${port}`;
  const url = `http://${targetHost}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), maxTimeout);

    return new Promise<boolean>((resolve) => {
      const curlCommand = `curl "${url}" --proxy "${proxyUrl}" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" -H "Host: ${targetHost}" -o /dev/null -w "%{http_code}"`;

      cp.exec(curlCommand, { timeout: maxTimeout }, (error, stdout, stderr) => {
        clearTimeout(timeoutId);
        if (error) {
          resolve(false);
        } else {
          const statusCode = parseInt(stdout.trim(), 10);
          resolve(statusCode === 200);
        }
      });
    });
  } catch (error) {
    return false;
  }
}

async function checkProxyWithTimeout(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  return Promise.race([
    checkProxy(proxy, maxTimeout),
    new Promise<boolean>((resolve) =>
      setTimeout(() => resolve(false), maxTimeout)
    ),
  ]);
}

async function workerFunction({
  proxies,
  maxTimeout,
}: {
  proxies: string[];
  maxTimeout: number;
}): Promise<void> {
  const results: string[] = [];
  const workingProxiesPath = "working_proxies.json";
  for (const proxy of proxies) {
    const isValid = await checkProxyWithTimeout(proxy, maxTimeout);
    if (isValid) {
      console.log(`\x1b[32m[+] ${proxy}\x1b[0m`);
      results.push(proxy);
      // update working_proxies.json
      let workingProxies: { [key: string]: { lastChecked: number } } = {};
      if (fs.existsSync(workingProxiesPath)) {
        try {
          const fileContent = fs.readFileSync(workingProxiesPath, "utf8");
          workingProxies = JSON.parse(fileContent);
        } catch (error) {
          console.error("Error parsing working_proxies.json:", error);
        }
      }
      workingProxies[proxy] = { lastChecked: Date.now() };
      fs.writeFileSync(
        workingProxiesPath,
        JSON.stringify(workingProxies, null, 4)
      );
    } else {
      // console.log(`\x1b[31m[-] ${proxy}\x1b[0m`);
    }
  }
  parentPort?.postMessage(results);
}

if (isMainThread) {
  async function scrapeAndCheckProxies(): Promise<void> {
    // Clear working_proxies.json before restarting
    const workingProxiesPath = "working_proxies.json";
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
    console.log("Cleared working_proxies.json");

    await scrapeProxies();
    const proxies = fs
      .readFileSync(config.InputFile, "utf-8")
      .split("\n")
      .filter(Boolean);
    const chunkSize = Math.ceil(proxies.length / config.Threads);
    const threads: Promise<void>[] = [];

    for (let i = 0; i < config.Threads; i++) {
      const chunk = proxies.slice(i * chunkSize, (i + 1) * chunkSize);
      threads.push(
        new Promise((resolve, reject) => {
          const worker = new Worker(__filename, {
            workerData: { proxies: chunk, maxTimeout: config.MaxTimeout },
          });
          worker.on("message", (message: string[]) => {
            validProxies = validProxies.concat(message);
            resolve();
          });
          worker.on("error", reject);
          worker.on("exit", (code: number) => {
            if (code !== 0)
              reject(new Error(`Worker stopped with exit code ${code}`));
          });
        })
      );
    }

    await Promise.all(threads);
    console.log(`Finished checking proxies!`);
  }

  async function main(): Promise<void> {
    while (true) {
      await scrapeAndCheckProxies();
      console.log("Waiting before next cycle...");
      await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
    }
  }

  process.on("SIGINT", () => {
    console.log("\nGracefully shutting down...");
    console.log(`Checked proxies didn't save!`);
    process.exit();
  });

  main();
} else {
  workerFunction(workerData as { proxies: string[]; maxTimeout: number });
}



User request: add debugs

Files to modify:

File: index.ts
Content:
import { checkProxyArchive } from "./providers/checkerProxyArchive";
import { github } from "./providers/github";
import * as fs from "fs";
import http from "http";
import path from "path";
import { Worker, isMainThread, parentPort, workerData } from "worker_threads";
import { Elysia } from "elysia";
import cp from "child_process";

let proxies: string[];

async function scrapeProxies() {
  const [one, two] = await Promise.all([checkProxyArchive(), github()]);

  proxies = [...one, ...two];

  proxies = [...new Set(proxies)];

  fs.writeFileSync("proxies.txt", proxies.join("\n"));

  console.log(`Scraped ${proxies.length.toLocaleString("en-US")} proxy(ies)`);
}

const dataPath = "data.json";
if (!fs.existsSync(dataPath)) {
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: "" }));
}
const data = JSON.parse(fs.readFileSync(dataPath, "utf8"));

if (data.lastScrape === "" || Date.now() - data.lastScrape > 10 * 60 * 1000) {
  scrapeProxies();
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: Date.now() }));
} else {
  proxies = fs.readFileSync("proxies.txt", "utf8").split("\n");
  proxies = [...new Set(proxies)];

  console.log(`Loaded ${proxies.length.toLocaleString("en-US")} proxy(ies)`);

  fs.writeFileSync("proxies.txt", proxies.join("\n"));
}

const app = new Elysia();

app.get("/getProxy", () => {
  const workingProxiesPath = "working_proxies.json";
  if (!fs.existsSync(workingProxiesPath)) {
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
  }
  const workingProxies = JSON.parse(
    fs.readFileSync(workingProxiesPath, "utf8")
  );

  const recentProxies = Object.entries(workingProxies).filter(
    ([_, data]: [string, any]) => Date.now() - data.lastChecked < 60 * 1000
  );

  if (recentProxies.length === 0) {
    return null;
  }

  const [selectedProxy] =
    recentProxies[Math.floor(Math.random() * recentProxies.length)];
  return selectedProxy;
});

app.listen(1111);

const configPath = path.join(__dirname, "config.json");

interface Config {
  Threads: number;
  InputFile: string;
  MaxTimeout: number;
  Hosts: string[];
}

const defaultConfig: Config = {
  Threads: 1,
  InputFile: "proxies.txt",
  MaxTimeout: 1000,
  Hosts: ["example.com"],
};

if (!fs.existsSync(configPath)) {
  fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4));
}

const config: Config = JSON.parse(fs.readFileSync(configPath, "utf-8"));

let validProxies: string[] = [];

function getRandomHost(): string {
  const hosts = config.Hosts;
  return hosts[Math.floor(Math.random() * hosts.length)];
}

export async function checkProxy(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  const [host, port] = proxy.split(":");
  const targetHost = getRandomHost();
  const proxyUrl = `http://${host}:${port}`;
  const url = `http://${targetHost}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), maxTimeout);

    return new Promise<boolean>((resolve) => {
      const curlCommand = `curl "${url}" --proxy "${proxyUrl}" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" -H "Host: ${targetHost}" -o /dev/null -w "%{http_code}"`;

      cp.exec(curlCommand, { timeout: maxTimeout }, (error, stdout, stderr) => {
        clearTimeout(timeoutId);
        if (error) {
          resolve(false);
        } else {
          const statusCode = parseInt(stdout.trim(), 10);
          resolve(statusCode === 200);
        }
      });
    });
  } catch (error) {
    return false;
  }
}

async function checkProxyWithTimeout(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  return Promise.race([
    checkProxy(proxy, maxTimeout),
    new Promise<boolean>((resolve) =>
      setTimeout(() => resolve(false), maxTimeout)
    ),
  ]);
}

async function workerFunction({
  proxies,
  maxTimeout,
}: {
  proxies: string[];
  maxTimeout: number;
}): Promise<void> {
  const results: string[] = [];
  const workingProxiesPath = "working_proxies.json";
  for (const proxy of proxies) {
    const isValid = await checkProxyWithTimeout(proxy, maxTimeout);
    if (isValid) {
      console.log(`\x1b[32m[+] ${proxy}\x1b[0m`);
      results.push(proxy);
      // update working_proxies.json
      let workingProxies: { [key: string]: { lastChecked: number } } = {};
      if (fs.existsSync(workingProxiesPath)) {
        try {
          const fileContent = fs.readFileSync(workingProxiesPath, "utf8");
          workingProxies = JSON.parse(fileContent);
        } catch (error) {
          console.error("Error parsing working_proxies.json:", error);
        }
      }
      workingProxies[proxy] = { lastChecked: Date.now() };
      fs.writeFileSync(
        workingProxiesPath,
        JSON.stringify(workingProxies, null, 4)
      );
    } else {
      // console.log(`\x1b[31m[-] ${proxy}\x1b[0m`);
    }
  }
  parentPort?.postMessage(results);
}

if (isMainThread) {
  async function scrapeAndCheckProxies(): Promise<void> {
    // Clear working_proxies.json before restarting
    const workingProxiesPath = "working_proxies.json";
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
    console.log("Cleared working_proxies.json");

    await scrapeProxies();
    const proxies = fs
      .readFileSync(config.InputFile, "utf-8")
      .split("\n")
      .filter(Boolean);
    const chunkSize = Math.ceil(proxies.length / config.Threads);
    const threads: Promise<void>[] = [];

    for (let i = 0; i < config.Threads; i++) {
      const chunk = proxies.slice(i * chunkSize, (i + 1) * chunkSize);
      threads.push(
        new Promise((resolve, reject) => {
          const worker = new Worker(__filename, {
            workerData: { proxies: chunk, maxTimeout: config.MaxTimeout },
          });
          worker.on("message", (message: string[]) => {
            validProxies = validProxies.concat(message);
            resolve();
          });
          worker.on("error", reject);
          worker.on("exit", (code: number) => {
            if (code !== 0)
              reject(new Error(`Worker stopped with exit code ${code}`));
          });
        })
      );
    }

    await Promise.all(threads);
    console.log(`Finished checking proxies!`);
  }

  async function main(): Promise<void> {
    while (true) {
      await scrapeAndCheckProxies();
      console.log("Waiting before next cycle...");
      await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
    }
  }

  process.on("SIGINT", () => {
    console.log("\nGracefully shutting down...");
    console.log(`Checked proxies didn't save!`);
    process.exit();
  });

  main();
} else {
  workerFunction(workerData as { proxies: string[]; maxTimeout: number });
}



PROMPT: You are an advanced o1 engineer designed to analyze files and provide edit instructions based on user requests. Your task is to:

1. Understand the User Request: Carefully interpret what the user wants to achieve with the modification.
2. Analyze the File(s): Review the content of the provided file(s).
3. Generate Edit Instructions: Provide clear, step-by-step instructions on how to modify the file(s) to address the user's request.

Your response should be in the following format:

```
File: [file_path]
Instructions:
1. [First edit instruction]
2. [Second edit instruction]
...

File: [another_file_path]
Instructions:
1. [First edit instruction]
2. [Second edit instruction]
...
```

Only provide instructions for files that need changes. Be specific and clear in your instructions.

User request: Added files:
File: index.ts
Content:
import { checkProxyArchive } from "./providers/checkerProxyArchive";
import { github } from "./providers/github";
import * as fs from "fs";
import http from "http";
import path from "path";
import { Worker, isMainThread, parentPort, workerData } from "worker_threads";
import { Elysia } from "elysia";
import cp from "child_process";

let proxies: string[];

async function scrapeProxies() {
  const [one, two] = await Promise.all([checkProxyArchive(), github()]);

  proxies = [...one, ...two];

  proxies = [...new Set(proxies)];

  fs.writeFileSync("proxies.txt", proxies.join("\n"));

  console.log(`Scraped ${proxies.length.toLocaleString("en-US")} proxy(ies)`);
}

const dataPath = "data.json";
if (!fs.existsSync(dataPath)) {
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: "" }));
}
const data = JSON.parse(fs.readFileSync(dataPath, "utf8"));

if (data.lastScrape === "" || Date.now() - data.lastScrape > 10 * 60 * 1000) {
  scrapeProxies();
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: Date.now() }));
} else {
  proxies = fs.readFileSync("proxies.txt", "utf8").split("\n");
  proxies = [...new Set(proxies)];

  console.log(`Loaded ${proxies.length.toLocaleString("en-US")} proxy(ies)`);

  fs.writeFileSync("proxies.txt", proxies.join("\n"));
}

const app = new Elysia();

app.get("/getProxy", () => {
  const workingProxiesPath = "working_proxies.json";
  if (!fs.existsSync(workingProxiesPath)) {
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
  }
  const workingProxies = JSON.parse(
    fs.readFileSync(workingProxiesPath, "utf8")
  );

  const recentProxies = Object.entries(workingProxies).filter(
    ([_, data]: [string, any]) => Date.now() - data.lastChecked < 60 * 1000
  );

  if (recentProxies.length === 0) {
    return null;
  }

  const [selectedProxy] =
    recentProxies[Math.floor(Math.random() * recentProxies.length)];
  return selectedProxy;
});

app.listen(1111);

const configPath = path.join(__dirname, "config.json");

interface Config {
  Threads: number;
  InputFile: string;
  MaxTimeout: number;
  Hosts: string[];
}

const defaultConfig: Config = {
  Threads: 1,
  InputFile: "proxies.txt",
  MaxTimeout: 1000,
  Hosts: ["example.com"],
};

if (!fs.existsSync(configPath)) {
  fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4));
}

const config: Config = JSON.parse(fs.readFileSync(configPath, "utf-8"));

let validProxies: string[] = [];

function getRandomHost(): string {
  const hosts = config.Hosts;
  return hosts[Math.floor(Math.random() * hosts.length)];
}

export async function checkProxy(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  const [host, port] = proxy.split(":");
  const targetHost = getRandomHost();
  const proxyUrl = `http://${host}:${port}`;
  const url = `http://${targetHost}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), maxTimeout);

    return new Promise<boolean>((resolve) => {
      const curlCommand = `curl "${url}" --proxy "${proxyUrl}" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" -H "Host: ${targetHost}" -o /dev/null -w "%{http_code}"`;

      cp.exec(curlCommand, { timeout: maxTimeout }, (error, stdout, stderr) => {
        clearTimeout(timeoutId);
        if (error) {
          resolve(false);
        } else {
          const statusCode = parseInt(stdout.trim(), 10);
          resolve(statusCode === 200);
        }
      });
    });
  } catch (error) {
    return false;
  }
}

async function checkProxyWithTimeout(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  return Promise.race([
    checkProxy(proxy, maxTimeout),
    new Promise<boolean>((resolve) =>
      setTimeout(() => resolve(false), maxTimeout)
    ),
  ]);
}

async function workerFunction({
  proxies,
  maxTimeout,
}: {
  proxies: string[];
  maxTimeout: number;
}): Promise<void> {
  const results: string[] = [];
  const workingProxiesPath = "working_proxies.json";
  for (const proxy of proxies) {
    const isValid = await checkProxyWithTimeout(proxy, maxTimeout);
    if (isValid) {
      console.log(`\x1b[32m[+] ${proxy}\x1b[0m`);
      results.push(proxy);
      // update working_proxies.json
      let workingProxies: { [key: string]: { lastChecked: number } } = {};
      if (fs.existsSync(workingProxiesPath)) {
        try {
          const fileContent = fs.readFileSync(workingProxiesPath, "utf8");
          workingProxies = JSON.parse(fileContent);
        } catch (error) {
          console.error("Error parsing working_proxies.json:", error);
        }
      }
      workingProxies[proxy] = { lastChecked: Date.now() };
      fs.writeFileSync(
        workingProxiesPath,
        JSON.stringify(workingProxies, null, 4)
      );
    } else {
      // console.log(`\x1b[31m[-] ${proxy}\x1b[0m`);
    }
  }
  parentPort?.postMessage(results);
}

if (isMainThread) {
  async function scrapeAndCheckProxies(): Promise<void> {
    // Clear working_proxies.json before restarting
    const workingProxiesPath = "working_proxies.json";
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
    console.log("Cleared working_proxies.json");

    await scrapeProxies();
    const proxies = fs
      .readFileSync(config.InputFile, "utf-8")
      .split("\n")
      .filter(Boolean);
    const chunkSize = Math.ceil(proxies.length / config.Threads);
    const threads: Promise<void>[] = [];

    for (let i = 0; i < config.Threads; i++) {
      const chunk = proxies.slice(i * chunkSize, (i + 1) * chunkSize);
      threads.push(
        new Promise((resolve, reject) => {
          const worker = new Worker(__filename, {
            workerData: { proxies: chunk, maxTimeout: config.MaxTimeout },
          });
          worker.on("message", (message: string[]) => {
            validProxies = validProxies.concat(message);
            resolve();
          });
          worker.on("error", reject);
          worker.on("exit", (code: number) => {
            if (code !== 0)
              reject(new Error(`Worker stopped with exit code ${code}`));
          });
        })
      );
    }

    await Promise.all(threads);
    console.log(`Finished checking proxies!`);
  }

  async function main(): Promise<void> {
    while (true) {
      await scrapeAndCheckProxies();
      console.log("Waiting before next cycle...");
      await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
    }
  }

  process.on("SIGINT", () => {
    console.log("\nGracefully shutting down...");
    console.log(`Checked proxies didn't save!`);
    process.exit();
  });

  main();
} else {
  workerFunction(workerData as { proxies: string[]; maxTimeout: number });
}



User request: add debugs

Files to modify:

File: index.ts
Content:
import { checkProxyArchive } from "./providers/checkerProxyArchive";
import { github } from "./providers/github";
import * as fs from "fs";
import http from "http";
import path from "path";
import { Worker, isMainThread, parentPort, workerData } from "worker_threads";
import { Elysia } from "elysia";
import cp from "child_process";

let proxies: string[];

async function scrapeProxies() {
  const [one, two] = await Promise.all([checkProxyArchive(), github()]);

  proxies = [...one, ...two];

  proxies = [...new Set(proxies)];

  fs.writeFileSync("proxies.txt", proxies.join("\n"));

  console.log(`Scraped ${proxies.length.toLocaleString("en-US")} proxy(ies)`);
}

const dataPath = "data.json";
if (!fs.existsSync(dataPath)) {
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: "" }));
}
const data = JSON.parse(fs.readFileSync(dataPath, "utf8"));

if (data.lastScrape === "" || Date.now() - data.lastScrape > 10 * 60 * 1000) {
  scrapeProxies();
  fs.writeFileSync(dataPath, JSON.stringify({ lastScrape: Date.now() }));
} else {
  proxies = fs.readFileSync("proxies.txt", "utf8").split("\n");
  proxies = [...new Set(proxies)];

  console.log(`Loaded ${proxies.length.toLocaleString("en-US")} proxy(ies)`);

  fs.writeFileSync("proxies.txt", proxies.join("\n"));
}

const app = new Elysia();

app.get("/getProxy", () => {
  const workingProxiesPath = "working_proxies.json";
  if (!fs.existsSync(workingProxiesPath)) {
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
  }
  const workingProxies = JSON.parse(
    fs.readFileSync(workingProxiesPath, "utf8")
  );

  const recentProxies = Object.entries(workingProxies).filter(
    ([_, data]: [string, any]) => Date.now() - data.lastChecked < 60 * 1000
  );

  if (recentProxies.length === 0) {
    return null;
  }

  const [selectedProxy] =
    recentProxies[Math.floor(Math.random() * recentProxies.length)];
  return selectedProxy;
});

app.listen(1111);

const configPath = path.join(__dirname, "config.json");

interface Config {
  Threads: number;
  InputFile: string;
  MaxTimeout: number;
  Hosts: string[];
}

const defaultConfig: Config = {
  Threads: 1,
  InputFile: "proxies.txt",
  MaxTimeout: 1000,
  Hosts: ["example.com"],
};

if (!fs.existsSync(configPath)) {
  fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 4));
}

const config: Config = JSON.parse(fs.readFileSync(configPath, "utf-8"));

let validProxies: string[] = [];

function getRandomHost(): string {
  const hosts = config.Hosts;
  return hosts[Math.floor(Math.random() * hosts.length)];
}

export async function checkProxy(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  const [host, port] = proxy.split(":");
  const targetHost = getRandomHost();
  const proxyUrl = `http://${host}:${port}`;
  const url = `http://${targetHost}`;

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), maxTimeout);

    return new Promise<boolean>((resolve) => {
      const curlCommand = `curl "${url}" --proxy "${proxyUrl}" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" -H "Host: ${targetHost}" -o /dev/null -w "%{http_code}"`;

      cp.exec(curlCommand, { timeout: maxTimeout }, (error, stdout, stderr) => {
        clearTimeout(timeoutId);
        if (error) {
          resolve(false);
        } else {
          const statusCode = parseInt(stdout.trim(), 10);
          resolve(statusCode === 200);
        }
      });
    });
  } catch (error) {
    return false;
  }
}

async function checkProxyWithTimeout(
  proxy: string,
  maxTimeout: number
): Promise<boolean> {
  return Promise.race([
    checkProxy(proxy, maxTimeout),
    new Promise<boolean>((resolve) =>
      setTimeout(() => resolve(false), maxTimeout)
    ),
  ]);
}

async function workerFunction({
  proxies,
  maxTimeout,
}: {
  proxies: string[];
  maxTimeout: number;
}): Promise<void> {
  const results: string[] = [];
  const workingProxiesPath = "working_proxies.json";
  for (const proxy of proxies) {
    const isValid = await checkProxyWithTimeout(proxy, maxTimeout);
    if (isValid) {
      console.log(`\x1b[32m[+] ${proxy}\x1b[0m`);
      results.push(proxy);
      // update working_proxies.json
      let workingProxies: { [key: string]: { lastChecked: number } } = {};
      if (fs.existsSync(workingProxiesPath)) {
        try {
          const fileContent = fs.readFileSync(workingProxiesPath, "utf8");
          workingProxies = JSON.parse(fileContent);
        } catch (error) {
          console.error("Error parsing working_proxies.json:", error);
        }
      }
      workingProxies[proxy] = { lastChecked: Date.now() };
      fs.writeFileSync(
        workingProxiesPath,
        JSON.stringify(workingProxies, null, 4)
      );
    } else {
      // console.log(`\x1b[31m[-] ${proxy}\x1b[0m`);
    }
  }
  parentPort?.postMessage(results);
}

if (isMainThread) {
  async function scrapeAndCheckProxies(): Promise<void> {
    // Clear working_proxies.json before restarting
    const workingProxiesPath = "working_proxies.json";
    fs.writeFileSync(workingProxiesPath, JSON.stringify({}));
    console.log("Cleared working_proxies.json");

    await scrapeProxies();
    const proxies = fs
      .readFileSync(config.InputFile, "utf-8")
      .split("\n")
      .filter(Boolean);
    const chunkSize = Math.ceil(proxies.length / config.Threads);
    const threads: Promise<void>[] = [];

    for (let i = 0; i < config.Threads; i++) {
      const chunk = proxies.slice(i * chunkSize, (i + 1) * chunkSize);
      threads.push(
        new Promise((resolve, reject) => {
          const worker = new Worker(__filename, {
            workerData: { proxies: chunk, maxTimeout: config.MaxTimeout },
          });
          worker.on("message", (message: string[]) => {
            validProxies = validProxies.concat(message);
            resolve();
          });
          worker.on("error", reject);
          worker.on("exit", (code: number) => {
            if (code !== 0)
              reject(new Error(`Worker stopped with exit code ${code}`));
          });
        })
      );
    }

    await Promise.all(threads);
    console.log(`Finished checking proxies!`);
  }

  async function main(): Promise<void> {
    while (true) {
      await scrapeAndCheckProxies();
      console.log("Waiting before next cycle...");
      await new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
    }
  }

  process.on("SIGINT", () => {
    console.log("\nGracefully shutting down...");
    console.log(`Checked proxies didn't save!`);
    process.exit();
  });

  main();
} else {
  workerFunction(workerData as { proxies: string[]; maxTimeout: number });
}