Back to Home
Gistify Snippet
Public
Scraper iloveimg
Scraper iloveimg
#github-gist#javascript#gist:39401894229df773b0d21aff7bc316dd#gistsync:2026-09-02T12:40:34Z
1
Rawiloveimg.jsjavascript
373 lines| 1 | |
| 2 | |
| 3 | import * as __ns_613 from 'axios' |
| 4 | const axios = __ns_613.default |
| 5 | import * as __ns_614 from 'cheerio' |
| 6 | const cheerio = __ns_614 |
| 7 | import * as __ns_615 from 'crypto' |
| 8 | const crypto = __ns_615.default |
| 9 | import * as __ns_616 from 'form-data' |
| 10 | const FormData = __ns_616.default |
| 11 | import * as __ns_617 from 'fs' |
| 12 | const fs = __ns_617.default |
| 13 | import * as __ns_618 from 'fs/promises' |
| 14 | const fsp = __ns_618.default |
| 15 | import * as __ns_619 from 'node:url' |
| 16 | const pathToFileURL = __ns_619.pathToFileURL |
| 17 | import * as __ns_620 from 'os' |
| 18 | const os = __ns_620.default |
| 19 | import * as __ns_621 from 'path' |
| 20 | const path = __ns_621.default |
| 21 | |
| 22 | const TOOL = "compressimage"; |
| 23 | const UA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Mobile Safari/537.36"; |
| 24 | const SERVERS = [ |
| 25 | "api1g", "api2g", "api3g", "api8g", "api9g", "api10g", "api11g", |
| 26 | "api12g", "api13g", "api14g", "api15g", "api16g", "api17g", |
| 27 | "api18g", "api19g", "api20g", "api21g", "api22g", "api24g", "api25g", |
| 28 | "api1", "api2", "api3", "api4", "api5", "api6", "api7", "api8", |
| 29 | "api9", "api10", "api11", "api12", "api13", "api14", "api15", |
| 30 | "api16", "api17", "api18", "api19", "api20", "api21", "api22", |
| 31 | "api23", "api24", "api25", "api26", "api27", "api28", "api29", |
| 32 | "api30", "api31", "api32", "api33", "api34", "api35", "api36", |
| 33 | "api37", "api38", "api39", "api40" |
| 34 | ]; |
| 35 | |
| 36 | function randomTask(length = 120) { |
| 37 | const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| 38 | let result = ""; |
| 39 | while (result.length < length) { |
| 40 | const bytes = crypto.randomBytes(length); |
| 41 | for (const byte of bytes) { |
| 42 | if (result.length >= length) break; |
| 43 | result += chars[byte % chars.length]; |
| 44 | } |
| 45 | } |
| 46 | return result; |
| 47 | } |
| 48 | |
| 49 | function shuffle(array) { |
| 50 | return [...array].sort(() => Math.random() - 0.5); |
| 51 | } |
| 52 | |
| 53 | function contentType(file) { |
| 54 | const ext = path.extname(file).toLowerCase(); |
| 55 | if (ext === ".png") return "image/png"; |
| 56 | if (ext === ".webp") return "image/webp"; |
| 57 | if (ext === ".gif") return "image/gif"; |
| 58 | if (ext === ".bmp") return "image/bmp"; |
| 59 | if (ext === ".tif" || ext === ".tiff") return "image/tiff"; |
| 60 | return "image/jpeg"; |
| 61 | } |
| 62 | |
| 63 | async function getToken() { |
| 64 | const res = await axios.get("https://www.iloveimg.com/compress-image", { |
| 65 | headers: { |
| 66 | "user-agent": UA, |
| 67 | accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", |
| 68 | "accept-language": "id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7" |
| 69 | }, |
| 70 | timeout: 120000, |
| 71 | validateStatus: () => true |
| 72 | }); |
| 73 | if (res.status !== 200) throw new Error(`Gagal membuka halaman token: HTTP ${res.status}`); |
| 74 | const $ = cheerio.load(res.data); |
| 75 | const script = $("script").filter((_, el) => String($(el).html() || "").includes("ilovepdfConfig =")).html(); |
| 76 | if (!script) throw new Error("Config script tidak ditemukan"); |
| 77 | const jsonText = script.split("ilovepdfConfig = ")[1]?.split(";")[0]; |
| 78 | if (!jsonText) throw new Error("Config JSON tidak ditemukan"); |
| 79 | const json = JSON.parse(jsonText); |
| 80 | const csrf = $("meta[name='csrf-token']").attr("content"); |
| 81 | if (!json.token || !csrf) throw new Error("Token atau CSRF tidak ditemukan"); |
| 82 | return { token: json.token, csrf }; |
| 83 | } |
| 84 | |
| 85 | async function uploadImage(server, headers, input, task) { |
| 86 | const form = new FormData(); |
| 87 | form.append("name", path.basename(input)); |
| 88 | form.append("chunk", "0"); |
| 89 | form.append("chunks", "1"); |
| 90 | form.append("task", task); |
| 91 | form.append("preview", "1"); |
| 92 | form.append("file", fs.createReadStream(input), { |
| 93 | filename: path.basename(input), |
| 94 | contentType: contentType(input) |
| 95 | }); |
| 96 | const res = await axios.post(`https://${server}.iloveimg.com/v1/upload`, form, { |
| 97 | headers: { ...headers, ...form.getHeaders() }, |
| 98 | timeout: 180000, |
| 99 | maxContentLength: Infinity, |
| 100 | maxBodyLength: Infinity, |
| 101 | validateStatus: () => true |
| 102 | }); |
| 103 | if (res.status !== 200 || !res.data?.server_filename) throw new Error(`Upload gagal: HTTP ${res.status}`); |
| 104 | return { filename: res.data.filename || path.basename(input), server_filename: res.data.server_filename }; |
| 105 | } |
| 106 | |
| 107 | async function processCompress(server, headers, task, file) { |
| 108 | const payload = { task, tool: TOOL, files: [{ server_filename: file.server_filename, filename: file.filename }] }; |
| 109 | const res = await axios.post(`https://${server}.iloveimg.com/v1/process`, payload, { |
| 110 | headers: { ...headers, "content-type": "application/json" }, |
| 111 | timeout: 180000, |
| 112 | maxContentLength: Infinity, |
| 113 | maxBodyLength: Infinity, |
| 114 | validateStatus: () => true |
| 115 | }); |
| 116 | if (res.status !== 200) throw new Error(`Process gagal: HTTP ${res.status}`); |
| 117 | return res.data; |
| 118 | } |
| 119 | |
| 120 | async function downloadResult(server, headers, task) { |
| 121 | const res = await axios.get(`https://${server}.iloveimg.com/v1/download/${task}`, { |
| 122 | headers, |
| 123 | responseType: "arraybuffer", |
| 124 | timeout: 180000, |
| 125 | maxContentLength: Infinity, |
| 126 | maxBodyLength: Infinity, |
| 127 | validateStatus: () => true |
| 128 | }); |
| 129 | if (res.status !== 200 || !res.data) throw new Error(`Download gagal: HTTP ${res.status}`); |
| 130 | return Buffer.from(res.data); |
| 131 | } |
| 132 | |
| 133 | async function compressImage(buffer, ext = 'jpg') { |
| 134 | const tempFile = path.join(os.tmpdir(), `iloveimg-${Date.now()}.${ext}`); |
| 135 | await fsp.writeFile(tempFile, buffer); |
| 136 | |
| 137 | try { |
| 138 | const { token, csrf } = await getToken(); |
| 139 | const errors = []; |
| 140 | for (const server of shuffle(SERVERS)) { |
| 141 | const task = randomTask(); |
| 142 | const headers = { |
| 143 | authorization: `Bearer ${token}`, |
| 144 | origin: "https://www.iloveimg.com", |
| 145 | referer: "https://www.iloveimg.com/compress-image", |
| 146 | cookie: `_csrf=${csrf}`, |
| 147 | "user-agent": UA, |
| 148 | accept: "application/json, text/plain, */*" |
| 149 | }; |
| 150 | try { |
| 151 | const uploaded = await uploadImage(server, headers, tempFile, task); |
| 152 | await processCompress(server, headers, task, uploaded); |
| 153 | const resultBuffer = await downloadResult(server, headers, task); |
| 154 | |
| 155 | const inputSize = buffer.length; |
| 156 | const outputSize = resultBuffer.length; |
| 157 | |
| 158 | await fsp.unlink(tempFile); |
| 159 | return { |
| 160 | Status: true, |
| 161 | Buffer: resultBuffer, |
| 162 | InputSize: inputSize, |
| 163 | OutputSize: outputSize, |
| 164 | SavedSize: Math.max(0, inputSize - outputSize) |
| 165 | }; |
| 166 | } catch (err) { |
| 167 | errors.push(err.message); |
| 168 | } |
| 169 | } |
| 170 | throw new Error(errors.slice(0, 5).join(" | ")); |
| 171 | } catch (e) { |
| 172 | if (fs.existsSync(tempFile)) await fsp.unlink(tempFile); |
| 173 | return { Status: false, Error: e.message }; |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | async function getUpscaleAuthToken() { |
| 178 | const pageUrl = 'https://www.iloveimg.com/upscale-image'; |
| 179 | const res = await axios.get(pageUrl, { |
| 180 | headers: { |
| 181 | 'User-Agent': UA, |
| 182 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', |
| 183 | 'Accept-Language': 'en-US,en;q=0.9', |
| 184 | }, |
| 185 | timeout: 15000, |
| 186 | }); |
| 187 | |
| 188 | const html = res.data; |
| 189 | const configMatch = html.match(/var\s+(?:ilovepdfConfig|iloveimgConfig)\s*=\s*({[\s\S]+?});/); |
| 190 | if (configMatch) { |
| 191 | try { |
| 192 | const config = JSON.parse(configMatch[1]); |
| 193 | if (config.token) return config.token; |
| 194 | } catch (_) {} |
| 195 | } |
| 196 | |
| 197 | const tokenMatch = html.match(/"token"\s*:\s*"(ey[a-zA-Z0-9_\-\.]+)"/) || html.match(/token:\s*'(ey[a-zA-Z0-9_\-\.]+)'/); |
| 198 | if (tokenMatch) return tokenMatch[1]; |
| 199 | |
| 200 | throw new Error('Gagal mengekstrak JWT token dari iLoveIMG.'); |
| 201 | } |
| 202 | |
| 203 | async function upscaleImage(input, options = {}) { |
| 204 | const multiplier = Number(options.multiplier) === 4 ? 4 : 2; |
| 205 | const startTime = Date.now(); |
| 206 | |
| 207 | const token = await getUpscaleAuthToken(); |
| 208 | const authHeaders = { |
| 209 | Authorization: `Bearer ${token}`, |
| 210 | Origin: 'https://www.iloveimg.com', |
| 211 | Referer: 'https://www.iloveimg.com/upscale-image', |
| 212 | }; |
| 213 | |
| 214 | const startRes = await axios.get('https://api.iloveimg.com/v1/start/upscaleimage', { |
| 215 | headers: authHeaders, |
| 216 | timeout: 15000, |
| 217 | }); |
| 218 | |
| 219 | const { server, task } = startRes.data; |
| 220 | if (!server || !task) { |
| 221 | throw new Error('Gagal memulai task upscale di server iLoveIMG.'); |
| 222 | } |
| 223 | |
| 224 | let fileBuffer = null; |
| 225 | let originalFilename = `image_${Date.now()}.jpg`; |
| 226 | |
| 227 | if (Buffer.isBuffer(input)) { |
| 228 | fileBuffer = input; |
| 229 | if (options.filename) originalFilename = options.filename; |
| 230 | } else if (typeof input === 'string') { |
| 231 | if (input.startsWith('http://') || input.startsWith('https://')) { |
| 232 | const imgRes = await axios.get(input, { |
| 233 | responseType: 'arraybuffer', |
| 234 | headers: { 'User-Agent': UA }, |
| 235 | }); |
| 236 | fileBuffer = Buffer.from(imgRes.data); |
| 237 | const urlPath = new URL(input).pathname; |
| 238 | const baseName = path.basename(urlPath); |
| 239 | if (baseName && baseName.includes('.')) originalFilename = baseName; |
| 240 | } else if (fs.existsSync(input)) { |
| 241 | fileBuffer = fs.readFileSync(input); |
| 242 | originalFilename = path.basename(input); |
| 243 | } else { |
| 244 | throw new Error(`File input tidak ditemukan: "${input}"`); |
| 245 | } |
| 246 | } else { |
| 247 | throw new Error('Format input tidak valid.'); |
| 248 | } |
| 249 | |
| 250 | const uploadForm = new FormData(); |
| 251 | uploadForm.append('task', task); |
| 252 | uploadForm.append('file', fileBuffer, { filename: originalFilename }); |
| 253 | |
| 254 | const uploadRes = await axios.post(`https://${server}/v1/upload`, uploadForm, { |
| 255 | headers: { |
| 256 | ...authHeaders, |
| 257 | ...uploadForm.getHeaders(), |
| 258 | }, |
| 259 | maxBodyLength: Infinity, |
| 260 | maxContentLength: Infinity, |
| 261 | timeout: 60000, |
| 262 | }); |
| 263 | |
| 264 | const serverFilename = uploadRes.data.server_filename; |
| 265 | if (!serverFilename) { |
| 266 | throw new Error('Gagal mengunggah berkas ke server iLoveIMG.'); |
| 267 | } |
| 268 | |
| 269 | const processForm = new FormData(); |
| 270 | processForm.append('task', task); |
| 271 | processForm.append('tool', 'upscaleimage'); |
| 272 | processForm.append('files[0][server_filename]', serverFilename); |
| 273 | processForm.append('files[0][filename]', originalFilename); |
| 274 | processForm.append('multiplier', String(multiplier)); |
| 275 | processForm.append('packaged_filename', `upscaled_${multiplier}x_${path.parse(originalFilename).name}`); |
| 276 | |
| 277 | const processRes = await axios.post(`https://${server}/v1/process`, processForm, { |
| 278 | headers: { |
| 279 | ...authHeaders, |
| 280 | ...processForm.getHeaders(), |
| 281 | }, |
| 282 | timeout: 90000, |
| 283 | }); |
| 284 | |
| 285 | let taskStatus = processRes.data.status; |
| 286 | |
| 287 | if (taskStatus === 'TaskProcessing' || taskStatus === 'TaskWaiting') { |
| 288 | let attempts = 0; |
| 289 | while (taskStatus !== 'TaskSuccess' && attempts < 30) { |
| 290 | await new Promise((r) => setTimeout(r, 1500)); |
| 291 | const checkRes = await axios.get(`https://${server}/v1/task/${task}`, { |
| 292 | headers: authHeaders, |
| 293 | timeout: 15000, |
| 294 | }); |
| 295 | taskStatus = checkRes.data.status; |
| 296 | if (taskStatus === 'TaskError') { |
| 297 | throw new Error(checkRes.data.status_message || 'Terjadi kesalahan saat memproses upscale gambar.'); |
| 298 | } |
| 299 | attempts++; |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | if (taskStatus !== 'TaskSuccess') { |
| 304 | throw new Error(`Status task tidak berhasil: ${taskStatus}`); |
| 305 | } |
| 306 | |
| 307 | const downloadUrl = `https://${server}/v1/download/${task}`; |
| 308 | const duration = `${((Date.now() - startTime) / 1000).toFixed(2)}s`; |
| 309 | |
| 310 | const downloadStream = await axios.get(downloadUrl, { |
| 311 | responseType: 'arraybuffer', |
| 312 | headers: authHeaders, |
| 313 | timeout: 60000, |
| 314 | }); |
| 315 | |
| 316 | const resultBuffer = Buffer.from(downloadStream.data); |
| 317 | |
| 318 | return { |
| 319 | success: true, |
| 320 | status: 'success', |
| 321 | engine: 'iLoveIMG AI Super Resolution', |
| 322 | multiplier: `${multiplier}x`, |
| 323 | downloadUrl, |
| 324 | duration, |
| 325 | resultBuffer, |
| 326 | buffer: resultBuffer, |
| 327 | fileSize: `${(resultBuffer.length / (1024 * 1024)).toFixed(2)} MB`, |
| 328 | }; |
| 329 | } |
| 330 | |
| 331 | const iloveimgUpscale = upscaleImage; |
| 332 | |
| 333 | if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { |
| 334 | const __exports = { compressImage: compressImage, getUpscaleAuthToken: getUpscaleAuthToken, upscaleImage: upscaleImage, iloveimgUpscale: iloveimgUpscale } |
| 335 | const __fns = Object.fromEntries(Object.entries(__exports).filter(([, v]) => typeof v === 'function')) |
| 336 | const __names = Object.keys(__fns) |
| 337 | if (__names.length === 0) { |
| 338 | console.log('Tidak ada fungsi yang bisa di-demo. Import modul ini dari kode lain.') |
| 339 | } else { |
| 340 | const __search = __names.find((n) => /search|cari/i.test(n)) |
| 341 | const __name = __search || __names[0] |
| 342 | const __fn = __fns[__name] |
| 343 | const __isClass = /^class\s/.test(Function.prototype.toString.call(__fn)) |
| 344 | const __defaultArgs = (() => { |
| 345 | const n = __name.toLowerCase() |
| 346 | if (/emoji/.test(n)) return [{ emoji: '😀😃' }] |
| 347 | if (/textpro|generate.*text|effect/.test(n)) return ['neon', 'Hello'] |
| 348 | if (/image|wallpaper|search|query|anime|movie|manga|news|lyrics|wiki|quote|stalk|detail/.test(n)) return ['naruto'] |
| 349 | if (/download|youtube|video|audio|music|spotify|tiktok|instagram|facebook|twitter|reels|terabox|media/.test(n)) return ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'] |
| 350 | if (/dork/.test(n)) return ['example.com', 'documents'] |
| 351 | if (/tts|speech|prompt|chat|ask|translate/.test(n)) return ['Hello world'] |
| 352 | if (/parse|format|normalize|list|features/.test(n)) return [] |
| 353 | return ['test'] |
| 354 | })() |
| 355 | let __args = __defaultArgs |
| 356 | if (process.argv.length > 2) __args = process.argv.slice(2).map((a) => { try { return JSON.parse(a) } catch { return a } }) |
| 357 | if (__args.length === 0 && !__search && !__isClass && __fn.length > 0) { |
| 358 | console.log('Fungsi: ' + __names.join(', ')) |
| 359 | console.log('Contoh: node ' + "iloveimg.js" + ' ' + __name + ' <arg>') |
| 360 | } else { |
| 361 | ;(async () => { |
| 362 | try { |
| 363 | const r = __isClass ? new __fn(...__args) : await __fn(...__args) |
| 364 | console.log(JSON.stringify(r, null, 2)) |
| 365 | } catch (e) { |
| 366 | console.error('Error: ' + (e && e.message ? e.message : e)) |
| 367 | process.exitCode = 1 |
| 368 | } |
| 369 | })() |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
Discussion & Comments0
No comments yet — be the first to leave feedback or start a code discussion.
Sign in with your GitHub account to write comments and join the discussion.