hrmndev commited on
Commit
bdecacc
·
verified ·
1 Parent(s): 71f2f61

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +178 -198
index.js CHANGED
@@ -5,256 +5,236 @@ const cheerio = require('cheerio');
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) => {
149
- const { domain } = req.query;
150
 
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
  });
 
5
  const app = express();
6
  const port = process.env.PORT || 3000;
7
 
8
+ // Global state with better structure
9
+ const globals = {
10
+ token: '',
11
+ cookies: '',
12
+ stats: {
13
+ requestsCount: 0,
14
+ totalTime: 0,
15
+ domainsQueried: {},
16
+ averageResponseTime: 0,
17
+ lastTokenRefresh: null
18
+ }
19
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ // Precompiled regex patterns for better performance
22
+ const regexPatterns = {
23
+ domainName: /Domain Name:\s*(.*)/,
24
+ domainStatus: /Domain Status:\s*(.*)/,
25
+ frozenStatus: /Frozen Status:\s*(.*)/,
26
+ transferStatus: /Transfer Status:\s*(.*)/,
27
+ registrant: /Registrant:\n([\s\S]*?)\n\n/,
28
+ nicHandle: /NIC Handle\s*:\s*(.*)/,
29
+ registrarName: /Organization Name\s*:\s*(.*)/,
30
+ registrarAddress: /Address\s*:\s*(.*)/,
31
+ registrarPhone: /Phone\s*:\s*(.*)/,
32
+ registrarFax: /Fax\s*:\s*(.*)/,
33
+ nameservers: /Domain Servers:\n([\s\S]*?)\n\n/,
34
+ createdDate: /Created on.*:\s*(.*)/,
35
+ expiresDate: /Expires on.*:\s*(.*)/,
36
+ lastUpdateTime: /Last Update Time:\s*(.*)/,
37
+ reassignmentDate: /(\d{2}\/\d{2}\/\d{4}) tarihinden itibaren/
38
+ };
39
 
40
+ // Optimized data extraction function
41
+ const extractData = (data) => {
42
+ const extract = (pattern) => pattern.exec(data)?.[1]?.trim();
43
+
44
  return {
45
+ domainName: extract(regexPatterns.domainName),
46
+ domainStatus: extract(regexPatterns.domainStatus),
47
+ frozenStatus: extract(regexPatterns.frozenStatus),
48
+ transferStatus: extract(regexPatterns.transferStatus),
49
+ registrant: extract(regexPatterns.registrant)?.split('\n').map(line => line.trim()),
50
+ registrar: {
51
+ nicHandle: extract(regexPatterns.nicHandle),
52
+ registrarName: extract(regexPatterns.registrarName),
53
+ registrarAddress: extract(regexPatterns.registrarAddress),
54
+ registrarPhone: extract(regexPatterns.registrarPhone),
55
+ registrarFax: extract(regexPatterns.registrarFax)
56
+ },
57
+ nameservers: extract(regexPatterns.nameservers)?.split('\n'),
58
+ createdDate: extract(regexPatterns.createdDate),
59
+ expiresDate: extract(regexPatterns.expiresDate),
60
+ lastUpdateTime: extract(regexPatterns.lastUpdateTime)
61
  };
62
  };
63
 
64
+ // Optimized token refresh with retries
65
+ async function refreshToken(retryCount = 0) {
66
+ const maxRetries = 3;
67
+ const baseDelay = 1000;
68
+
69
  try {
70
  const response = await axios({
71
  method: 'get',
72
  url: 'https://www.trabis.gov.tr/whois',
73
  headers: {
74
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',
75
+ 'accept-language': 'en,tr;q=0.9',
76
+ 'cache-control': 'no-cache',
77
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
78
+ },
79
+ timeout: 5000
 
 
 
 
 
 
 
 
 
 
80
  });
81
 
 
 
 
82
  const $ = cheerio.load(response.data);
83
+ globals.token = $('#search-domain-form > input[type=hidden]:nth-child(1)').val();
84
+ globals.cookies = response.headers['set-cookie']?.map(cookie => cookie.split(';')[0]).join('; ') || '';
85
+ globals.stats.lastTokenRefresh = Date.now();
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
+ return true;
88
  } catch (error) {
89
+ console.error(`Token refresh attempt ${retryCount + 1} failed:`, error.message);
 
 
 
 
90
 
91
+ if (retryCount < maxRetries) {
92
+ const delay = baseDelay * Math.pow(2, retryCount);
93
+ await new Promise(resolve => setTimeout(resolve, delay));
94
+ return refreshToken(retryCount + 1);
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
+ throw error;
97
  }
98
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
+ // Automatic token refresh every hour
101
+ setInterval(refreshToken, 3600000);
102
 
103
+ // Optimized WHOIS request processing
104
+ async function processWhoisRequest(domain) {
 
 
105
  try {
106
  const response = await axios.post(
107
  'https://www.trabis.gov.tr/search-domain',
108
+ new URLSearchParams({ _token: globals.token, domain }),
 
 
 
109
  {
110
  headers: {
111
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',
 
 
112
  'content-type': 'application/x-www-form-urlencoded',
113
+ 'cookie': globals.cookies,
114
  'origin': 'https://www.trabis.gov.tr',
 
115
  'referer': 'https://www.trabis.gov.tr/',
116
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
117
+ },
118
+ timeout: 10000,
119
+ validateStatus: status => status < 500 // Accept all status codes below 500
 
 
 
 
 
 
120
  }
121
  );
122
 
123
+ // Handle invalid token
124
+ if (response.status === 419) {
125
+ await refreshToken();
126
+ return processWhoisRequest(domain);
127
+ }
128
+
129
+ const $ = cheerio.load(response.data);
130
+ const text = $('body').text();
131
+
132
+ if (text.includes("Hatalı")) {
133
+ throw new Error('Invalid domain (Only TR Domains)');
134
+ }
135
 
136
  const keywords = {
137
+ Belgeli: text.includes('Belgeli'),
138
+ Belgesiz: text.includes('Belgesiz'),
139
+ kullanımdadır: text.includes('kullanımdadır'),
140
+ başvurulmuş: text.includes('başvuruldu'),
141
+ tahsis: text.includes('yeniden tahsis listesinde')
142
  };
143
 
144
+ let result = { domain, status: keywords };
 
 
 
 
 
145
 
146
+ if (keywords.tahsis) {
147
+ const dateMatch = regexPatterns.reassignmentDate.exec(text);
148
+ if (dateMatch) result.reassignmentDate = dateMatch[1];
 
 
 
 
 
149
  }
150
 
151
+ if (keywords.kullanımdadır) {
152
+ const whoisText = $('#main > div > div.Sub-page-content > div > div > section > div:nth-child(4) > pre').text();
153
+ result.whoisData = extractData(whoisText);
154
  }
155
 
156
+ return result;
157
+ } catch (error) {
158
+ if (error.response?.status === 419) {
159
+ await refreshToken();
160
+ return processWhoisRequest(domain);
161
+ }
162
+ throw error;
163
+ }
164
+ }
165
 
166
+ // Performance tracking middleware
167
+ app.use((req, res, next) => {
168
+ const startTime = Date.now();
169
+ globals.stats.requestsCount++;
170
+
171
+ res.on('finish', () => {
172
+ const duration = Date.now() - startTime;
173
+ globals.stats.totalTime += duration;
174
+ globals.stats.averageResponseTime = globals.stats.totalTime / globals.stats.requestsCount;
175
+
176
+ if (req.query.domain) {
177
+ globals.stats.domainsQueried[req.query.domain] =
178
+ (globals.stats.domainsQueried[req.query.domain] || 0) + 1;
 
 
 
 
 
179
  }
180
+ });
181
+
182
+ next();
183
+ });
184
 
185
+ // Routes
186
+ app.get('/stats', (req, res) => {
187
+ res.json({
188
+ requestsCount: globals.stats.requestsCount,
189
+ averageResponseTime: parseFloat(globals.stats.averageResponseTime.toFixed(2)),
190
+ uptime: parseFloat(process.uptime().toFixed(2)),
191
+ lastTokenRefresh: globals.stats.lastTokenRefresh,
192
+ domainsQueried: Object.entries(globals.stats.domainsQueried).map(([domain, count]) => ({
193
+ domain,
194
+ count
195
+ }))
196
+ });
197
+ });
198
+
199
+ app.get('/whois', async (req, res) => {
200
+ const { domain } = req.query;
201
+
202
+ if (!domain) {
203
+ return res.status(400).json({ error: 'Domain is required' });
204
+ }
205
+
206
+ try {
207
+ const result = await processWhoisRequest(domain);
208
+ res.json(result);
209
  } catch (error) {
210
+ console.error('Error processing request:', error);
211
+ res.status(error.response?.status || 500).json({
212
+ error: error.message || 'An error occurred'
213
+ });
214
  }
215
  });
216
 
 
217
  app.get('/', (req, res) => {
218
  res.status(200).json({ success: true });
219
+ });
220
 
 
221
  app.get('*', (req, res) => {
222
+ res.status(404).json({ error: 'Page not found' });
223
+ });
224
 
225
+ // Graceful shutdown
226
+ process.on('SIGTERM', () => {
227
+ console.log('Received SIGTERM. Performing graceful shutdown...');
228
+ process.exit(0);
229
+ });
230
+
231
+ // Initialize server
232
  app.listen(port, async () => {
233
+ try {
234
+ await refreshToken();
235
+ console.log(`Server running on port ${port}`);
236
+ } catch (error) {
237
+ console.error('Failed to start server:', error);
238
+ process.exit(1);
239
+ }
240
  });