@erfan_bahramali/tping 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +118 -0
  3. package/dist/crypto/aes-ctr.d.ts +18 -0
  4. package/dist/crypto/aes-ctr.d.ts.map +1 -0
  5. package/dist/crypto/aes-ctr.js +30 -0
  6. package/dist/crypto/aes-ctr.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +66 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/checker.d.ts +6 -0
  12. package/dist/lib/checker.d.ts.map +1 -0
  13. package/dist/lib/checker.js +72 -0
  14. package/dist/lib/checker.js.map +1 -0
  15. package/dist/lib/parser.d.ts +7 -0
  16. package/dist/lib/parser.d.ts.map +1 -0
  17. package/dist/lib/parser.js +96 -0
  18. package/dist/lib/parser.js.map +1 -0
  19. package/dist/lib/ping.d.ts +10 -0
  20. package/dist/lib/ping.d.ts.map +1 -0
  21. package/dist/lib/ping.js +59 -0
  22. package/dist/lib/ping.js.map +1 -0
  23. package/dist/mtproto/connection.d.ts +59 -0
  24. package/dist/mtproto/connection.d.ts.map +1 -0
  25. package/dist/mtproto/connection.js +198 -0
  26. package/dist/mtproto/connection.js.map +1 -0
  27. package/dist/mtproto/fake-tls.d.ts +56 -0
  28. package/dist/mtproto/fake-tls.d.ts.map +1 -0
  29. package/dist/mtproto/fake-tls.js +175 -0
  30. package/dist/mtproto/fake-tls.js.map +1 -0
  31. package/dist/mtproto/messages.d.ts +48 -0
  32. package/dist/mtproto/messages.d.ts.map +1 -0
  33. package/dist/mtproto/messages.js +104 -0
  34. package/dist/mtproto/messages.js.map +1 -0
  35. package/dist/mtproto/obfuscation.d.ts +26 -0
  36. package/dist/mtproto/obfuscation.d.ts.map +1 -0
  37. package/dist/mtproto/obfuscation.js +78 -0
  38. package/dist/mtproto/obfuscation.js.map +1 -0
  39. package/dist/mtproto/socks5.d.ts +36 -0
  40. package/dist/mtproto/socks5.d.ts.map +1 -0
  41. package/dist/mtproto/socks5.js +148 -0
  42. package/dist/mtproto/socks5.js.map +1 -0
  43. package/dist/types/index.d.ts +49 -0
  44. package/dist/types/index.d.ts.map +1 -0
  45. package/dist/types/index.js +2 -0
  46. package/dist/types/index.js.map +1 -0
  47. package/dist/utils/format.d.ts +22 -0
  48. package/dist/utils/format.d.ts.map +1 -0
  49. package/dist/utils/format.js +131 -0
  50. package/dist/utils/format.js.map +1 -0
  51. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Erfan Bahramali
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # 🏓 tping
2
+
3
+ **Ping for Telegram Proxies** - Test connectivity to Telegram Proxies, just like `ping` for IP addresses.
4
+
5
+ A simple and clean CLI tool to continuously ping Telegram proxies (MTProto and SOCKS5) and measure latency in real-time using official Telegram API.
6
+
7
+ ---
8
+
9
+ ## ✨ Features
10
+
11
+ - 🏓 **Continuous ping mode** - Like standard `ping` command
12
+ - 🔄 **Multiple proxies** - Ping simultaneously
13
+ - ⚙️ **Configurable** - Custom count and interval
14
+ - 📊 **Statistics** - min/avg/max latency, packet loss
15
+ - 🚀 **Simple & clean** - Easy to use
16
+
17
+ ---
18
+
19
+ ## 📦 Installation
20
+
21
+ ```bash
22
+ npm install -g @erfan_bahramali/tping
23
+ ```
24
+
25
+ Or use directly with npx:
26
+
27
+ ```bash
28
+ npx @erfan_bahramali/tping <proxy>
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 🚀 Usage
34
+
35
+ You can pass proxy as text or file path. For multiple proxies, separate by newlines (in text or file).
36
+
37
+ ```bash
38
+ # Single proxy
39
+ tping "https://t.me/proxy?server=proxy.example.com&port=443&secret=0123456789abcdef"
40
+
41
+ # Multiple proxies
42
+ tping "https://t.me/proxy?server=proxy1.com&port=443&secret=abc
43
+ https://t.me/socks?server=proxy2.com&port=1080"
44
+
45
+ # From file (single or multiple proxies)
46
+ tping proxies.txt
47
+
48
+ # Ping 5 times
49
+ tping -c 5 "https://t.me/socks?server=proxy.example.com&port=1080"
50
+
51
+ # Ping unlimited times with custom interval (500ms)
52
+ tping -i 500 "https://t.me/socks?server=proxy.example.com&port=1080"
53
+
54
+ # Ping 10 times with custom interval (500ms)
55
+ tping -c 10 -i 500 proxies.txt
56
+ ```
57
+
58
+ ---
59
+
60
+ ## ⚙️ Options
61
+
62
+ | Option | Description |
63
+ |--------|-------------|
64
+ | `-c, --count <n>` | Number of pings to send (default: unlimited) |
65
+ | `-i, --interval <ms>` | Interval between pings in milliseconds (default: 1000) |
66
+ | `-t, --timeout <ms>` | Timeout for each ping in milliseconds (default: 10000) |
67
+ | `-v, --version` | Show version number |
68
+ | `-h, --help` | Show help |
69
+
70
+ ---
71
+
72
+ ## 📊 Example Output
73
+
74
+ ```
75
+ 🏓 PING proxy.example.com:443 (MTProto)
76
+ Sending pings with 1000ms interval... (Press Ctrl+C to stop)
77
+
78
+ ✓ proxy.example.com:443 │ MTProto │ seq=1 │ 45ms
79
+ ✓ proxy.example.com:443 │ MTProto │ seq=2 │ 48ms
80
+ ✓ proxy.example.com:443 │ MTProto │ seq=3 │ 43ms
81
+ ^C
82
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
83
+ 📊 Statistics for proxy.example.com:443
84
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
85
+ Packets: 3 sent │ 3 received │ 0% loss
86
+ Latency: 43ms min │ 45ms avg │ 48ms max
87
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 🔍 How it Works
93
+
94
+ tping performs a **real MTProto handshake** through the proxy — the same first
95
+ step every official Telegram client does:
96
+
97
+ 1. **Transport obfuscation** — a 64-byte header is generated with AES-256-CTR
98
+ keys derived from the proxy secret (per the official
99
+ [MTProto transport obfuscation](https://core.telegram.org/mtproto/mtproto-transports#transport-obfuscation)).
100
+ 2. **Fake TLS** (secrets with `ee` prefix) — a TLS 1.3 ClientHello with a valid
101
+ HMAC digest is sent; the proxy's signed ServerHello is verified before any
102
+ data is trusted. Wrong secrets are detected immediately.
103
+ 3. **MTProto ping** — a `req_pq_multi` request is sent through the proxy to the
104
+ Telegram datacenter. The measured latency is the round trip of receiving a
105
+ valid `resPQ` reply with our echoed nonce. A proxy only passes if the
106
+ datacenter actually answers — dead or fake proxies are reported as failures,
107
+ never as successes.
108
+
109
+ SOCKS5 proxies are checked by negotiating a connection to a Telegram datacenter
110
+ through them.
111
+
112
+ ---
113
+
114
+ ## 📋 License
115
+
116
+ MIT © 2026 [ErfanBahramali](https://github.com/ErfanBahramali)
117
+
118
+ ---
@@ -0,0 +1,18 @@
1
+ /**
2
+ * AES-256-CTR cipher with continuous counter mode.
3
+ * Used for MTProto obfuscation layer encryption.
4
+ */
5
+ export declare class AESCTR {
6
+ private cipher;
7
+ /**
8
+ * @param key - 32 bytes encryption key
9
+ * @param iv - 16 bytes initialization vector (counter)
10
+ */
11
+ constructor(key: Buffer, iv: Buffer);
12
+ /**
13
+ * Encrypt/decrypt data (CTR mode is symmetric).
14
+ * Maintains internal counter state across multiple calls.
15
+ */
16
+ encrypt(data: Buffer): Buffer;
17
+ }
18
+ //# sourceMappingURL=aes-ctr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aes-ctr.d.ts","sourceRoot":"","sources":["../../src/crypto/aes-ctr.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAoC;IAElD;;;OAGG;gBACS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAYnC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAG9B"}
@@ -0,0 +1,30 @@
1
+ import { createCipheriv } from 'crypto';
2
+ /**
3
+ * AES-256-CTR cipher with continuous counter mode.
4
+ * Used for MTProto obfuscation layer encryption.
5
+ */
6
+ export class AESCTR {
7
+ cipher;
8
+ /**
9
+ * @param key - 32 bytes encryption key
10
+ * @param iv - 16 bytes initialization vector (counter)
11
+ */
12
+ constructor(key, iv) {
13
+ if (key.length !== 32) {
14
+ throw new Error('AES-256 key must be 32 bytes');
15
+ }
16
+ if (iv.length !== 16) {
17
+ throw new Error('IV must be 16 bytes');
18
+ }
19
+ // CTR mode doesn't distinguish between encrypt/decrypt
20
+ this.cipher = createCipheriv('aes-256-ctr', key, iv);
21
+ }
22
+ /**
23
+ * Encrypt/decrypt data (CTR mode is symmetric).
24
+ * Maintains internal counter state across multiple calls.
25
+ */
26
+ encrypt(data) {
27
+ return this.cipher.update(data);
28
+ }
29
+ }
30
+ //# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../src/crypto/aes-ctr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAExC;;;GAGG;AACH,MAAM,OAAO,MAAM;IACT,MAAM,CAAoC;IAElD;;;OAGG;IACH,YAAY,GAAW,EAAE,EAAU;QACjC,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,uDAAuD;QACvD,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ import chalk from 'chalk';
3
+ import { program } from 'commander';
4
+ import { parseProxies } from './lib/parser.js';
5
+ import { pingProxy } from './lib/ping.js';
6
+ program
7
+ .name('tping')
8
+ .description('Ping for Telegram Proxies')
9
+ .version('1.0.0', '-v, --version')
10
+ .argument('[proxy]', 'Proxy URL or file path (supports MTProto, SOCKS5)')
11
+ .option('-c, --count <n>', 'Number of pings to send (default: unlimited)', parseInt)
12
+ .option('-i, --interval <ms>', 'Interval between pings in milliseconds (default: 1000)', parseInt)
13
+ .option('-t, --timeout <ms>', 'Timeout for each ping in milliseconds (default: 10000)', parseInt)
14
+ .showHelpAfterError('(add --help for additional information)')
15
+ .addHelpText('after', `
16
+ Supported proxy formats:
17
+ MTProto: "https://t.me/proxy?server=...&port=...&secret=..."
18
+ MTProto: "tg://proxy?server=...&port=...&secret=..."
19
+ SOCKS5: "https://t.me/socks?server=...&port=...&user=...&pass=..."
20
+ SOCKS5: "tg://socks?server=...&port=...&user=...&pass=..."
21
+
22
+ Examples:
23
+ $ tping "https://t.me/proxy?server=proxy.example.com&port=443&secret=0123456789abcdef"
24
+ $ tping -c 5 "https://t.me/socks?server=proxy.example.com&port=1080"
25
+ $ tping -c 10 -i 500 "tg://socks?server=proxy.example.com&port=1080&user=admin&pass=secret"
26
+ $ tping proxies.txt
27
+ `)
28
+ .action(async (proxyInput, options) => {
29
+ if (!proxyInput) {
30
+ program.help();
31
+ }
32
+ // Parse proxies
33
+ const proxies = parseProxies(proxyInput);
34
+ if (proxies.length === 0) {
35
+ console.log(chalk.red('Error: Invalid proxy format'));
36
+ process.exit(1);
37
+ }
38
+ options.interval = options.interval || 1000;
39
+ options.timeout = options.timeout || 10000;
40
+ // Print header
41
+ console.log();
42
+ console.log(chalk.bold.cyan('🏓 TPing'));
43
+ console.log(chalk.gray('━'.repeat(50)));
44
+ console.log(chalk.cyan(`📡 Proxies: ${chalk.white(proxies.length)}`));
45
+ console.log(chalk.cyan(`🎯 Count: ${chalk.white(options.count || 'unlimited')}`));
46
+ console.log(chalk.cyan(`⏰ Interval: ${chalk.white(options.interval + 'ms')}`));
47
+ console.log(chalk.cyan(`⏳ Timeout: ${chalk.white(options.timeout + 'ms')}`));
48
+ console.log(chalk.gray('━'.repeat(50)));
49
+ console.log();
50
+ // Setup abort controller for Ctrl+C
51
+ const abortController = new AbortController();
52
+ let isAborting = false;
53
+ const handleAbort = async () => {
54
+ if (isAborting) {
55
+ return;
56
+ }
57
+ isAborting = true;
58
+ abortController.abort();
59
+ console.log(chalk.yellow('\n⏸️ Stopping... (Press Ctrl+C again to force quit)'));
60
+ };
61
+ process.on('SIGINT', handleAbort);
62
+ process.on('SIGTERM', handleAbort);
63
+ await pingProxy(proxies, options, abortController.signal);
64
+ process.exit(0);
65
+ }).parse();
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { TelegramProxy, CheckResult } from '../types/index.js';
2
+ /**
3
+ * Ping any proxy type.
4
+ */
5
+ export declare const checkProxy: (proxy: TelegramProxy, timeout?: number) => Promise<CheckResult>;
6
+ //# sourceMappingURL=checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../../src/lib/checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA0EpE;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,aAAa,EACpB,UAAS,MAAc,KACtB,OAAO,CAAC,WAAW,CAQrB,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { MTProtoConnection } from '../mtproto/connection.js';
2
+ import { SOCKS5Client } from '../mtproto/socks5.js';
3
+ /**
4
+ * Ping an MTProto proxy with a real MTProto handshake (req_pq -> ResPQ).
5
+ * Latency includes TCP + obfuscation (+ fake TLS) handshake + the MTProto round trip.
6
+ */
7
+ const pingMTProtoProxy = async (proxy, timeout) => {
8
+ if (proxy.type !== 'mtproto' || !proxy.secret) {
9
+ return { proxy, success: false, error: 'Invalid MTProto configuration' };
10
+ }
11
+ try {
12
+ const latency = await MTProtoConnection.pingOnce({
13
+ host: proxy.server,
14
+ port: proxy.port,
15
+ secret: proxy.secret,
16
+ timeout,
17
+ }, timeout);
18
+ return { proxy, success: true, latency };
19
+ }
20
+ catch (err) {
21
+ return {
22
+ proxy,
23
+ success: false,
24
+ error: err instanceof Error ? err.message : 'Connection failed',
25
+ };
26
+ }
27
+ };
28
+ /**
29
+ * Ping a SOCKS5 proxy by connecting through it to a Telegram datacenter.
30
+ */
31
+ const pingSOCKS5Proxy = async (proxy, timeout) => {
32
+ if (proxy.type !== 'socks5') {
33
+ return { proxy, success: false, error: 'Invalid SOCKS5 configuration' };
34
+ }
35
+ try {
36
+ const client = new SOCKS5Client({
37
+ host: proxy.server,
38
+ port: proxy.port,
39
+ username: proxy.username,
40
+ password: proxy.password,
41
+ timeout,
42
+ });
43
+ const start = Date.now();
44
+ await client.connect();
45
+ const ok = await client.testConnection();
46
+ client.close();
47
+ if (!ok) {
48
+ return { proxy, success: false, error: 'Connection test failed' };
49
+ }
50
+ return { proxy, success: true, latency: Date.now() - start };
51
+ }
52
+ catch (err) {
53
+ return {
54
+ proxy,
55
+ success: false,
56
+ error: err instanceof Error ? err.message : 'Connection failed',
57
+ };
58
+ }
59
+ };
60
+ /**
61
+ * Ping any proxy type.
62
+ */
63
+ export const checkProxy = async (proxy, timeout = 10000) => {
64
+ if (proxy.type === 'mtproto') {
65
+ return pingMTProtoProxy(proxy, timeout);
66
+ }
67
+ if (proxy.type === 'socks5') {
68
+ return pingSOCKS5Proxy(proxy, timeout);
69
+ }
70
+ return { proxy, success: false, error: 'Unsupported proxy type' };
71
+ };
72
+ //# sourceMappingURL=checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/lib/checker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { TelegramProxy } from '../types/index.js';
2
+ /**
3
+ * Parse proxies from input string or file.
4
+ * Automatically detects if input is a file path or proxy text.
5
+ */
6
+ export declare const parseProxies: (input: string) => readonly TelegramProxy[];
7
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/lib/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA4EvD;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,SAAS,aAAa,EA0BlE,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ /**
3
+ * Valid Telegram proxy URL prefixes
4
+ */
5
+ const TELEGRAM_PROXY_PREFIXES = [
6
+ 'https://t.me/proxy?',
7
+ 'https://telegram.me/proxy?',
8
+ 'https://telegram.dog/proxy?',
9
+ 'tg://proxy?',
10
+ ];
11
+ const TELEGRAM_SOCKS_PREFIXES = [
12
+ 'https://t.me/socks?',
13
+ 'https://telegram.me/socks?',
14
+ 'https://telegram.dog/socks?',
15
+ 'tg://socks?',
16
+ ];
17
+ /**
18
+ * Parse proxy string in Telegram URL format.
19
+ */
20
+ const parseProxyString = (line) => {
21
+ // Strip shell-escape backslashes before URL punctuation (e.g. t.me/proxy\?...\&...)
22
+ const trimmed = line
23
+ .replace(/\\([?=&#])/g, '$1')
24
+ .replace(/\+/g, '%2B')
25
+ .trim();
26
+ if (!trimmed || trimmed.startsWith('#')) {
27
+ return null;
28
+ }
29
+ try {
30
+ const url = new URL(trimmed);
31
+ // Check if it's MTProto proxy
32
+ if (TELEGRAM_PROXY_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
33
+ const server = url.searchParams.get('server');
34
+ const port = url.searchParams.get('port');
35
+ const secret = url.searchParams.get('secret');
36
+ if (server && port && secret) {
37
+ return {
38
+ type: 'mtproto',
39
+ server,
40
+ port: parseInt(port, 10),
41
+ secret,
42
+ };
43
+ }
44
+ }
45
+ // Check if it's SOCKS5 proxy
46
+ if (TELEGRAM_SOCKS_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
47
+ const server = url.searchParams.get('server');
48
+ const port = url.searchParams.get('port');
49
+ const user = url.searchParams.get('user');
50
+ const pass = url.searchParams.get('pass');
51
+ if (server && port) {
52
+ return {
53
+ type: 'socks5',
54
+ server,
55
+ port: parseInt(port, 10),
56
+ username: user || undefined,
57
+ password: pass || undefined,
58
+ };
59
+ }
60
+ }
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ return null;
66
+ };
67
+ /**
68
+ * Parse proxies from input string or file.
69
+ * Automatically detects if input is a file path or proxy text.
70
+ */
71
+ export const parseProxies = (input) => {
72
+ let content;
73
+ // Check if input is a file path
74
+ if (existsSync(input)) {
75
+ try {
76
+ content = readFileSync(input, 'utf-8');
77
+ }
78
+ catch {
79
+ content = input;
80
+ }
81
+ }
82
+ else {
83
+ content = input;
84
+ }
85
+ // Parse each line
86
+ const proxies = [];
87
+ const lines = content.split(/\r?\n/);
88
+ for (const line of lines) {
89
+ const proxy = parseProxyString(line);
90
+ if (proxy) {
91
+ proxies.push(proxy);
92
+ }
93
+ }
94
+ return proxies;
95
+ };
96
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/lib/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TelegramProxy, CheckResult } from '../types/index.js';
2
+ /**
3
+ * Ping proxies continuously.
4
+ */
5
+ export declare const pingProxy: (proxies: readonly TelegramProxy[], options: {
6
+ count?: number;
7
+ interval?: number;
8
+ timeout?: number;
9
+ }, signal?: AbortSignal) => Promise<readonly CheckResult[][]>;
10
+ //# sourceMappingURL=ping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ping.d.ts","sourceRoot":"","sources":["../../src/lib/ping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,eAAO,MAAM,SAAS,GAClB,SAAS,SAAS,aAAa,EAAE,EACjC,SAAS;IACL,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,EACD,SAAS,WAAW,KACrB,OAAO,CAAC,SAAS,WAAW,EAAE,EAAE,CAmElC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { checkProxy } from './checker.js';
2
+ import { printPingResult, printPingStatistics } from '../utils/format.js';
3
+ /**
4
+ * Ping proxies continuously.
5
+ */
6
+ export const pingProxy = async (proxies, options, signal) => {
7
+ const { count, interval = 1000, timeout = 10000 } = options;
8
+ let shouldStop = false;
9
+ // Handle abort signal
10
+ if (signal) {
11
+ signal.addEventListener('abort', () => {
12
+ shouldStop = true;
13
+ });
14
+ }
15
+ const sleep = (ms) => {
16
+ return new Promise((resolve) => setTimeout(resolve, ms));
17
+ };
18
+ // Initialize results array for each proxy
19
+ const allResults = proxies.map(() => []);
20
+ let sequence = 1;
21
+ // Main ping loop - all proxies tested together
22
+ while (!shouldStop) {
23
+ // Check if we've reached the count limit
24
+ if (count !== undefined && sequence > count) {
25
+ break;
26
+ }
27
+ // Show testing status for all proxies
28
+ for (let i = 0; i < proxies.length; i++) {
29
+ printPingResult(i, proxies, sequence, 'testing');
30
+ process.stdout.write('\n');
31
+ }
32
+ // Ping all proxies in parallel with real-time updates
33
+ await Promise.all(proxies.map(async (proxy, i) => {
34
+ const result = await checkProxy(proxy, timeout);
35
+ allResults[i].push(result);
36
+ // Move cursor to the correct line and update
37
+ const lineOffset = proxies.length - i;
38
+ process.stdout.write(`\x1b[${lineOffset}A`); // Move up
39
+ printPingResult(i, proxies, sequence, 'done', result);
40
+ process.stdout.write(`\x1b[${lineOffset}B`); // Move back down
41
+ }));
42
+ // Move to position after all lines
43
+ process.stdout.write('\n');
44
+ sequence++;
45
+ // Check if aborted or should stop
46
+ if (shouldStop) {
47
+ break;
48
+ }
49
+ // Wait for interval before next ping (unless it's the last one)
50
+ if (count === undefined || sequence <= count) {
51
+ if (!shouldStop) {
52
+ await sleep(interval);
53
+ }
54
+ }
55
+ }
56
+ printPingStatistics(proxies, allResults);
57
+ return allResults;
58
+ };
59
+ //# sourceMappingURL=ping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ping.js","sourceRoot":"","sources":["../../src/lib/ping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE1E;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC1B,OAAiC,EACjC,OAIC,EACD,MAAoB,EACa,EAAE;IACnC,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC5D,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,sBAAsB;IACtB,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YAClC,UAAU,GAAG,IAAI,CAAC;QACtB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE;QACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,0CAA0C;IAC1C,MAAM,UAAU,GAAoB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,+CAA+C;IAC/C,OAAO,CAAC,UAAU,EAAE,CAAC;QACjB,yCAAyC;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,GAAG,KAAK,EAAE,CAAC;YAC1C,MAAM;QACV,CAAC;QAED,sCAAsC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,sDAAsD;QACtD,MAAM,OAAO,CAAC,GAAG,CACb,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAChD,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAE3B,6CAA6C;YAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC,CAAC,UAAU;YACvD,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC,CAAC,iBAAiB;QAClE,CAAC,CAAC,CACL,CAAC;QAEF,mCAAmC;QACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3B,QAAQ,EAAE,CAAC;QAEX,kCAAkC;QAClC,IAAI,UAAU,EAAE,CAAC;YACb,MAAM;QACV,CAAC;QAED,gEAAgE;QAChE,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;gBACd,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;QACL,CAAC;IACL,CAAC;IAED,mBAAmB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEzC,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ export interface MTProtoConnectionOptions {
2
+ host: string;
3
+ port: number;
4
+ secret: string;
5
+ dcId?: number;
6
+ timeout?: number;
7
+ }
8
+ /**
9
+ * MTProto proxy connection supporting both simple (dd) and fake TLS (ee) modes.
10
+ *
11
+ * A ping is a real MTProto handshake: req_pq_multi is sent and a valid ResPQ
12
+ * must come back from the Telegram datacenter. In fake TLS mode the proxy's
13
+ * ServerHello is also verified against an HMAC of the proxy secret, so a wrong
14
+ * secret is detected immediately.
15
+ */
16
+ export declare class MTProtoConnection {
17
+ private options;
18
+ private socket;
19
+ private encryptor?;
20
+ private decryptor?;
21
+ private isFakeTLS;
22
+ private receiveBuffer;
23
+ private pending;
24
+ private phase;
25
+ private clientRandom?;
26
+ constructor(options: MTProtoConnectionOptions);
27
+ /**
28
+ * Connect to the MTProto proxy and perform the obfuscation (+ fake TLS) handshake.
29
+ * Resolves only after the proxy's ServerHello is HMAC-verified (fake TLS mode).
30
+ */
31
+ connect(): Promise<void>;
32
+ /**
33
+ * Send a real MTProto ping: req_pq_multi and wait for a valid ResPQ.
34
+ *
35
+ * @returns Round-trip time in ms
36
+ */
37
+ ping(timeout?: number): Promise<number>;
38
+ /**
39
+ * Connect + single real ping in one call. Closes the connection afterwards.
40
+ */
41
+ static pingOnce(options: MTProtoConnectionOptions, timeout?: number): Promise<number>;
42
+ /**
43
+ * Handle incoming socket data depending on the current phase.
44
+ */
45
+ private onData;
46
+ /**
47
+ * Wait until the FakeTLS ServerHello can be verified.
48
+ */
49
+ private awaitVerdict;
50
+ /**
51
+ * Reject any pending waiters (socket closed mid-handshake/ping).
52
+ */
53
+ private failPending;
54
+ /**
55
+ * Close the connection.
56
+ */
57
+ close(): void;
58
+ }
59
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/mtproto/connection.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAUhB,OAAO,CAAC,OAAO;IAT3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAmB;IACxC,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,YAAY,CAAC,CAAS;gBAEV,OAAO,EAAE,wBAAwB;IAOrD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6C9B;;;;OAIG;IACG,IAAI,CAAC,OAAO,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IA2C5C;;OAEG;WACU,QAAQ,CAAC,OAAO,EAAE,wBAAwB,EAAE,OAAO,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAU1F;;OAEG;IACH,OAAO,CAAC,MAAM;IA4Bd;;OAEG;YACW,YAAY;IAyB1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}