@erfan_bahramali/tping 1.0.0 → 1.1.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 (98) hide show
  1. package/README.md +76 -55
  2. package/dist/crypto/x25519.d.ts +10 -0
  3. package/dist/crypto/x25519.d.ts.map +1 -0
  4. package/dist/crypto/x25519.js +51 -0
  5. package/dist/crypto/x25519.js.map +1 -0
  6. package/dist/index.js +82 -39
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/attempt.d.ts +31 -0
  9. package/dist/lib/attempt.d.ts.map +1 -0
  10. package/dist/lib/attempt.js +94 -0
  11. package/dist/lib/attempt.js.map +1 -0
  12. package/dist/lib/checker.d.ts +21 -3
  13. package/dist/lib/checker.d.ts.map +1 -1
  14. package/dist/lib/checker.js +133 -49
  15. package/dist/lib/checker.js.map +1 -1
  16. package/dist/lib/datacenters.d.ts +15 -0
  17. package/dist/lib/datacenters.d.ts.map +1 -0
  18. package/dist/lib/datacenters.js +20 -0
  19. package/dist/lib/datacenters.js.map +1 -0
  20. package/dist/lib/parser.d.ts +18 -3
  21. package/dist/lib/parser.d.ts.map +1 -1
  22. package/dist/lib/parser.js +174 -78
  23. package/dist/lib/parser.js.map +1 -1
  24. package/dist/lib/ping.d.ts +13 -6
  25. package/dist/lib/ping.d.ts.map +1 -1
  26. package/dist/lib/ping.js +44 -44
  27. package/dist/lib/ping.js.map +1 -1
  28. package/dist/mtproto/exchange.d.ts +10 -0
  29. package/dist/mtproto/exchange.d.ts.map +1 -0
  30. package/dist/mtproto/exchange.js +20 -0
  31. package/dist/mtproto/exchange.js.map +1 -0
  32. package/dist/mtproto/fake-tls.d.ts +36 -44
  33. package/dist/mtproto/fake-tls.d.ts.map +1 -1
  34. package/dist/mtproto/fake-tls.js +174 -148
  35. package/dist/mtproto/fake-tls.js.map +1 -1
  36. package/dist/mtproto/messages.d.ts +23 -36
  37. package/dist/mtproto/messages.d.ts.map +1 -1
  38. package/dist/mtproto/messages.js +64 -90
  39. package/dist/mtproto/messages.js.map +1 -1
  40. package/dist/mtproto/obfuscation.d.ts +23 -20
  41. package/dist/mtproto/obfuscation.d.ts.map +1 -1
  42. package/dist/mtproto/obfuscation.js +64 -64
  43. package/dist/mtproto/obfuscation.js.map +1 -1
  44. package/dist/mtproto/secret.d.ts +28 -0
  45. package/dist/mtproto/secret.d.ts.map +1 -0
  46. package/dist/mtproto/secret.js +68 -0
  47. package/dist/mtproto/secret.js.map +1 -0
  48. package/dist/mtproto/transport.d.ts +28 -0
  49. package/dist/mtproto/transport.d.ts.map +1 -0
  50. package/dist/mtproto/transport.js +78 -0
  51. package/dist/mtproto/transport.js.map +1 -0
  52. package/dist/net/http-client.d.ts +37 -0
  53. package/dist/net/http-client.d.ts.map +1 -0
  54. package/dist/net/http-client.js +93 -0
  55. package/dist/net/http-client.js.map +1 -0
  56. package/dist/net/http-proxy.d.ts +26 -0
  57. package/dist/net/http-proxy.d.ts.map +1 -0
  58. package/dist/net/http-proxy.js +71 -0
  59. package/dist/net/http-proxy.js.map +1 -0
  60. package/dist/net/socks5.d.ts +15 -0
  61. package/dist/net/socks5.d.ts.map +1 -0
  62. package/dist/net/socks5.js +112 -0
  63. package/dist/net/socks5.js.map +1 -0
  64. package/dist/net/stream.d.ts +54 -0
  65. package/dist/net/stream.d.ts.map +1 -0
  66. package/dist/net/stream.js +142 -0
  67. package/dist/net/stream.js.map +1 -0
  68. package/dist/net/websocket.d.ts +19 -0
  69. package/dist/net/websocket.d.ts.map +1 -0
  70. package/dist/net/websocket.js +123 -0
  71. package/dist/net/websocket.js.map +1 -0
  72. package/dist/types/index.d.ts +40 -17
  73. package/dist/types/index.d.ts.map +1 -1
  74. package/dist/utils/format.d.ts +7 -14
  75. package/dist/utils/format.d.ts.map +1 -1
  76. package/dist/utils/format.js +101 -87
  77. package/dist/utils/format.js.map +1 -1
  78. package/dist/webproxy/check.d.ts +15 -0
  79. package/dist/webproxy/check.d.ts.map +1 -0
  80. package/dist/webproxy/check.js +423 -0
  81. package/dist/webproxy/check.js.map +1 -0
  82. package/dist/webproxy/frames.d.ts +30 -0
  83. package/dist/webproxy/frames.d.ts.map +1 -0
  84. package/dist/webproxy/frames.js +59 -0
  85. package/dist/webproxy/frames.js.map +1 -0
  86. package/dist/webproxy/link.d.ts +27 -0
  87. package/dist/webproxy/link.d.ts.map +1 -0
  88. package/dist/webproxy/link.js +107 -0
  89. package/dist/webproxy/link.js.map +1 -0
  90. package/package.json +16 -11
  91. package/dist/mtproto/connection.d.ts +0 -59
  92. package/dist/mtproto/connection.d.ts.map +0 -1
  93. package/dist/mtproto/connection.js +0 -198
  94. package/dist/mtproto/connection.js.map +0 -1
  95. package/dist/mtproto/socks5.d.ts +0 -36
  96. package/dist/mtproto/socks5.d.ts.map +0 -1
  97. package/dist/mtproto/socks5.js +0 -148
  98. package/dist/mtproto/socks5.js.map +0 -1
