Video_Tamer / speedster.cpp
Bl4ckSpaces's picture
Create speedster.cpp
04def54 verified
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <fstream>
#include <string>
#include <curl/curl.h>
#include <random>
using namespace std;
const int NUM_THREADS = 12;
mutex log_mutex;
// Koleksi User-Agent Modern (Desktop & Mobile)
const vector<string> USER_AGENTS = {
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 14; SM-S928B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (iPad; CPU OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/124.0.6367.111 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"
};
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
return fwrite(ptr, size, nmemb, stream);
}
bool download_chunk(const string& url, const string& out_filename, long start_byte, long end_byte, int thread_id) {
CURL *curl;
FILE *fp;
CURLcode res;
curl = curl_easy_init();
if (curl) {
fp = fopen(out_filename.c_str(), "wb");
string range = to_string(start_byte) + "-" + to_string(end_byte);
// 1. Pilih User-Agent acak/berbeda untuk thread ini
string selected_ua = USER_AGENTS[thread_id % USER_AGENTS.size()];
// 2. Rakit Header HTTP Siluman (Mirip Request Video Asli)
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, ("User-Agent: " + selected_ua).c_str());
headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.9,id;q=0.8");
headers = curl_slist_append(headers, "Connection: keep-alive");
headers = curl_slist_append(headers, "Sec-Fetch-Dest: video"); // Manipulasi bahwa ini adalah request elemen <video>
headers = curl_slist_append(headers, "Sec-Fetch-Mode: no-cors");
headers = curl_slist_append(headers, "Sec-Fetch-Site: cross-site");
headers = curl_slist_append(headers, "Cache-Control: no-cache");
headers = curl_slist_append(headers, "Pragma: no-cache");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_RANGE, range.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Pasang header siluman
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Ikuti jika server melempar redirect (CDN behavior)
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);
int retries = 3;
while (retries > 0) {
res = curl_easy_perform(curl);
if (res == CURLE_OK) break;
retries--;
this_thread::sleep_for(chrono::milliseconds(500)); // Delay super singkat jika gagal, lalu hantam lagi
}
fclose(fp);
curl_slist_free_all(headers); // Bersihkan memory header
curl_easy_cleanup(curl);
lock_guard<mutex> guard(log_mutex);
if (res == CURLE_OK) {
cout << "Thread " << thread_id << " (UA: " << selected_ua.substr(13, 15) << "...) Selesai!\n";
return true;
} else {
cout << "Thread " << thread_id << " Gagal: " << curl_easy_strerror(res) << "\n";
return false;
}
}
return false;
}
int main(int argc, char* argv[]) {
if (argc < 4) {
cout << "Usage: ./speedster <URL> <OUTPUT_FILE> <TOTAL_SIZE>\n";
return 1;
}
string url = argv[1];
string output_file = argv[2];
long total_size = stol(argv[3]);
long chunk_size = total_size / NUM_THREADS;
vector<thread> threads;
vector<string> temp_files;
cout << "[Speedster Engine] Memulai 12 Threads Siluman Paralel...\n";
for (int i = 0; i < NUM_THREADS; ++i) {
long start_byte = i * chunk_size;
long end_byte = (i == NUM_THREADS - 1) ? total_size - 1 : (start_byte + chunk_size - 1);
string temp_file = output_file + ".part" + to_string(i);
temp_files.push_back(temp_file);
threads.emplace_back(download_chunk, url, temp_file, start_byte, end_byte, i);
}
for (auto& t : threads) {
t.join();
}
cout << "[Speedster Engine] Merging chunks...\n";
ofstream final_file(output_file, ios_base::binary);
for (const string& temp_file : temp_files) {
ifstream file_chunk(temp_file, ios_base::binary);
final_file << file_chunk.rdbuf();
file_chunk.close();
remove(temp_file.c_str());
}
final_file.close();
cout << "[Speedster Engine] Selesai: " << output_file << "\n";
return 0;
}