Reaperxxxx commited on
Commit
9fcf553
·
verified ·
1 Parent(s): 6c16192

Create index.js

Browse files
Files changed (1) hide show
  1. index.js +234 -0
index.js ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const { gotScraping } = require('got-scraping');
3
+ const axios = require('axios');
4
+ const tough = require('tough-cookie');
5
+ const { HttpsCookieAgent } = require('http-cookie-agent/http');
6
+ const cheerio = require('cheerio');
7
+
8
+ const app = express();
9
+ const PORT = process.env.PORT || 3000;
10
+
11
+ app.use(express.json());
12
+
13
+ // Method 1: Using got-scraping (Most reliable for anti-bot bypass)
14
+ async function extractWithGotScraping(url) {
15
+ try {
16
+ const response = await gotScraping({
17
+ url: url,
18
+ headerGeneratorOptions: {
19
+ browsers: [
20
+ {
21
+ name: 'chrome',
22
+ minVersion: 116,
23
+ maxVersion: 122
24
+ }
25
+ ],
26
+ devices: ['desktop'],
27
+ locales: ['en-US', 'en'],
28
+ operatingSystems: ['windows']
29
+ },
30
+ http2: true,
31
+ followRedirect: true,
32
+ maxRedirects: 10,
33
+ timeout: {
34
+ request: 30000
35
+ },
36
+ retry: {
37
+ limit: 3,
38
+ methods: ['GET'],
39
+ statusCodes: [408, 413, 429, 500, 502, 503, 504],
40
+ errorCodes: [
41
+ 'ETIMEDOUT',
42
+ 'ECONNRESET',
43
+ 'EADDRINUSE',
44
+ 'ECONNREFUSED',
45
+ 'EPIPE',
46
+ 'ENOTFOUND',
47
+ 'ENETUNREACH',
48
+ 'EAI_AGAIN'
49
+ ]
50
+ }
51
+ });
52
+
53
+ const html = response.body;
54
+ const $ = cheerio.load(html);
55
+
56
+ // Check for iframe
57
+ const iframe = $('iframe.embed-responsive-item');
58
+ const iframeExists = iframe.length > 0;
59
+ const iframeSrc = iframe.attr('src') || null;
60
+
61
+ // Check for download section
62
+ const downloadSection = $('.download-form, .message.video-details, .download');
63
+ const downloadSectionExists = downloadSection.length > 0;
64
+
65
+ // Extract file details
66
+ const fileName = $('strong').first().text().trim() || null;
67
+ const fileSize = $('abbr[title*="Bytes"]').text().trim() || null;
68
+ const resolution = $('.column:contains("Resolution")').text().replace('Resolution:', '').trim() || null;
69
+
70
+ return {
71
+ success: true,
72
+ url: url,
73
+ iframeExists: iframeExists,
74
+ iframeSrc: iframeSrc,
75
+ downloadSectionExists: downloadSectionExists,
76
+ fileDetails: {
77
+ fileName: fileName,
78
+ fileSize: fileSize,
79
+ resolution: resolution
80
+ },
81
+ method: 'got-scraping'
82
+ };
83
+
84
+ } catch (error) {
85
+ console.error('got-scraping error:', error.message);
86
+ return {
87
+ success: false,
88
+ error: error.message,
89
+ method: 'got-scraping'
90
+ };
91
+ }
92
+ }
93
+
94
+ // Method 2: Using axios with enhanced headers and cookie handling
95
+ async function extractWithAxios(url) {
96
+ try {
97
+ const cookieJar = new tough.CookieJar();
98
+
99
+ const client = axios.create({
100
+ httpsAgent: new HttpsCookieAgent({
101
+ cookies: { jar: cookieJar },
102
+ rejectUnauthorized: false
103
+ }),
104
+ headers: {
105
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
106
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
107
+ 'Accept-Language': 'en-US,en;q=0.9',
108
+ 'Accept-Encoding': 'gzip, deflate, br',
109
+ 'DNT': '1',
110
+ 'Connection': 'keep-alive',
111
+ 'Upgrade-Insecure-Requests': '1',
112
+ 'Sec-Fetch-Dest': 'document',
113
+ 'Sec-Fetch-Mode': 'navigate',
114
+ 'Sec-Fetch-Site': 'none',
115
+ 'Sec-Fetch-User': '?1',
116
+ 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
117
+ 'sec-ch-ua-mobile': '?0',
118
+ 'sec-ch-ua-platform': '"Windows"',
119
+ 'Cache-Control': 'max-age=0',
120
+ 'Referer': 'https://kwik.cx/'
121
+ },
122
+ maxRedirects: 10,
123
+ validateStatus: () => true,
124
+ timeout: 30000
125
+ });
126
+
127
+ const response = await client.get(url);
128
+
129
+ if (response.status === 403) {
130
+ throw new Error('403 Forbidden - Access Denied');
131
+ }
132
+
133
+ const html = response.data;
134
+ const $ = cheerio.load(html);
135
+
136
+ // Check for iframe
137
+ const iframe = $('iframe.embed-responsive-item');
138
+ const iframeExists = iframe.length > 0;
139
+ const iframeSrc = iframe.attr('src') || null;
140
+
141
+ // Check for download section
142
+ const downloadSection = $('.download-form, .message.video-details, .download');
143
+ const downloadSectionExists = downloadSection.length > 0;
144
+
145
+ // Extract file details
146
+ const fileName = $('strong').first().text().trim() || null;
147
+ const fileSize = $('abbr[title*="Bytes"]').text().trim() || null;
148
+ const resolution = $('.column:contains("Resolution")').text().replace('Resolution:', '').trim() || null;
149
+
150
+ return {
151
+ success: true,
152
+ url: url,
153
+ iframeExists: iframeExists,
154
+ iframeSrc: iframeSrc,
155
+ downloadSectionExists: downloadSectionExists,
156
+ fileDetails: {
157
+ fileName: fileName,
158
+ fileSize: fileSize,
159
+ resolution: resolution
160
+ },
161
+ method: 'axios'
162
+ };
163
+
164
+ } catch (error) {
165
+ console.error('axios error:', error.message);
166
+ return {
167
+ success: false,
168
+ error: error.message,
169
+ method: 'axios'
170
+ };
171
+ }
172
+ }
173
+
174
+ // Main route with fallback mechanism
175
+ app.get('/extract', async (req, res) => {
176
+ const { url } = req.query;
177
+
178
+ if (!url) {
179
+ return res.status(400).json({
180
+ success: false,
181
+ error: 'Missing "url" query parameter'
182
+ });
183
+ }
184
+
185
+ if (!url.includes('kwik.cx') && !url.includes('kwik.si')) {
186
+ return res.status(400).json({
187
+ success: false,
188
+ error: 'Invalid URL - must be a kwik.cx or kwik.si URL'
189
+ });
190
+ }
191
+
192
+ console.log(`[REQUEST] Extracting data from: ${url}`);
193
+
194
+ // Try got-scraping first (most reliable)
195
+ let result = await extractWithGotScraping(url);
196
+
197
+ // If got-scraping fails, fallback to axios
198
+ if (!result.success) {
199
+ console.log('[FALLBACK] Trying axios method...');
200
+ result = await extractWithAxios(url);
201
+ }
202
+
203
+ if (result.success) {
204
+ console.log(`[SUCCESS] Iframe exists: ${result.iframeExists}`);
205
+ console.log(`[SUCCESS] Download section exists: ${result.downloadSectionExists}`);
206
+ } else {
207
+ console.log(`[FAILED] Error: ${result.error}`);
208
+ }
209
+
210
+ return res.json(result);
211
+ });
212
+
213
+ // Health check route
214
+ app.get('/health', (req, res) => {
215
+ res.json({ status: 'ok', timestamp: new Date().toISOString() });
216
+ });
217
+
218
+ // Root route
219
+ app.get('/', (req, res) => {
220
+ res.json({
221
+ service: 'Kwik Extractor API',
222
+ version: '1.0.0',
223
+ endpoints: {
224
+ extract: '/extract?url=<kwik_url>',
225
+ health: '/health'
226
+ },
227
+ example: '/extract?url=https://kwik.cx/f/0SoyAdDuRvy1'
228
+ });
229
+ });
230
+
231
+ app.listen(7860, () => {
232
+ console.log(`🚀 Server running on port ${PORT}`);
233
+ console.log(`📡 API endpoint: http://localhost:${PORT}/extract?url=<kwik_url>`);
234
+ });