hrmndev commited on
Commit
36421f3
·
verified ·
1 Parent(s): e9e18fe

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +205 -200
index.js CHANGED
@@ -1,213 +1,148 @@
1
  const express = require('express');
2
- const http2 = require('http2');
3
  const cheerio = require('cheerio');
4
 
5
  const app = express();
6
  const port = process.env.PORT || 3000;
7
 
8
- // HTTP/2 client for faster requests
9
- const client = http2.connect('https://www.trabis.gov.tr');
10
-
11
- // Global state
12
- const globals = {
13
- token: '',
14
- cookies: '',
15
- stats: {
16
- requestsCount: 0,
17
- totalTime: 0,
18
- domainsQueried: {},
19
- averageResponseTime: 0,
20
- lastTokenRefresh: null
21
- }
22
- };
23
 
24
- // Precompiled regex patterns
25
- const regexPatterns = {
26
- domainName: /Domain Name:\s*(.*)/,
27
- domainStatus: /Domain Status:\s*(.*)/,
28
- frozenStatus: /Frozen Status:\s*(.*)/,
29
- transferStatus: /Transfer Status:\s*(.*)/,
30
- registrant: /Registrant:\n([\s\S]*?)\n\n/,
31
- nicHandle: /NIC Handle\s*:\s*(.*)/,
32
- registrarName: /Organization Name\s*:\s*(.*)/,
33
- registrarAddress: /Address\s*:\s*(.*)/,
34
- registrarPhone: /Phone\s*:\s*(.*)/,
35
- registrarFax: /Fax\s*:\s*(.*)/,
36
- nameservers: /Domain Servers:\n([\s\S]*?)\n\n/,
37
- createdDate: /Created on.*:\s*(.*)/,
38
- expiresDate: /Expires on.*:\s*(.*)/,
39
- lastUpdateTime: /Last Update Time:\s*(.*)/,
40
- reassignmentDate: /(\d{2}\/\d{2}\/\d{4}) tarihinden itibaren/
41
- };
42
-
43
- // Fast data extraction
44
  const extractData = (data) => {
45
- const extract = (pattern) => pattern.exec(data)?.[1]?.trim();
46
-
47
- return {
48
- domainName: extract(regexPatterns.domainName),
49
- domainStatus: extract(regexPatterns.domainStatus),
50
- frozenStatus: extract(regexPatterns.frozenStatus),
51
- transferStatus: extract(regexPatterns.transferStatus),
52
- registrant: extract(regexPatterns.registrant)?.split('\n').map(line => line.trim()),
53
- registrar: {
54
- nicHandle: extract(regexPatterns.nicHandle),
55
- registrarName: extract(regexPatterns.registrarName),
56
- registrarAddress: extract(regexPatterns.registrarAddress),
57
- registrarPhone: extract(regexPatterns.registrarPhone),
58
- registrarFax: extract(regexPatterns.registrarFax)
59
- },
60
- nameservers: extract(regexPatterns.nameservers)?.split('\n'),
61
- createdDate: extract(regexPatterns.createdDate),
62
- expiresDate: extract(regexPatterns.expiresDate),
63
- lastUpdateTime: extract(regexPatterns.lastUpdateTime)
64
- };
65
- };
66
 
67
- // HTTP/2 request helper
68
- async function makeHttp2Request(path, method = 'GET', headers = {}, body = null) {
69
- return new Promise((resolve, reject) => {
70
- const req = client.request({
71
- ':path': path,
72
- ':method': method,
73
- ...headers
74
- });
75
 
76
- let data = '';
 
 
 
 
 
77
 
78
- req.on('response', (headers) => {
79
- if (headers[':status'] === 419) {
80
- reject({ statusCode: 419 });
81
- }
82
- });
83
 
84
- req.setEncoding('utf8');
85
- req.on('data', (chunk) => data += chunk);
86
- req.on('end', () => resolve(data));
87
- req.on('error', (err) => {
88
- console.error('HTTP/2 request error:', err);
89
- reject(err);
90
- });
91
 
92
- if (body) {
93
- req.write(body);
94
- }
95
- req.end();
96
- });
97
- }
98
 
