Spaces:
Paused
Paused
Update index.js
Browse files
index.js
CHANGED
|
@@ -1,82 +1,128 @@
|
|
| 1 |
-
import axios from 'axios';
|
| 2 |
-
import { request } from 'undici';
|
| 3 |
-
import dotenv from 'dotenv';
|
| 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 |
-
config.
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
console.
|
| 61 |
-
}
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
console.
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import axios from 'axios';
|
| 2 |
+
import { request } from 'undici';
|
| 3 |
+
import dotenv from 'dotenv';
|
| 4 |
+
import https from 'https';
|
| 5 |
+
import net from 'net';
|
| 6 |
+
|
| 7 |
+
dotenv.config();
|
| 8 |
+
|
| 9 |
+
// Simple DoH resolver using Cloudflare
|
| 10 |
+
async function resolveDNS(hostname) {
|
| 11 |
+
try {
|
| 12 |
+
const dohUrl = `https://cloudflare-dns.com/dns-query?name=${hostname}&type=A`;
|
| 13 |
+
const response = await request(dohUrl, {
|
| 14 |
+
method: 'GET',
|
| 15 |
+
headers: { 'Accept': 'application/dns-json' }
|
| 16 |
+
});
|
| 17 |
+
const data = await response.body.json();
|
| 18 |
+
if (data.Answer && data.Answer.length > 0) {
|
| 19 |
+
const aRecord = data.Answer.find(r => r.type === 1);
|
| 20 |
+
if (aRecord) return aRecord.data;
|
| 21 |
+
}
|
| 22 |
+
return hostname;
|
| 23 |
+
} catch (e) {
|
| 24 |
+
console.warn('DoH failed:', e.message || e);
|
| 25 |
+
return hostname;
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
const apiClient = axios.create({ timeout: 15000 });
|
| 30 |
+
const fallbackClient = axios.create({ timeout: 15000 });
|
| 31 |
+
|
| 32 |
+
apiClient.interceptors.request.use(async (config) => {
|
| 33 |
+
if (!config.url) return config;
|
| 34 |
+
try {
|
| 35 |
+
const url = new URL(config.url);
|
| 36 |
+
const hostname = url.hostname;
|
| 37 |
+
if (hostname && !hostname.match(/^(\d+\.){3}\d+$/) && hostname !== 'localhost') {
|
| 38 |
+
const ip = await resolveDNS(hostname);
|
| 39 |
+
if (ip !== hostname) {
|
| 40 |
+
url.hostname = ip;
|
| 41 |
+
config.url = url.toString();
|
| 42 |
+
config.headers = config.headers || {};
|
| 43 |
+
config.headers['Host'] = hostname;
|
| 44 |
+
console.log(`DoH: ${hostname} -> ${ip}`);
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
} catch (e) {
|
| 48 |
+
console.warn('DoH resolver error', e.message || e);
|
| 49 |
+
}
|
| 50 |
+
return config;
|
| 51 |
+
});
|
| 52 |
+
|
| 53 |
+
async function testTelegramApi(botToken) {
|
| 54 |
+
const url = `https://api.telegram.org/bot${botToken}/getMe`;
|
| 55 |
+
|
| 56 |
+
console.log('\n=== Testing apiClient (DoH) ===');
|
| 57 |
+
try {
|
| 58 |
+
const res = await apiClient.get(url, { timeout: 15000 });
|
| 59 |
+
console.log('apiClient response status:', res.status);
|
| 60 |
+
console.log('apiClient data:', res.data);
|
| 61 |
+
} catch (e) {
|
| 62 |
+
console.error('apiClient error:', e && e.response ? { status: e.response.status, data: e.response.data } : e.message || e);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
console.log('\n=== Testing fallbackClient (normal DNS) ===');
|
| 66 |
+
try {
|
| 67 |
+
const res2 = await fallbackClient.get(url, { timeout: 15000 });
|
| 68 |
+
console.log('fallbackClient response status:', res2.status);
|
| 69 |
+
console.log('fallbackClient data:', res2.data);
|
| 70 |
+
} catch (e) {
|
| 71 |
+
console.error('fallbackClient error:', e && e.response ? { status: e.response.status, data: e.response.data } : e.message || e);
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
// Additional diagnostics: resolve DNS, test TCP connect to IP, and HTTPS to IP with SNI
|
| 75 |
+
try {
|
| 76 |
+
const hostname = new URL(url).hostname;
|
| 77 |
+
console.log('\n=== Additional diagnostics ===');
|
| 78 |
+
const resolved = await resolveDNS(hostname);
|
| 79 |
+
console.log('Resolved hostname via DoH (or fallback):', resolved);
|
| 80 |
+
|
| 81 |
+
// If resolved is not the hostname, attempt TCP connect to port 443
|
| 82 |
+
if (resolved && resolved !== hostname) {
|
| 83 |
+
console.log(`Attempting TCP connect to ${resolved}:443`);
|
| 84 |
+
const tcpResult = await new Promise((resolve) => {
|
| 85 |
+
const socket = new net.Socket();
|
| 86 |
+
let settled = false;
|
| 87 |
+
socket.setTimeout(5000);
|
| 88 |
+
socket.on('connect', () => { if (!settled) { settled = true; socket.destroy(); resolve({ connected: true }); } });
|
| 89 |
+
socket.on('timeout', () => { if (!settled) { settled = true; socket.destroy(); resolve({ connected: false, error: 'timeout' }); } });
|
| 90 |
+
socket.on('error', (err) => { if (!settled) { settled = true; resolve({ connected: false, error: err.message }); } });
|
| 91 |
+
socket.connect(443, resolved);
|
| 92 |
+
});
|
| 93 |
+
|
| 94 |
+
console.log('TCP connect result:', tcpResult);
|
| 95 |
+
|
| 96 |
+
// Attempt HTTPS request directly to the IP while setting SNI (servername)
|
| 97 |
+
try {
|
| 98 |
+
console.log(`Attempting HTTPS request to https://${resolved} with SNI=${hostname} (rejectUnauthorized=false for test)`);
|
| 99 |
+
const httpsAgent = new https.Agent({ servername: hostname, rejectUnauthorized: false });
|
| 100 |
+
const ipUrl = url.replace(hostname, resolved);
|
| 101 |
+
const resp = await axios.get(ipUrl, {
|
| 102 |
+
timeout: 15000,
|
| 103 |
+
headers: { Host: hostname },
|
| 104 |
+
httpsAgent
|
| 105 |
+
});
|
| 106 |
+
console.log('HTTPS-over-IP response status:', resp.status);
|
| 107 |
+
console.log('HTTPS-over-IP data:', resp.data);
|
| 108 |
+
} catch (err) {
|
| 109 |
+
console.error('HTTPS-over-IP error:', err && err.response ? { status: err.response.status, data: err.response.data } : err.message || err);
|
| 110 |
+
}
|
| 111 |
+
} else {
|
| 112 |
+
console.log('No IP resolved (or hostname returned) — skipping TCP/HTTPS-over-IP tests');
|
| 113 |
+
}
|
| 114 |
+
} catch (diagErr) {
|
| 115 |
+
console.error('Diagnostics failed:', diagErr instanceof Error ? diagErr.message : diagErr);
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
async function main() {
|
| 120 |
+
const botToken = process.env.TEST_BOT_TOKEN;
|
| 121 |
+
if (!botToken) {
|
| 122 |
+
console.error('Set TEST_BOT_TOKEN in .env');
|
| 123 |
+
process.exit(1);
|
| 124 |
+
}
|
| 125 |
+
await testTelegramApi(botToken);
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
main().catch(e => { console.error('Fatal:', e); process.exit(1); });
|