@@ -1,72 +1,156 @@
1
- import { MTProtoConnection } from '../mtproto/connection.js';
2
- import { SOCKS5Client } from '../mtproto/socks5.js';
1
+ import { AbortedError, Attempt, STAGE_CONNECTING, STAGE_WAITING, describeError } from './attempt.js';
2
+ import { checkWebProxy } from '../webproxy/check.js';
3
+ import { socks5Connect } from '../net/socks5.js';
4
+ import { HttpProxyError, httpConnect, httpTransportRequest } from '../net/http-proxy.js';
5
+ import { parseSecret } from '../mtproto/secret.js';
6
+ import { fakeTlsHandshake } from '../mtproto/fake-tls.js';
7
+ import { createObfuscation, ObfuscatedPipe } from '../mtproto/obfuscation.js';
8
+ import { buildReqPqMulti, parseResPQ } from '../mtproto/messages.js';
9
+ import { exchangeReqPq, InvalidResponseError } from '../mtproto/exchange.js';
10
+ import { DEFAULT_DC, resolveDatacenter } from './datacenters.js';
3
11
  /**
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.
12
+ * Run `body` on a fresh connection to the proxy and measure the phases.
13
+ * `body` calls `handshakeDone()` when the proxy-level negotiation is finished.
6
14
  */
7
- const pingMTProtoProxy = async (proxy, timeout) => {
8
- if (proxy.type !== 'mtproto' || !proxy.secret) {
9
- return { proxy, success: false, error: 'Invalid MTProto configuration' };
10
- }
15
+ const measure = async (proxy, deadline, options, body) => {
16
+ const attempt = new Attempt(deadline, options.signal);
11
17
  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 };
18
+ const start = Date.now();
19
+ await attempt.stream.connect(proxy.server, proxy.port);
20
+ const connected = Date.now();
21
+ let negotiated = connected;
22
+ await body(attempt, () => {
23
+ negotiated = Date.now();
24
+ });
25
+ const end = Date.now();
26
+ return { timings: { connect: connected - start, handshake: negotiated - connected, rtt: end - negotiated } };
19
27
  }
