-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsecretSauce.cpp
More file actions
208 lines (174 loc) · 8.07 KB
/
Copy pathsecretSauce.cpp
File metadata and controls
208 lines (174 loc) · 8.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <iostream>
#include <fstream>
#include <thread>
#include <vector>
#include <string>
#include <filesystem>
#include <curl/curl.h>
#include "json.hpp"
#include <mutex>
#include <queue>
#include <condition_variable>
using json = nlohmann::json;
namespace fs = std::filesystem;
// Mutex and condition variables for thread synchronization
std::mutex queueMutex;
std::condition_variable condition;
bool finished = false;
std::queue<std::pair<std::string, std::string>> taskQueue; // Holds tasks (image URL and filename)
// Callback function for libcurl to write received data to a string
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// Function to download an image and save it to a file
void downloadImage(const std::string& url, const std::string& filePath) {
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init(); // Initialize curl session
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // Set URL
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // Set callback to capture data
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // Data to write
res = curl_easy_perform(curl); // Perform the request
if (res != CURLE_OK) {
std::cerr << "💥 Uh-oh! Couldn't download image: " << curl_easy_strerror(res) << std::endl;
} else {
// Write the downloaded image to the file system
std::ofstream file(filePath, std::ios::binary);
if (file) {
file.write(readBuffer.c_str(), readBuffer.size());
std::cout << "🎉 Image successfully saved at: " << filePath << std::endl;
} else {
std::cerr << "❌ Error: Could not write to file: " << filePath << std::endl;
}
}
curl_easy_cleanup(curl); // Clean up the curl session
}
}
// Function to fetch JSON from the given URL
std::string fetchJson(const std::string& url) {
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init(); // Initialize curl session
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // Set URL for JSON
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // Set callback to write JSON data
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // Write received data into the buffer
res = curl_easy_perform(curl); // Perform the request
if (res != CURLE_OK) {
std::cerr << "🤔 Something went wrong while fetching JSON: " << curl_easy_strerror(res) << std::endl;
return "";
}
curl_easy_cleanup(curl); // Clean up curl session
}
return readBuffer; // Return the received JSON data as a string
}
// Worker function for threads in the thread pool
void worker() {
while (true) {
std::pair<std::string, std::string> task;
{
std::unique_lock<std::mutex> lock(queueMutex);
condition.wait(lock, [] { return !taskQueue.empty() || finished; });
if (finished && taskQueue.empty()) break; // Exit condition for threads
task = taskQueue.front(); // Get the next task
taskQueue.pop();
}
// Process the task (download the image)
downloadImage(task.first, task.second);
}
}
// Function to download images from the JSON data using a thread pool
void downloadImagesFromJson(const json& data, const std::string& downloadDir, int threadCount = 4) {
int fileIndex = 1;
// Spawn a thread pool
std::vector<std::thread> threadPool;
for (int i = 0; i < threadCount; ++i) {
threadPool.emplace_back(worker); // Start worker threads
}
// Prepare the tasks (URL and file paths)
for (auto& [key, subproperty] : data.items()) {
if (subproperty.contains("dhd")) {
std::string imageUrl = subproperty["dhd"];
std::cout << "🔎 Found image URL: " << imageUrl << std::endl;
// Extract the file extension and remove query parameters
std::string ext;
size_t dotPos = imageUrl.find_last_of('.');
size_t queryPos = imageUrl.find('?');
if (dotPos != std::string::npos) {
if (queryPos != std::string::npos) {
ext = imageUrl.substr(dotPos, queryPos - dotPos); // Extract only the extension without query parameters
} else {
ext = imageUrl.substr(dotPos); // No query parameters, just extract the extension
}
}
// If extension isn't valid, default to .jpg
if (ext != ".jpg" && ext != ".png") {
ext = ".jpg";
}
// Create the filename and path
std::string filename = std::to_string(fileIndex++) + ext;
std::string filePath = fs::path(downloadDir) / filename;
// Add task to queue
{
std::lock_guard<std::mutex> lock(queueMutex);
taskQueue.emplace(imageUrl, filePath); // Add the task (URL, file path) to the queue
}
condition.notify_one(); // Notify a thread to start processing
}
}
// Indicate that we are done adding tasks
{
std::lock_guard<std::mutex> lock(queueMutex);
finished = true;
}
condition.notify_all(); // Wake up all threads to finish their tasks
// Join all threads
for (auto& t : threadPool) {
if (t.joinable()) {
t.join(); // Wait for the threads to finish
}
}
}
int main() {
// Fun Ascii art banner
std::cout << R"(
________ ________ ________ _______ ___ ________ ________ ________ ________
|\ __ \|\ __ \|\ ___ \|\ ___ \ |\ \ |\ ____\|\ __ \|\ __ \|\ ____\
\ \ \|\ \ \ \|\ \ \ \\ \ \ \ __/|\ \ \ \ \ \___|\ \ \|\ \ \ \|\ \ \ \___|_
\ \ ____\ \ __ \ \ \\ \ \ \ \_|/_\ \ \ \ \ \ __\ \ __ \ \ ____\ \_____ \
\ \ \___|\ \ \ \ \ \ \\ \ \ \ \_|\ \ \ \____ \ \ \|\ \ \ \ \ \ \ \___|\|____|\ \
\ \__\ \ \__\ \__\ \__\\ \__\ \_______\ \_______\ \ \_______\ \__\ \__\ \__\ ____\_\ \
\|__| \|__|\|__|\|__| \|__|\|_______|\|_______| \|_______|\|__|\|__|\|__| |\_________\
\|_________|
)";
std::cout << "\n🤑 Time to grab some epic wallpapers from your favorite cash-grabbing app!\n";
// URL to fetch JSON from
std::string url = "https://storage.googleapis.com/panels-api/data/20240916/media-1a-i-p~s";
// Fetch the JSON
std::string jsonData = fetchJson(url);
if (jsonData.empty()) {
std::cerr << "💔 Oh no! We couldn't fetch any data. Try again later!" << std::endl;
return 1;
}
// Parse the JSON
json parsedData = json::parse(jsonData);
if (!parsedData.contains("data")) {
std::cerr << "💢 The JSON file seems to be missing a 'data' section. Are we being trolled?" << std::endl;
return 1;
}
// Create the 'downloads' directory if it doesn't exist
std::string downloadDir = "downloads";
if (!fs::exists(downloadDir)) {
fs::create_directory(downloadDir);
std::cout << "📁 No folder? No problem! Created 'downloads' directory for you!" << std::endl;
}
// Start downloading images using the thread pool
std::cout << "🚀 Firing up the download engine with multithreaded awesomeness! Hold tight...\n";
downloadImagesFromJson(parsedData["data"], downloadDir, 8); // Pass the desired number of threads (e.g., 8)
std::cout << "🎉 Done! All images have been downloaded to the 'downloads' folder. Enjoy your new wallpapers!\n";
return 0;
}