99
- // Optimized token refresh
100
- async function refreshToken(retryCount = 0) {
101
- const maxRetries = 3;
102
- const baseDelay = 1000;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
 
104
  try {
105
- const html = await makeHttp2Request('/whois', 'GET', {
106
- 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',
107
- 'accept-language': 'en,tr;q=0.9',
108
- 'cache-control': 'no-cache',
109
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  });
111
 
112
- const $ = cheerio.load(html);
113
- globals.token = $('#search-domain-form > input[type=hidden]:nth-child(1)').val();
114
- globals.stats.lastTokenRefresh = Date.now();
115
 
116
- return true;
117
- } catch (error) {
118
- console.error(`Token refresh attempt ${retryCount + 1} failed:`, error.message);
 
119
 
120
- if (retryCount < maxRetries) {
121
- const delay = baseDelay * Math.pow(2, retryCount);
122
- await new Promise(resolve => setTimeout(resolve, delay));
123
- return refreshToken(retryCount + 1);
 
 
 
124
  }
125
- throw error;
126
- }
127
- }
128
-
129
- // Automatic token refresh
130
- setInterval(refreshToken, 3600000);
131
-
132
- // Fast WHOIS request processing
133
- async function processWhoisRequest(domain) {
134
- try {
135
- const formData = new URLSearchParams({ _token: globals.token, domain }).toString();
136
- const html = await makeHttp2Request('/search-domain', 'POST', {
137
- 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',
138
- 'content-type': 'application/x-www-form-urlencoded',
139
- 'origin': 'https://www.trabis.gov.tr',
140
- 'referer': 'https://www.trabis.gov.tr/'
141
- }, formData);
142
 
143
- const $ = cheerio.load(html);
144
- const text = $('body').text();
145
-
146
- if (text.includes("Hatalı")) {
147
- throw new Error('Invalid domain (Only TR Domains)');
148
- }
149
-
150
- const keywords = {
151
- Belgeli: text.includes('Belgeli'),
152
- Belgesiz: text.includes('Belgesiz'),
153
- kullanımdadır: text.includes('kullanımdadır'),
154
- başvurulmuş: text.includes('başvuruldu'),
155
- tahsis: text.includes('yeniden tahsis listesinde')
156
- };
157
-
158
- let result = { domain, status: keywords };
159
-
160
- if (keywords.tahsis) {
161
- const dateMatch = regexPatterns.reassignmentDate.exec(text);
162
- if (dateMatch) result.reassignmentDate = dateMatch[1];
163
- }
164
-
165
- if (keywords.kullanımdadır) {
166
- const whoisText = $('#main > div > div.Sub-page-content > div > div > section > div:nth-child(4) > pre').text();
167
- result.whoisData = extractData(whoisText);
168
- }
169
 
170
- return result;
171
  } catch (error) {
172
- if (error.statusCode === 419) {
173
- await refreshToken();
174
- return processWhoisRequest(domain);
175
- }
176
- throw error;
177
  }
178
  }
179
 
180
- // Performance tracking
 
181
  app.use((req, res, next) => {
182
  const startTime = Date.now();
183
- globals.stats.requestsCount++;
184
-
185
- res.on('finish', () => {
186
- const duration = Date.now() - startTime;
187
- globals.stats.totalTime += duration;
188
- globals.stats.averageResponseTime = globals.stats.totalTime / globals.stats.requestsCount;
189
-
190
- if (req.query.domain) {
191
- globals.stats.domainsQueried[req.query.domain] =
192
- (globals.stats.domainsQueried[req.query.domain] || 0) + 1;
193
- }
194
- });
195
-
196
  next();
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  });
198
 
199
- // Routes
200
  app.get('/stats', (req, res) => {
201
- res.json({
202
- requestsCount: globals.stats.requestsCount,
203
- averageResponseTime: parseFloat(globals.stats.averageResponseTime.toFixed(2)),
204
  uptime: parseFloat(process.uptime().toFixed(2)),
205
- lastTokenRefresh: globals.stats.lastTokenRefresh,
206
- domainsQueried: Object.entries(globals.stats.domainsQueried).map(([domain, count]) => ({
207
  domain,
208
- count
209
- }))
210
- });
 
 
211
  });