20
28
  catch (err) {
21
- return {
22
- proxy,
23
- success: false,
24
- error: err instanceof Error ? err.message : 'Connection failed',
25
- };
29
+ throw Object.assign(err instanceof Error ? err : new Error(String(err)), { stage: attempt.stage });
26
30
  }
31
+ finally {
32
+ attempt.close();
33
+ }
34
+ };
35
+ const checkMTProto = (proxy, dc, deadline, options) => {
36
+ const secret = parseSecret(proxy.secret);
37
+ const mode = secret.kind === 'simple' ? 'intermediate' : 'padded';
38
+ return measure(proxy, deadline, options, async (attempt, handshakeDone) => {
39
+ let pipe = attempt.stream;
40
+ if (secret.kind === 'faketls') {
41
+ attempt.stage = 'fake-TLS handshake';
42
+ pipe = await fakeTlsHandshake(attempt.stream, secret.key, secret.domain ?? '');
43
+ }
44
+ handshakeDone();
45
+ attempt.stage = STAGE_WAITING;
46
+ await exchangeReqPq(new ObfuscatedPipe(pipe, createObfuscation(dc, mode, secret.key)), mode);
47
+ });
27
48
  };
49
+ const dcAddress = (dc, transport, options) => options.resolveDc?.(dc, transport) ?? resolveDatacenter(dc, options.ipv6 ?? false, transport);
28
50
  /**
29
- * Ping a SOCKS5 proxy by connecting through it to a Telegram datacenter.
51
+ * Direct (unsecured) obfuscated connection to the DC, as used through SOCKS5/HTTP proxies.
30
52
  */
