mtproto-checker 0.1.1 → 0.1.2

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 (3) hide show
  1. package/README.md +94 -231
  2. package/check.js +47 -3
  3. package/package.json +7 -3
package/README.md CHANGED
@@ -1,34 +1,34 @@
1
- # MTProto Checker
1
+ # MTProto Checker
2
2
 
3
- Fast Telegram MTProto proxy checker powered by TDLib. It does a real `testProxy`
4
- handshake through every proxy, so a green result means the proxy is much more
5
- likely to work in Telegram than with a plain TCP/TLS port check.
3
+ Telegram MTProto proxy checker powered by TDLib. It runs a real `testProxy`
4
+ handshake through each proxy, so a successful result is closer to "works in
5
+ Telegram" than a plain TCP/TLS port check.
6
6
 
7
- ## What It Does
7
+ ## Features
8
8
 
9
- - Parses `tg://proxy` and `https://t.me/proxy` links
10
- - 🌐 Loads proxy lists from remote URLs, local files, or `stdin`
11
- - 🧹 Removes duplicates by `server:port:secret`
12
- - 🔐 Supports hex and base64url MTProto secrets
13
- - 🕵️ Extracts Fake-TLS SNI from `ee...` secrets and supports padded `dd...` secrets
14
- - 🚀 Checks proxies concurrently via TDLib `testProxy`
15
- - 💪 Re-checks survivors with `--iterations` to find the most stable proxies
16
- - 📄 Writes both a full JSON report and a ready-to-use TXT list
9
+ - Parses `tg://proxy` and `https://t.me/proxy` links.
10
+ - Loads proxies from direct links, remote lists, local files, or `stdin`.
11
+ - De-duplicates by `server:port:secret`.
12
+ - Supports hex and base64url secrets, including Fake-TLS SNI extraction.
13
+ - Checks proxies concurrently and can re-check only successful proxies across
14
+ multiple iterations.
15
+ - Works as a CLI, HTTP API server, or CommonJS library.
17
16
 
18
17
  ## Requirements
19
18
 
20
- - Node.js 18+ recommended
21
- - npm
22
- - Telegram API credentials:
23
- - `TG_API_ID`
24
- - `TG_API_HASH`
19
+ - Node.js 18+
20
+ - Telegram API credentials: `TG_API_ID` and `TG_API_HASH`
25
21
 