212
 
213
  app.get('/whois', async (req, res) => {
@@ -216,40 +151,110 @@ app.get('/whois', async (req, res) => {
216
  if (!domain) {
217
  return res.status(400).json({ error: 'Domain is required' });
218
  }
219
-
220
  try {
221
- const result = await processWhoisRequest(domain);
222
- res.json(result);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  } catch (error) {
224
- console.error('Error processing request:', error);
225
- res.status(error.statusCode || 500).json({
226
- error: error.message || 'An error occurred'
227
- });
228
  }
229
  });
230
 
 
231
  app.get('/', (req, res) => {
232
  res.status(200).json({ success: true });
233
- });
234
 
 
235
  app.get('*', (req, res) => {
236
- res.status(404).json({ error: 'Page not found' });
237
- });
238
 
239
- // Graceful shutdown
240
- process.on('SIGTERM', () => {
241
- console.log('Received SIGTERM. Performing graceful shutdown...');
242
- client.close();
243
- process.exit(0);
244
- });
245
-
246
- // Initialize server
247
  app.listen(port, async () => {
248
- try {
249
- await refreshToken();
250
- console.log(`Server running on port ${port}`);
251
- } catch (error) {
252
- console.error('Failed to start server:', error);
253
- process.exit(1);
254
- }
255
  });
 
1
  const express = require('express');
2
+ const axios = require('axios');
3
  const cheerio = require('cheerio');
4
 
5
  const app = express();
6
  const port = process.env.PORT || 3000;
7
 
8
+ // Global variables to store the token and cookies
9
+ let token = '';
10
+ let cookies = '';
11
+ let requestsCount = 0;
12
+ let totalTime = 0;
13
+ let domainsQueried = {};
14
+ let averageResponseTime = 0;
 
 
 
 
 
 
 
 
15
 
16
+ // Create a function to extract data using regex
17
+ // Create a function to extract all available data using regex
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  const extractData = (data) => {
19
+ const domainName = data.match(/Domain Name:\s*(.*)/)?.[1]?.trim();
20
+ const domainStatus = data.match(/Domain Status:\s*(.*)/)?.[1]?.trim();
21
+ const frozenStatus = data.match(/Frozen Status:\s*(.*)/)?.[1]?.trim();
22
+ const transferStatus = data.match(/Transfer Status:\s*(.*)/)?.[1]?.trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
+ // Registrant details (in this case they are hidden)
25
+ const registrant = data.match(/Registrant:\n([\s\S]*?)\n\n/)?.[1]?.trim().split('\n').map(line => line.trim());
 
 
 
 
 
 
26
 
27
+ // Registrar details
28
+ const nicHandle = data.match(/NIC Handle\s*:\s*(.*)/)?.[1]?.trim();
29
+ const registrarName = data.match(/Organization Name\s*:\s*(.*)/)?.[1]?.trim();
30
+ const registrarAddress = data.match(/Address\s*:\s*(.*)/)?.[1]?.trim();
31
+ const registrarPhone = data.match(/Phone\s*:\s*(.*)/)?.[1]?.trim();
32
+ const registrarFax = data.match(/Fax\s*:\s*(.*)/)?.[1]?.trim();
33
 
34
+ // Domain servers
35
+ const nameservers = data.match(/Domain Servers:\n([\s\S]*?)\n\n/)?.[1]?.trim().split('\n');
 
 
 
36
 
37
+ // Additional info (Created and Expiry dates)
38
+ const createdDate = data.match(/Created on.*:\s*(.*)/)?.[1]?.trim();
39
+ const expiresDate = data.match(/Expires on.*:\s*(.*)/)?.[1]?.trim();
 
 
 
 
40
 
41
+ // Last update time
42
+ const lastUpdateTime = data.match(/Last Update Time:\s*(.*)/)?.[1]?.trim();
 
 
 
 
43
 
44
+ return {
45
+ domainName,
46
+ domainStatus,
47
+ frozenStatus,
48
+ transferStatus,
49
+ registrant,
50
+ registrar: {
51
+ nicHandle,
52
+ registrarName,
53
+ registrarAddress,
54
+ registrarPhone,
55
+ registrarFax
56
+ },
57
+ nameservers,
58
+ createdDate,
59
+ expiresDate,
60
+ lastUpdateTime
61
+ };
62
+ };
63
 
64
+ async function sendRequestAndSetGlobals() {
65
  try {
66
+ const response = await axios({
67
+ method: 'get',
68
+ url: 'https://www.trabis.gov.tr/whois',
69
+ headers: {
70
+ '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',
71
+ 'accept-language': 'en,tr;q=0.9,en-GB;q=0.8,en-US;q=0.7',
72
+ 'cache-control': 'max-age=0',
73
+ 'dnt': '1',
74
+ 'priority': 'u=0, i',
75
+ 'referer': 'https://www.trabis.gov.tr/',
76
+ 'sec-ch-ua': '"Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
77
+ 'sec-ch-ua-mobile': '?0',
78
+ 'sec-ch-ua-platform': '"Windows"',
79
+ 'sec-fetch-dest': 'document',
80
+ 'sec-fetch-mode': 'navigate',
81
+ 'sec-fetch-site': 'same-origin',
82
+ 'sec-fetch-user': '?1',
83
+ 'upgrade-insecure-requests': '1',
84
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0'
85
+ }
86
  });
87
 
88
+ console.log('Response status:', response.status);
 
 
89
 
90
+ // Extract _token value and set it as a global variable
91
+ const $ = cheerio.load(response.data);
92
+ token = $('#search-domain-form > input[type=hidden]:nth-child(1)').val();
93
+ console.log('_token value set globally');
94
 
95
+ // Extract and format cookies, then set as a global variable
96
+ const rawCookies = response.headers['set-cookie'];
97
+ if (rawCookies) {
98
+ cookies = rawCookies.map(cookie => cookie.split(';')[0]).join('; ');
99
+ console.log('Cookies formatted and set globally');
100
+ } else {
101
+ console.log('No cookies found in the response');
102
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
+ // Log the global values
105
+ console.log('\nGlobal _token:', token);
106
+ console.log('Global cookies:', cookies);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
 
108
  } catch (error) {
109
+ console.error('Error:', error.message);
 
 
 
 
110
  }
111
  }
112
 
113
+ setInterval(sendRequestAndSetGlobals, 3600000);
114
+
115
  app.use((req, res, next) => {
116
  const startTime = Date.now();
117
+ requestsCount++;
 
 
 
 
 
 
 
 
 
 
 
 
118
  next();
119
+ const endTime = Date.now();
120
+ totalTime += endTime - startTime;
121
+ averageResponseTime = (totalTime / requestsCount).toFixed(2);
122
+
123
+ // track domains queried
124
+ if (req.query.domain) {
125
+ const domain = req.query.domain;
126
+ if (!domainsQueried[domain]) {
127
+ domainsQueried[domain] = 1;
128
+ } else {
129
+ domainsQueried[domain]++;
130
+ }
131
+ }
132
  });
133
 
 
134
  app.get('/stats', (req, res) => {
135
+ const stats = {
136
+ requestsCount,
137
+ averageResponseTime: parseFloat(averageResponseTime),
138
  uptime: parseFloat(process.uptime().toFixed(2)),
139
+ domainsQueried: Object.keys(domainsQueried).map((domain) => ({
 
140
  domain,
141
+ count: domainsQueried[domain],
142
+ })),
143
+ };
144
+
145
+ res.json(stats);
146
  });
147
 
148
  app.get('/whois', async (req, res) => {
 
151
  if (!domain) {
152
  return res.status(400).json({ error: 'Domain is required' });
153
  }
154
+
155
  try {
156
+ const response = await axios.post(
157
+ 'https://www.trabis.gov.tr/search-domain',
158
+ new URLSearchParams({
159
+ _token: token,
160
+ domain: domain
161
+ }),
162
+ {
163
+ headers: {
164
+ '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',
165
+ 'accept-language': 'en,tr;q=0.9,en-GB;q=0.8,en-US;q=0.7',
166
+ 'cache-control': 'max-age=0',
167
+ 'content-type': 'application/x-www-form-urlencoded',
168
+ 'cookie': cookies,
169
+ 'origin': 'https://www.trabis.gov.tr',
170
+ 'priority': 'u=0, i',
171
+ 'referer': 'https://www.trabis.gov.tr/',
172
+ 'sec-ch-ua': '"Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
173
+ 'sec-ch-ua-mobile': '?0',
174
+ 'sec-ch-ua-platform': '"Windows"',
175
+ 'sec-fetch-dest': 'document',
176
+ 'sec-fetch-mode': 'navigate',
177
+ 'sec-fetch-site': 'same-origin',
178
+ 'sec-fetch-user': '?1',
179
+ 'upgrade-insecure-requests': '1',
180
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0'
181
+ }
182
+ }
183
+ );
184
+
185
+ const html = response.data;
186
+ const $ = cheerio.load(html);
187
+
188
+ const keywords = {
189
+ Belgeli: false,
190
+ Belgesiz: false,
191
+ kullanımdadır: false,
192
+ başvurulmuş: false,
193
+ tahsis: false
194
+ };
195
+
196
+ // Search for the keywords
197
+ const text = $('body').text();
198
+ keywords.Belgeli = text.includes('Belgeli');
199
+ keywords.Belgesiz = text.includes('Belgesiz');
200
+ keywords.kullanımdadır = text.includes('kullanımdadır');
201
+ keywords.başvurulmuş = text.includes('başvuruldu');
202
+
203
+ // Check for reassignment text and extract date
204
+ let reassignmentDate = null;
205
+ if (text.includes('yeniden tahsis listesinde')) {
206
+ keywords.tahsis = true;
207
+ const dateMatch = text.match(/(\d{2}\/\d{2}\/\d{4}) tarihinden itibaren/);
208
+ if (dateMatch) {
209
+ reassignmentDate = dateMatch[1];
210
+ }
211
+ }
212
+
213
+ if (text.includes("Hatalı")) {
214
+ return res.status(400).json({ error: 'Invalid domain (Only TR Domains)' });
215
+ }
216
+
217
+ // if its "kullanımdadır", please get the html seleector "#main > div > div.Sub-page-content > div > div > section > div:nth-child(4) > pre" from the response and send it back to the user as "whois" data
218
+
219
+
220
+ // the selector is a "pre", get its text
221
+ let whoisData = null;
222
+ if (keywords.kullanımdadır) {
223
+ const selector = '#main > div > div.Sub-page-content > div > div > section > div:nth-child(4) > pre';
224
+ whoisData = $(selector).text();
225
+ whoisData = extractData(whoisData);
226
+ res.json({
227
+ domain,
228
+ status: keywords,
229
+ whoisData,
230
+ ...(reassignmentDate && { reassignmentDate })
231
+ });
232
+ } else {
233
+ res.json({
234
+ domain,
235
+ status: keywords,
236
+ ...(reassignmentDate && { reassignmentDate })
237
+ });
238
+ }
239
+
240
  } catch (error) {
241
+ await sendRequestAndSetGlobals()
242
+ console.error(error);
243
+ res.status(500).json({ error: 'An error occurred' });
 
244
  }
245
  });
246
 
247
+ // default router
248
  app.get('/', (req, res) => {
249
  res.status(200).json({ success: true });
250
+ })
251
 
252
+ //404 not found
253
  app.get('*', (req, res) => {
254
+ res.status(404).json({error: 'Page not found'});
255
+ })
256
 
 
 
 
 
 
 
 
 
257
  app.listen(port, async () => {
258
+ await sendRequestAndSetGlobals()
259
+ console.log(`Server running on port ${port}`);
 
 
 
 
 
260
  });