31
- const pingSOCKS5Proxy = async (proxy, timeout) => {
32
- if (proxy.type !== 'socks5') {
33
- return { proxy, success: false, error: 'Invalid SOCKS5 configuration' };
34
- }
53
+ const exchangeDirect = (pipe, dc) => exchangeReqPq(new ObfuscatedPipe(pipe, createObfuscation(dc, 'abridged')), 'abridged');
54
+ const checkSocks5 = (proxy, dc, deadline, options) => measure(proxy, deadline, options, async (attempt, handshakeDone) => {
55
+ const target = dcAddress(dc, 'tcp', options);
56
+ await socks5Connect(attempt.stream, target.host, target.port, proxy, (stage) => {
57
+ attempt.stage = stage;
58
+ });
59
+ handshakeDone();
60
+ attempt.stage = STAGE_WAITING;
61
+ await exchangeDirect(attempt.stream, dc);
62
+ });
63
+ const checkHttp = async (proxy, dc, deadline, options) => {
35
64
  try {
36
- const client = new SOCKS5Client({
37
- host: proxy.server,
38
- port: proxy.port,
39
- username: proxy.username,
40
- password: proxy.password,
41
- timeout,
65
+ return await measure(proxy, deadline, options, async (attempt, handshakeDone) => {
66
+ const target = dcAddress(dc, 'tcp', options);
67
+ attempt.stage = 'HTTP CONNECT';
68
+ await httpConnect(attempt.stream, target.host, target.port, proxy);
69
+ handshakeDone();
70
+ attempt.stage = STAGE_WAITING;
71
+ await exchangeDirect(attempt.stream, dc);
42
72
  });
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' };
73
+ }
74
+ catch (err) {
75
+ // Like Telegram Desktop, fall back to the HTTP transport when the proxy refuses CONNECT.
76
+ if (!(err instanceof HttpProxyError) || err.status === undefined || err.status === 407) {
77
+ throw err;
78
+ }
79
+ const measured = await measure(proxy, deadline, options, async (attempt, handshakeDone) => {
80
+ const target = dcAddress(dc, 'http', options);
81
+ handshakeDone();
82
+ attempt.stage = `${STAGE_WAITING} (HTTP transport)`;
83
+ const { message, nonce } = buildReqPqMulti();
84
+ const reply = parseResPQ(await httpTransportRequest(attempt.stream, target.host, target.port, proxy, message));
85
+ if (!reply || !reply.nonce.equals(nonce)) {
86
+ throw new InvalidResponseError('Invalid reply from Telegram over HTTP transport');
87
+ }
88
+ });
89
+ return { ...measured, via: 'http-transport' };
90
+ }
91
+ };
92
+ const checkDc = async (proxy, dc, options) => {
93
+ const deadline = Date.now() + options.timeout;
94
+ try {
95
+ let measured;
96
+ switch (proxy.type) {
97
+ case 'mtproto':
98
+ measured = await checkMTProto(proxy, dc, deadline, options);
99
+ break;
100
+ case 'socks5':
101
+ measured = await checkSocks5(proxy, dc, deadline, options);
102
+ break;
103
+ case 'http':
104
+ measured = await checkHttp(proxy, dc, deadline, options);
105
+ break;
106
+ default:
107
+ return { dc, success: false, error: 'Unsupported proxy type' };
49
108
  }
50
- return { proxy, success: true, latency: Date.now() - start };
109
+ const { connect, handshake, rtt } = measured.timings;
110
+ return { dc, success: true, latency: connect + handshake + rtt, timings: measured.timings, via: measured.via };
51
111
  }
52
112
  catch (err) {
53
- return {
54
- proxy,
55
- success: false,
56
- error: err instanceof Error ? err.message : 'Connection failed',
57
- };
113
+ if (err instanceof AbortedError) {
114
+ throw err;
115
+ }
116
+ const stage = err.stage ?? STAGE_CONNECTING;
117
+ return { dc, success: false, error: describeError(err, stage) };
58
118
  }
59
119
  };
60
120
  /**
61
- * Ping any proxy type.
121
+ * Check one proxy the way the official clients use it: open a real connection,
122
+ * do the proxy handshake, and get a resPQ back from each requested Telegram DC.
62
123
  */
63
- export const checkProxy = async (proxy, timeout = 10000) => {
124
+ export const checkProxy = async (proxy, options) => {
125
+ const dcs = options.dcs?.length ? options.dcs : [DEFAULT_DC];
64
126
  if (proxy.type === 'mtproto') {
65
- return pingMTProtoProxy(proxy, timeout);
127
+ try {
128
+ parseSecret(proxy.secret);
129
+ }
130
+ catch (err) {
131
+ return { proxy, success: false, dcs: [], error: err.message };
132
+ }
133
+ }
134
+ let results;
135
+ try {
136
+ results = proxy.type === 'web'
137
+ ? await checkWebProxy(proxy, dcs, options)
138
+ : await Promise.all(dcs.map((dc) => checkDc(proxy, dc, options)));
66
139
  }
67
- if (proxy.type === 'socks5') {
68
- return pingSOCKS5Proxy(proxy, timeout);
140
+ catch (err) {
141
+ if (err instanceof AbortedError) {
142
+ return { proxy, success: false, dcs: [], error: 'Aborted', aborted: true };
143
+ }
144
+ throw err;
69
145
  }
70
- return { proxy, success: false, error: 'Unsupported proxy type' };
146
+ const success = results.every((r) => r.success);
147
+ const failed = results.find((r) => !r.success);
148
+ return {
149
+ proxy,
150
+ success,
151
+ latency: success ? Math.max(...results.map((r) => r.latency ?? 0)) : undefined,
152
+ dcs: results,
153
+ error: failed?.error,
154
+ };
71
155
  };
72
156
  //# sourceMappingURL=checker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/lib/checker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/lib/checker.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACrG,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAkB,MAAM,kBAAkB,CAAC;AAoBjF;;;GAGG;AACH,MAAM,OAAO,GAAG,KAAK,EACnB,KAAoB,EACpB,QAAgB,EAChB,OAAqB,EACrB,IAAoE,EACjD,EAAE;IACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,UAAU,GAAG,SAAS,CAAC;QAC3B,MAAM,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,UAAU,EAAE,EAAE,CAAC;IAC/G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACrG,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAE,EAAU,EAAE,QAAgB,EAAE,OAAqB,EAAqB,EAAE;IACnH,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAkB,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEjF,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;QACxE,IAAI,IAAI,GAAS,OAAO,CAAC,MAAM,CAAC;QAChC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,GAAG,oBAAoB,CAAC;YACrC,IAAI,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,aAAa,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC;QAC9B,MAAM,aAAa,CAAC,IAAI,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,SAAyB,EAAE,OAAqB,EAAa,EAAE,CAC5F,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,iBAAiB,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC;AAEhG;;GAEG;AACH,MAAM,cAAc,GAAG,CAAC,IAAU,EAAE,EAAU,EAAiB,EAAE,CAC/D,aAAa,CAAC,IAAI,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAEzF,MAAM,WAAW,GAAG,CAAC,KAAkB,EAAE,EAAU,EAAE,QAAgB,EAAE,OAAqB,EAAqB,EAAE,CACjH,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;IACjE,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;QAC7E,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACxB,CAAC,CAAC,CAAC;IACH,aAAa,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC;IAC9B,MAAM,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEL,MAAM,SAAS,GAAG,KAAK,EAAE,KAAgB,EAAE,EAAU,EAAE,QAAgB,EAAE,OAAqB,EAAqB,EAAE;IACnH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;YAC9E,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC;YAC/B,MAAM,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACnE,aAAa,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC;YAC9B,MAAM,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,yFAAyF;QACzF,IAAI,CAAC,CAAC,GAAG,YAAY,cAAc,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvF,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;YACxF,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9C,aAAa,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,GAAG,GAAG,aAAa,mBAAmB,CAAC;YACpD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/G,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,oBAAoB,CAAC,iDAAiD,CAAC,CAAC;YACpF,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;IAChD,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,KAAK,EAAE,KAAoB,EAAE,EAAU,EAAE,OAAqB,EAAqB,EAAE;IACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAC9C,IAAI,CAAC;QACH,IAAI,QAAkB,CAAC;QACvB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS;gBACZ,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5D,MAAM;YACR,KAAK,QAAQ;gBACX,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC3D,MAAM;YACR,KAAK,MAAM;gBACT,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACzD,MAAM;YACR;gBACE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;QACnE,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC;IACjH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,YAAY,EAAE,CAAC;YAChC,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,GAAI,GAA0B,CAAC,KAAK,IAAI,gBAAgB,CAAC;QACpE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;IAClE,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,KAAoB,EAAE,OAAqB,EAAwB,EAAE;IACpG,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAE7D,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,IAAI,OAA4B,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK;YAC5B,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC;YAC1C,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,YAAY,EAAE,CAAC;YAChC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7E,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO;QACL,KAAK;QACL,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAC9E,GAAG,EAAE,OAAO;QACZ,KAAK,EAAE,MAAM,EAAE,KAAK;KACrB,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Production Telegram datacenter addresses (same defaults as the official clients).
3
+ * Only needed for SOCKS5/HTTP proxies; MTProto proxies pick the DC from the DC id.
4
+ */
5
+ export interface DcAddress {
6
+ readonly host: string;
7
+ readonly port: number;
8
+ }
9
+ export declare const DC_IDS: readonly number[];
10
+ export declare const DEFAULT_DC = 2;
11
+ /**
12
+ * @param transport - 'tcp' uses port 443, 'http' (HTTP transport) uses port 80
13
+ */
14
+ export declare const resolveDatacenter: (dcId: number, ipv6: boolean, transport: "tcp" | "http") => DcAddress;
15
+ //# sourceMappingURL=datacenters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datacenters.d.ts","sourceRoot":"","sources":["../../src/lib/datacenters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAUD,eAAO,MAAM,MAAM,EAAE,SAAS,MAAM,EAAoB,CAAC;AACzD,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,EAAE,WAAW,KAAK,GAAG,MAAM,KAAG,SAM1F,CAAC"}
@@ -0,0 +1,20 @@
1
+ const DATACENTERS = {
2
+ 1: { ipv4: '149.154.175.50', ipv6: '2001:b28:f23d:f001::a' },
3
+ 2: { ipv4: '149.154.167.51', ipv6: '2001:67c:4e8:f002::a' },
4
+ 3: { ipv4: '149.154.175.100', ipv6: '2001:b28:f23d:f003::a' },
5
+ 4: { ipv4: '149.154.167.91', ipv6: '2001:67c:4e8:f004::a' },
6
+ 5: { ipv4: '149.154.171.5', ipv6: '2001:b28:f23f:f005::a' },
7
+ };
8
+ export const DC_IDS = [1, 2, 3, 4, 5];
9
+ export const DEFAULT_DC = 2;
10
+ /**
11
+ * @param transport - 'tcp' uses port 443, 'http' (HTTP transport) uses port 80
12
+ */
13
+ export const resolveDatacenter = (dcId, ipv6, transport) => {
14
+ const dc = DATACENTERS[Math.abs(dcId)];
15
+ if (!dc) {
16
+ throw new Error(`Unknown DC ${dcId}`);
17
+ }
18
+ return { host: ipv6 ? dc.ipv6 : dc.ipv4, port: transport === 'http' ? 80 : 443 };
19
+ };
20
+ //# sourceMappingURL=datacenters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datacenters.js","sourceRoot":"","sources":["../../src/lib/datacenters.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,GAA+E;IAC9F,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,uBAAuB,EAAE;IAC5D,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,sBAAsB,EAAE;IAC3D,CAAC,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,uBAAuB,EAAE;IAC7D,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,sBAAsB,EAAE;IAC3D,CAAC,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,uBAAuB,EAAE;CAC5D,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAsB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,IAAa,EAAE,SAAyB,EAAa,EAAE;IACrG,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACnF,CAAC,CAAC"}
@@ -1,7 +1,22 @@
1
1
  import type { TelegramProxy } from '../types/index.js';
2
+ export interface ParseIssue {
3
+ readonly input: string;
4
+ readonly reason: string;
5
+ }
6
+ export interface ParseResult {
7
+ readonly proxies: readonly TelegramProxy[];
8
+ readonly issues: readonly ParseIssue[];
9
+ }
10
+ type Outcome = {
11
+ readonly proxy: TelegramProxy;
12
+ } | {
13
+ readonly reason: string;
14
+ };
15
+ export declare const parseProxyString: (token: string) => Outcome;
2
16
  /**
3
- * Parse proxies from input string or file.
4
- * Automatically detects if input is a file path or proxy text.
17
+ * Parse proxies from a file path, "-" (stdin), or proxy text.
18
+ * Proxies may be separated by newlines or whitespace; lines starting with "#" are comments.
5
19
  */
6
- export declare const parseProxies: (input: string) => readonly TelegramProxy[];
20
+ export declare const parseProxies: (input: string) => ParseResult;
21
+ export {};
7
22
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/lib/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAsBvD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CACxC;AAED,KAAK,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAsH/E,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,OA2BhD,CAAC;AAgBF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,WAuB5C,CAAC"}
@@ -1,96 +1,192 @@
1
- import { readFileSync, existsSync } from 'fs';
1
+ import { readFileSync, statSync } from 'fs';
2
+ import { decodeWebSecret, parseWebProxyServer } from '../webproxy/link.js';
2
3
  /**
3
- * Valid Telegram proxy URL prefixes
4
+ * Supported inputs:
5
+ * https://t.me/proxy?server=..&port=..&secret=.. (also telegram.me, telegram.dog, www., http://, no scheme)
6
+ * tg://proxy?server=..&port=..&secret=.. (also tg:proxy)
7
+ * https://t.me/socks?server=..&port=..&user=..&pass=.. / tg://socks?...
8
+ * tg://webproxy?server=host[/path]&secret=.. / https://t.me/webproxy?... (WEB proxy, port 443)
9
+ * socks5://user:pass@host:port (also socks://, socks5h://)
10
+ * http://user:pass@host:port (HTTP proxy, Telegram Desktop)
4
11
  */
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;
12
+ const TELEGRAM_HOSTS = new Set([
13
+ 't.me',
14
+ 'telegram.me',
15
+ 'telegram.dog',
16
+ 'www.t.me',
17
+ 'www.telegram.me',
18
+ 'www.telegram.dog',
19
+ ]);
20
+ const normalize = (token) => {
21
+ // Strip shell-escape backslashes before URL punctuation (e.g. t.me/proxy\?...\&...).
22
+ let value = token.replace(/\\([?=&#])/g, '$1').trim();
23
+ if (/^tg:(?!\/\/)/i.test(value)) {
24
+ value = `tg://${value.slice(3)}`;
25
+ }
26
+ if (/^(www\.)?(t\.me|telegram\.me|telegram\.dog)\//i.test(value)) {
27
+ value = `https://${value}`;
28
+ }
29
+ return value;
30
+ };
31
+ const parsePort = (value, fallback) => {
32
+ if (!value) {
33
+ return fallback ?? 'port is missing';
34
+ }
35
+ if (!/^\d+$/.test(value)) {
36
+ return `invalid port "${value}"`;
37
+ }
38
+ const port = Number(value);
39
+ return port >= 1 && port <= 65535 ? port : `port ${port} is out of range`;
40
+ };
41
+ const cleanServer = (value) => (value ?? '').trim().replace(/^\[(.*)\]$/, '$1');
42
+ const decodeUserInfo = (value) => {
43
+ if (!value) {
44
+ return undefined;
28
45
  }
29
46
  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
- }
47
+ return decodeURIComponent(value);
48
+ }
49
+ catch {
50
+ return value;
51
+ }
52
+ };
53
+ const fromWebQuery = (params) => {
54
+ const server = (params.get('server') ?? params.get('host') ?? '').trim();
55
+ if (!server) {
56
+ return { reason: 'server is missing' };
57
+ }
58
+ const address = parseWebProxyServer(server);
59
+ if (typeof address === 'string') {
60
+ return { reason: address };
61
+ }
62
+ const secretText = params.get('secret')?.trim();
63
+ if (!secretText) {
64
+ return { reason: 'secret is missing' };
65
+ }
66
+ const secret = decodeWebSecret(secretText, address.basePath !== '');
67
+ if (typeof secret === 'string') {
68
+ return { reason: secret };
69
+ }
70
+ return {
71
+ proxy: { type: 'web', server: address.host, port: 443, basePath: address.basePath, secret: secret.toString('hex') },
72
+ };
73
+ };
74
+ const fromQuery = (kind, params) => {
75
+ if (kind === 'webproxy') {
76
+ return fromWebQuery(params);
77
+ }
78
+ const server = cleanServer(params.get('server'));
79
+ if (!server) {
80
+ return { reason: 'server is missing' };
81
+ }
82
+ const port = parsePort(params.get('port')?.trim());
83
+ if (typeof port === 'string') {
84
+ return { reason: port };
85
+ }
86
+ if (kind === 'proxy') {
87
+ const secret = params.get('secret')?.trim();
88
+ if (!secret) {
89
+ return { reason: 'secret is missing' };
44
90
  }
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
- }
91
+ return { proxy: { type: 'mtproto', server, port, secret } };
92
+ }
93
+ if (kind === 'socks') {
94
+ return {
95
+ proxy: {
96
+ type: 'socks5',
97
+ server,
98
+ port,
99
+ username: params.get('user') || undefined,
100
+ password: params.get('pass') || undefined,
101
+ },
102
+ };
103
+ }
104
+ return { reason: `unknown link type "${kind}"` };
105
+ };
106
+ const fromAuthority = (type, url, defaultPort) => {
107
+ const server = cleanServer(url.hostname);
108
+ if (!server) {
109
+ return { reason: 'server is missing' };
110
+ }
111
+ const port = parsePort(url.port, defaultPort);
112
+ if (typeof port === 'string') {
113
+ return { reason: port };
114
+ }
115
+ return {
116
+ proxy: {
117
+ type,
118
+ server,
119
+ port,
120
+ username: decodeUserInfo(url.username),
121
+ password: decodeUserInfo(url.password),
122
+ },
123
+ };
124
+ };
125
+ export const parseProxyString = (token) => {
126
+ const value = normalize(token);
127
+ let url;
128
+ try {
129
+ // URLSearchParams turns "+" into a space; keep it for base64 secrets.
130
+ url = new URL(value.replace(/\+/g, '%2B'));
131
+ }
132
+ catch {
133
+ return { reason: value.includes(':') ? 'not a valid proxy link' : 'not a proxy link, and no such file' };
134
+ }
135
+ const protocol = url.protocol.toLowerCase();
136
+ const host = url.hostname.toLowerCase();
137
+ if (protocol === 'tg:') {
138
+ return fromQuery(host, url.searchParams);
139
+ }
140
+ if ((protocol === 'https:' || protocol === 'http:') && TELEGRAM_HOSTS.has(host)) {
141
+ return fromQuery(url.pathname.replace(/^\/+|\/+$/g, '').toLowerCase(), url.searchParams);
142
+ }
143
+ if (protocol === 'socks5:' || protocol === 'socks5h:' || protocol === 'socks:') {
144
+ return fromAuthority('socks5', url, 1080);
145
+ }
146
+ if (protocol === 'http:') {
147
+ return fromAuthority('http', url, 80);
148
+ }
149
+ return { reason: 'unsupported link (expected t.me/proxy, t.me/socks, tg://..., socks5:// or http://)' };
150
+ };
151
+ const readInput = (input) => {
152
+ if (input === '-') {
153
+ return readFileSync(0, 'utf-8');
154
+ }
155
+ try {
156
+ if (statSync(input).isFile()) {
157
+ return readFileSync(input, 'utf-8');
60
158
  }
61
159
  }
62
160
  catch {
63
- return null;
161
+ // Not a file: treat as proxy text.
64
162
  }
65
- return null;
163
+ return input;
66
164
  };
67
165
  /**
68
- * Parse proxies from input string or file.
69
- * Automatically detects if input is a file path or proxy text.
166
+ * Parse proxies from a file path, "-" (stdin), or proxy text.
167
+ * Proxies may be separated by newlines or whitespace; lines starting with "#" are comments.
70
168
  */
71
169
  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
170
  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);
171
+ const issues = [];
172
+ for (const rawLine of readInput(input).split(/\r?\n/)) {
173
+ const line = rawLine.trim();
174
+ if (!line || line.startsWith('#')) {
175
+ continue;
176
+ }
177
+ for (const token of line.split(/\s+/)) {
178
+ if (token.startsWith('#')) {
179
+ break;
180
+ }
181
+ const outcome = parseProxyString(token);
182
+ if ('proxy' in outcome) {
183
+ proxies.push(outcome.proxy);
184
+ }
185
+ else {
186
+ issues.push({ input: token, reason: outcome.reason });
187
+ }
92
188
  }
93
189
  }
94
- return proxies;
190
+ return { proxies, issues };
95
191
  };
96
192
  //# sourceMappingURL=parser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/lib/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/lib/parser.ts"],"names":[],"mappings":"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"}