26
- Get API credentials from [my.telegram.org](https://my.telegram.org).
22
+ Get credentials from [my.telegram.org](https://my.telegram.org). No Telegram
23
+ login or phone number is required; credentials are only used to initialize TDLib.
27
24
 
28
- > No Telegram login or phone number is required. The credentials are only used
29
- > to initialize TDLib before running `testProxy`.
25
+ ## Install
30
26
 
31
- ## Installation
27
+ ```bash
28
+ npm install mtproto-checker
29
+ ```
30
+
31
+ For local development:
32
32
 
33
33
  ```bash
34
34
  git clone git@github.com:Tar4s/mtproto-checker.git
@@ -36,183 +36,102 @@ cd mtproto-checker
36
36
  npm install
37
37
  ```
38
38
 
39
- Optional, if you want the `check-proxies` command available locally:
40
-
41
- ```bash
42
- npm link
43
- ```
44
-
45
- ### GitHub Packages
46
-
47
- This project can also be published to GitHub Packages as
48
- `@tar4s/mtproto-checker`. GitHub's npm registry requires scoped package names,
49
- so the GitHub Packages workflow applies that scoped name during publishing.
50
-
51
- To install from GitHub Packages:
39
+ GitHub Packages users can install the scoped package:
52
40
 
53
41
  ```bash
54
42
  npm config set @tar4s:registry https://npm.pkg.github.com
55
43
  npm install @tar4s/mtproto-checker
56
44
  ```
57
45
 
58
- Private packages require authentication with a GitHub personal access token that
59
- has `read:packages`.
60
-
61
- ## Quick Start
62
-
63
- Start the HTTP API server:
64
-
65
- ```bash
66
- TG_API_ID=12345 \
67
- TG_API_HASH=abcdef \
68
- CHECK_AUTH_USER=admin \
69
- CHECK_AUTH_PASSWORD=secret \
70
- node check.js
71
- ```
72
-
73
- By default it listens on port `3080`. Override it with `PORT`.
74
-
75
- Check URLs listed in `urls.txt`:
76
-
77
- ```bash
78
- TG_API_ID=12345 TG_API_HASH=abcdef npm start -- --sources urls.txt
79
- ```
80
-
81
- Equivalent direct Node.js run:
82
-
83
- ```bash
84
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt
85
- ```
86
-
87
- With `npm link`:
46
+ Private GitHub Packages require a token with `read:packages`.
88
47
 
89
- ```bash
90
- TG_API_ID=12345 TG_API_HASH=abcdef check-proxies --sources urls.txt
91
- ```
92
-
93
- Check one proxy link directly:
48
+ ## CLI
94
49
 
95
50
  ```bash
96
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js \
97
- --proxy 'tg://proxy?server=quackton.life&port=443&secret=7mX8dVOh9cqLULccAVs4ciR5YW5kZXgucnU'
51
+ TG_API_ID=12345 TG_API_HASH=abcdef npx mtproto-checker --sources urls.txt
98
52
  ```
99
53
 
100
- ## Input Sources
101
-
102
- You can provide proxies in several ways.
103
-
104
- ### 1. Direct Proxy Link
54
+ Common inputs:
105
55
 
106
56
  ```bash
57
+ # One direct proxy link
107
58
  TG_API_ID=12345 TG_API_HASH=abcdef node check.js \
108
- --proxy 'https://t.me/proxy?server=1.2.3.4&port=443&secret=...'
109
- ```
110
-
111
- ### 2. Source URL File
112
-
113
- `urls.txt` contains one remote text-list URL per line:
114
-
115
- ```txt
116
- https://example.com/proxies.txt
117
- https://example.com/more-proxies.txt
118
- ```
119
-
120
- Run:
121
-
122
- ```bash
123
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt
124
- ```
125
-
126
- ### 3. One Or More Remote URLs
59
+ --proxy 'tg://proxy?server=1.2.3.4&port=443&secret=...'
127
60
 
128
- ```bash
61
+ # One or more remote proxy-list URLs
129
62
  TG_API_ID=12345 TG_API_HASH=abcdef node check.js \
130
63
  --url https://example.com/proxies.txt \
131
- --url https://example.com/more-proxies.txt
132
- ```
133
-
134
- Positional HTTP URLs also work:
135
-
136
- ```bash
137
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js https://example.com/proxies.txt
138
- ```
64
+ --url https://example.com/more.txt
139
65
 
140
- ### 4. Local Proxy File
141
-
142
- ```bash
66
+ # Source URL file, local proxy file, or stdin
67
+ TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt
143
68
  TG_API_ID=12345 TG_API_HASH=abcdef node check.js proxies.txt
144
- ```
145
-
146
- ### 5. stdin
147
-
148
- ```bash
149
69
  cat proxies.txt | TG_API_ID=12345 TG_API_HASH=abcdef node check.js
150
70
  ```
151
71
 
152
- Input files may contain blank lines and `#` comments.
153
-
154
- ## CLI Options
72
+ Options:
155
73
 
156
74
  | Option | Default | Description |
157
75
  | --- | ---: | --- |
158
- | `--url <url>` | none | Add a remote proxy-list URL. Can be repeated. |
159
76
  | `--proxy <link>` | none | Check one `tg://proxy` or `https://t.me/proxy` link directly. |
160
- | `--sources <file>` | none | Read remote source URLs from a file, one URL per line. |
161
- | `--dc <1-5>` | `2` | Telegram data center ID used for `testProxy`. |
162
- | `--timeout <sec>` | `10` | Per-proxy TDLib timeout in seconds. Decimals are allowed. |
163
- | `--concurrency <n>` | `30` | Number of proxies checked in parallel. Lower values can produce steadier latency numbers. |
164
- | `--iterations <num>` | `1` | Number of check rounds. Each next round checks only proxies that passed the previous one. |
165
- | `--out <prefix>` | `result` | Output file prefix. Writes `<prefix>.json` and `<prefix>.txt`. |
166
-
167
- Environment variables:
168
-
169
- | Variable | Required | Description |
170
- | --- | --- | --- |
171
- | `TG_API_ID` | yes | Telegram API ID from `my.telegram.org`. |
172
- | `TG_API_HASH` | yes | Telegram API hash from `my.telegram.org`. |
173
- | `CHECK_AUTH_USER` | HTTP server only | Basic auth username. |
174
- | `CHECK_AUTH_PASSWORD` | HTTP server only | Basic auth password. |
175
- | `PORT` | no | HTTP server port. Defaults to `3080`. |
77
+ | `--url <url>` | none | Add a remote proxy-list URL. Repeatable. |
78
+ | `--sources <file>` | none | Read remote source URLs from a file. |
79
+ | `--dc <1-5>` | `2` | Telegram data center used for `testProxy`. |
80
+ | `--timeout <sec>` | `10` | Per-proxy TDLib timeout. |
81
+ | `--concurrency <n>` | `30` | Parallel proxy checks. |
82
+ | `--iterations <n>` | `1` | Re-check only successful proxies for `n` rounds. |
83
+ | `--out <prefix>` | `result` | Writes `<prefix>.json` and `<prefix>.txt`. |
84
+
85
+ Input files may contain blank lines and `#` comments. Only MTProto proxy links
86
+ are checked; `tg://socks` links are ignored.
176
87
 
177
88
  ## HTTP API
178
89
 
179
- Running `node check.js` without CLI arguments starts the HTTP server. The server
180
- requires Basic auth and exposes one endpoint:
90
+ Running `node check.js` without arguments starts the server on `PORT` or `3080`.
91
+ Basic auth is required.
92
+
93
+ ```bash
94
+ TG_API_ID=12345 \
95
+ TG_API_HASH=abcdef \
96
+ CHECK_AUTH_USER=admin \
97
+ CHECK_AUTH_PASSWORD=secret \
98
+ node check.js
99
+ ```
100
+
101
+ Endpoint:
181
102
 
182
103
  ```http
183
104
  POST /check
184
105
  Content-Type: application/json
185
106
  Authorization: Basic ...
186
107
 
187
- { "url": "https://example.com/proxies.txt" }
108
+ {
109
+ "url": "https://example.com/proxies.txt",
110
+ "iterations": 3,
111
+ "concurrency": 10
112
+ }
188
113
  ```
189
114
 
190
- The `url` field accepts either a remote `http(s)` proxy list or one direct
191
- `tg://proxy` / `https://t.me/proxy` link.
115
+ `url` accepts either a remote `http(s)` proxy list or one direct `tg://proxy` /
116
+ `https://t.me/proxy` link. `iterations` defaults to `1`; `concurrency` defaults
117
+ to `30`.
192
118
 
193
119
  Example:
194
120
 
195
121
  ```bash
196
122
  curl -u admin:secret \
197
123
  -H 'content-type: application/json' \
198
- -d '{"url":"https://example.com/proxies.txt"}' \
199
- http://127.0.0.1:3080/check
200
- ```
201
-
202
- Direct proxy link example:
203
-
204
- ```bash
205
- curl -u admin:secret \
206
- -H 'content-type: application/json' \
207
- -d '{"url":"tg://proxy?server=quackton.life&port=443&secret=7mX8dVOh9cqLULccAVs4ciR5YW5kZXgucnU"}' \
124
+ -d '{"url":"tg://proxy?server=1.2.3.4&port=443&secret=...","iterations":3,"concurrency":10}' \
208
125
  http://127.0.0.1:3080/check
209
126
  ```
210
127
 
211
- Response:
128
+ Response shape:
212
129
 
213
130
  ```json
214
131
  {
215
132
  "url": "https://example.com/proxies.txt",
133
+ "iterations": 3,
134
+ "concurrency": 10,
216
135
  "count": 1,
217
136
  "working": 1,
218
137
  "results": [
@@ -229,88 +148,27 @@ Response:
229
148
  }
230
149
  ```
231
150
 
232
- ## Output
233
-
234
- By default the checker writes:
151
+ ## Library Usage
235
152
 
236
- - `result.json` — full report for the final completed round
237
- - `result.txt` working proxy links from the final completed round, fastest first
238
-
239
- Example JSON item:
153
+ ```js
154
+ const { checkRequestUrl, checkProxiesFromUrls } = require('mtproto-checker')
240
155
 
241
- ```json
242
- {
243
- "server": "1.2.3.4",
244
- "port": 443,
245
- "sni": "example.com",
246
- "ok": true,
247
- "ms": 841,
248
- "error": null,
249
- "link": "tg://proxy?server=1.2.3.4&port=443&secret=..."
156
+ const opts = {
157
+ apiId: Number(process.env.TG_API_ID),
158
+ apiHash: process.env.TG_API_HASH,
159
+ concurrency: 30,
160
+ iterations: 2
250
161
  }
251
- ```
252
-
253
- Use a custom prefix:
254
-
255
- ```bash
256
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt --out fresh
257
- ```
258
-
259
- This creates `fresh.json` and `fresh.txt`.
260
-
261
- ## Practical Examples
262
-
263
- Fast broad scan:
264
-
265
- ```bash
266
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt --concurrency 80 --timeout 7
267
- ```
268
-
269
- More conservative latency check:
270
-
271
- ```bash
272
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt --concurrency 10 --timeout 15
273
- ```
274
-
275
- Find the most stable proxies across several rounds:
276
-
277
- ```bash
278
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt --iterations 3 --out stable
279
- ```
280
-
281
- Test against another Telegram DC:
282
-
283
- ```bash
284
- TG_API_ID=12345 TG_API_HASH=abcdef node check.js --sources urls.txt --dc 4
285
- ```
286
162
 
287
- Check a pasted list:
163
+ const direct = await checkRequestUrl('tg://proxy?server=1.2.3.4&port=443&secret=...', opts)
164
+ const fromLists = await checkProxiesFromUrls(['https://example.com/proxies.txt'], opts)
288
165
 
289
- ```bash
290
- pbpaste | TG_API_ID=12345 TG_API_HASH=abcdef node check.js --out pasted
166
+ console.log(direct, fromLists)
291
167
  ```
292
168
 
293
- ## Programmatic Usage
294
-
295
- ```js
296
- const { checkProxiesFromUrls } = require('./check')
297
-
298
- const results = await checkProxiesFromUrls(
299
- ['https://example.com/proxies.txt'],
300
- {
301
- apiId: Number(process.env.TG_API_ID),
302
- apiHash: process.env.TG_API_HASH,
303
- dc: 2,
304
- timeout: 10,
305
- concurrency: 30
306
- }
307
- )
308
-
309
- console.log(results)
310
- ```
311
-
312
- Exported helpers:
169
+ Main exports:
313
170
 
171
+ - `checkRequestUrl(url, opts)`
314
172
  - `checkProxiesFromUrls(urls, opts)`
315
173
  - `loadProxiesFromUrls(urls)`
316
174
  - `checkProxies(proxies, opts)`
@@ -319,15 +177,20 @@ Exported helpers:
319
177
  - `normalizeSecret(secret)`
320
178
  - `faketlsSni(hexSecret)`
321
179
 
322
- ## Notes & Troubleshooting
180
+ ## Output
181
+
182
+ CLI runs write:
183
+
184
+ - `result.json` or `<out>.json`: full report for the final completed round.
185
+ - `result.txt` or `<out>.txt`: working proxy links, fastest first.
186
+
187
+ Use `--out fresh` to write `fresh.json` and `fresh.txt`.
188
+
189
+ ## Troubleshooting
323
190
 
324
- - If you see `Set TG_API_ID and TG_API_HASH`, export both credentials or prefix
325
- the command with them.
326
- - If remote URLs fail on old Node.js versions, upgrade to Node.js 18+.
327
- - If checks are noisy, reduce `--concurrency`.
328
- - If you want only resilient proxies, increase `--iterations`; `result.txt`
329
- will contain proxies that survived the final round.
330
- - Only MTProto proxy links are checked. `tg://socks` links are ignored.
191
+ - `Set TG_API_ID and TG_API_HASH`: export both credentials or prefix the command.
192
+ - Noisy latency: reduce `--concurrency`.
193
+ - Need only stable proxies: increase `--iterations`.
331
194
  - Temporary TDLib files are created in `.proxy-checker-td/` and removed after the run.
332
195
 
333
196
  ## License
package/check.js CHANGED
@@ -415,6 +415,31 @@ async function checkSingleUrl(url, opts) {
415
415
  return checker(proxies, opts)
416
416
  }
417
417
 
418
+ async function loadSingleUrlProxies(url, opts = {}) {
419
+ const directProxy = parseLink(url)
420
+ if (directProxy) return [directProxy]
421
+
422
+ let parsed
423
+ try {
424
+ parsed = new URL(url)
425
+ } catch {
426
+ throw new Error('url must be a proxy link or an http or https URL')
427
+ }
428
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
429
+ throw new Error('url must be a proxy link or an http or https URL')
430
+ }
431
+
432
+ const fetcher = opts.fetcher || fetchText
433
+ const text = await fetcher(url)
434
+ return mergeProxies([text])
435
+ }
436
+
437
+ async function checkRequestUrl(url, opts) {
438
+ const proxies = await loadSingleUrlProxies(url, opts)
439
+ const checker = opts.checker || checkProxies
440
+ return runIterativeChecks(proxies, opts.iterations ?? 1, batch => checker(batch, opts))
441
+ }
442
+
418
443
  async function resolveInputProxies(opts, deps = {}) {
419
444
  const readFile = deps.readFile || (file => fs.readFileSync(file, 'utf8'))
420
445
  const readInputFn = deps.readInput || readInput
@@ -554,11 +579,23 @@ function createServer({ auth, checkUrl, logger = console.error }) {
554
579
  jsonResponse(res, statusCode, { error: 'Request body must include url' })
555
580
  return
556
581
  }
582
+ const iterations = body.iterations === undefined ? 1 : body.iterations
583
+ if (!Number.isInteger(iterations) || iterations < 1) {
584
+ statusCode = 400
585
+ jsonResponse(res, statusCode, { error: 'iterations must be a positive integer' })
586
+ return
587
+ }
588
+ const concurrency = body.concurrency === undefined ? 30 : body.concurrency
589
+ if (!Number.isInteger(concurrency) || concurrency < 1) {
590
+ statusCode = 400
591
+ jsonResponse(res, statusCode, { error: 'concurrency must be a positive integer' })
592
+ return
593
+ }
557
594
 
558
595
  const url = body.url.trim()
559
596
  let results
560
597
  try {
561
- results = await checkUrl(url)
598
+ results = await checkUrl(url, { iterations, concurrency })
562
599
  } catch (err) {
563
600
  statusCode = 502
564
601
  jsonResponse(res, statusCode, {
@@ -571,6 +608,8 @@ function createServer({ auth, checkUrl, logger = console.error }) {
571
608
  statusCode = 200
572
609
  jsonResponse(res, statusCode, {
573
610
  url,
611
+ iterations,
612
+ concurrency,
574
613
  count: report.length,
575
614
  working: report.filter(item => item.ok).length,
576
615
  results: report
@@ -603,7 +642,12 @@ async function startServer(env = process.env) {
603
642
 
604
643
  const server = createServer({
605
644
  auth: { user, password },
606
- checkUrl: async url => checkSingleUrl(url, { apiId, apiHash })
645
+ checkUrl: async (url, requestOpts) => checkRequestUrl(url, {
646
+ apiId,
647
+ apiHash,
648
+ iterations: requestOpts.iterations,
649
+ concurrency: requestOpts.concurrency
650
+ })
607
651
  })
608
652
 
609
653
  await new Promise((resolve, reject) => {
@@ -681,7 +725,7 @@ async function main() {
681
725
  process.exit(0)
682
726
  }
683
727
 
684
- module.exports = { checkSingleUrl, configureTdlibOnce, createServer, parseArgs, resolveInputProxies, checkProxiesFromUrls, loadProxiesFromUrls, checkProxies, runIterativeChecks, mergeProxies, parseLink, normalizeSecret, faketlsSni, shouldStartServer, startServer }
728
+ module.exports = { checkRequestUrl, checkSingleUrl, configureTdlibOnce, createServer, parseArgs, resolveInputProxies, checkProxiesFromUrls, loadProxiesFromUrls, checkProxies, runIterativeChecks, mergeProxies, parseLink, normalizeSecret, faketlsSni, shouldStartServer, startServer }
685
729
 
686
730
  if (require.main === module) (shouldStartServer(process.argv.slice(2)) ? startServer() : main()).catch(err => {
687
731
  console.error(err)
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "mtproto-checker",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Check Telegram MTProto proxies via a real TDLib handshake (testProxy), like tdesktop does",
5
+ "main": "check.js",
6
+ "exports": {
7
+ ".": "./check.js"
8
+ },
5
9
  "repository": {
6
10
  "type": "git",
7
- "url": "https://github.com/Tar4s/mtproto-checker"
11
+ "url": "git+https://github.com/Tar4s/mtproto-checker.git"
8
12
  },
9
13
  "bugs": {
10
14
  "url": "https://github.com/Tar4s/mtproto-checker/issues"
@@ -22,7 +26,7 @@
22
26
  "start": "node check.js"
23
27
  },
24
28
  "engines": {
25
- "node": ">=16"
29
+ "node": ">=18"
26
30
  },
27
31
  "dependencies": {
28
32
  "tdl": "^8.0.2",