mtproto-checker 0.2.0 โ 0.3.1
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.
- package/README.md +75 -34
- package/check.js +29 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Telegram MTProto proxy health checker powered by **TDLib**. Performs a real `tes
|
|
|
5
5
|
## โก Features
|
|
6
6
|
|
|
7
7
|
- ๐ค Real MTProto handshake (not just a port scan)
|
|
8
|
-
- ๐ก Check from remote URLs, local files,
|
|
8
|
+
- ๐ก Check from remote URLs, local files, direct proxy links, or any mix
|
|
9
9
|
- ๐ Multi-iteration filtering โ only survivors advance
|
|
10
10
|
- ๐ Built-in HTTP API server with Basic Auth
|
|
11
11
|
- ๐งน Auto de-duplication by `server:port:secret`
|
|
@@ -15,10 +15,14 @@ Telegram MTProto proxy health checker powered by **TDLib**. Performs a real `tes
|
|
|
15
15
|
## ๐ฆ Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
+
# Global โ gives you the `mtproto-checker` command
|
|
19
|
+
npm install -g mtproto-checker
|
|
20
|
+
|
|
21
|
+
# Local dependency
|
|
18
22
|
npm install mtproto-checker
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
Or clone
|
|
25
|
+
Or clone:
|
|
22
26
|
|
|
23
27
|
```bash
|
|
24
28
|
git clone https://github.com/Tar4s/mtproto-checker.git
|
|
@@ -44,32 +48,46 @@ npm install @tar4s/mtproto-checker
|
|
|
44
48
|
| `TG_API_HASH` | โ
| Telegram API Hash |
|
|
45
49
|
| `CHECK_AUTH_USER` | ๐ | HTTP Basic Auth username (server mode) |
|
|
46
50
|
| `CHECK_AUTH_PASSWORD` | ๐ | HTTP Basic Auth password (server mode) |
|
|
47
|
-
| `PORT` | โ | Server port (default `
|
|
51
|
+
| `PORT` | โ | Server port (default `8080`) |
|
|
52
|
+
|
|
53
|
+
## ๐ Quick Start (Global)
|
|
54
|
+
|
|
55
|
+
After `npm i -g mtproto-checker`:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Start HTTP server (no arguments)
|
|
59
|
+
TG_API_ID=12345 TG_API_HASH=abcdef \
|
|
60
|
+
CHECK_AUTH_USER=admin CHECK_AUTH_PASSWORD=secret \
|
|
61
|
+
check-proxies
|
|
62
|
+
|
|
63
|
+
# CLI mode (with arguments)
|
|
64
|
+
TG_API_ID=12345 TG_API_HASH=abcdef check-proxies --sources urls.txt
|
|
65
|
+
```
|
|
48
66
|
|
|
49
|
-
##
|
|
67
|
+
## ๐ฅ CLI Usage
|
|
50
68
|
|
|
51
69
|
```bash
|
|
52
|
-
TG_API_ID=12345 TG_API_HASH=abcdef
|
|
70
|
+
TG_API_ID=12345 TG_API_HASH=abcdef check-proxies [sources] [options]
|
|
53
71
|
```
|
|
54
72
|
|
|
55
73
|
### Input Methods
|
|
56
74
|
|
|
57
75
|
```bash
|
|
58
76
|
# Single proxy link
|
|
59
|
-
|
|
77
|
+
check-proxies --proxy "tg://proxy?server=1.2.3.4&port=443&secret=ee..."
|
|
60
78
|
|
|
61
79
|
# Remote URLs (positional or --url flag, repeatable)
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
check-proxies https://example.com/proxies.txt
|
|
81
|
+
check-proxies --url URL1 --url URL2
|
|
64
82
|
|
|
65
83
|
# File with source URLs (one per line, # comments ok)
|
|
66
|
-
|
|
84
|
+
check-proxies --sources urls.txt
|
|
67
85
|
|
|
68
86
|
# Local proxy file
|
|
69
|
-
|
|
87
|
+
check-proxies ./my-proxies.txt
|
|
70
88
|
|
|
71
89
|
# Stdin
|
|
72
|
-
cat proxies.txt |
|
|
90
|
+
cat proxies.txt | check-proxies
|
|
73
91
|
```
|
|
74
92
|
|
|
75
93
|
### โ๏ธ Options
|
|
@@ -94,23 +112,29 @@ cat proxies.txt | node check.js
|
|
|
94
112
|
|
|
95
113
|
## ๐ HTTP API Server
|
|
96
114
|
|
|
97
|
-
Start with **no arguments
|
|
115
|
+
Start with **no arguments** โ works both globally and locally:
|
|
98
116
|
|
|
99
117
|
```bash
|
|
118
|
+
# Global
|
|
119
|
+
TG_API_ID=12345 TG_API_HASH=abcdef \
|
|
120
|
+
CHECK_AUTH_USER=admin CHECK_AUTH_PASSWORD=secret \
|
|
121
|
+
check-proxies
|
|
122
|
+
|
|
123
|
+
# Local
|
|
100
124
|
TG_API_ID=12345 TG_API_HASH=abcdef \
|
|
101
125
|
CHECK_AUTH_USER=admin CHECK_AUTH_PASSWORD=secret \
|
|
102
126
|
node check.js
|
|
103
127
|
```
|
|
104
128
|
|
|
105
129
|
```
|
|
106
|
-
[mtproto-checker] โก HTTP server listening on http://localhost:
|
|
130
|
+
[mtproto-checker] โก HTTP server listening on http://localhost:8080
|
|
107
131
|
[mtproto-checker] POST /check (Basic auth: admin:***)
|
|
108
132
|
```
|
|
109
133
|
|
|
110
134
|
### `POST /check`
|
|
111
135
|
|
|
112
136
|
```bash
|
|
113
|
-
curl -u admin:secret http://localhost:
|
|
137
|
+
curl -u admin:secret http://localhost:8080/check \
|
|
114
138
|
-H "Content-Type: application/json" \
|
|
115
139
|
-d '{"url": "https://example.com/proxies.txt", "iterations": 2, "concurrency": 20}'
|
|
116
140
|
```
|
|
@@ -119,21 +143,39 @@ curl -u admin:secret http://localhost:3080/check \
|
|
|
119
143
|
|
|
120
144
|
| Field | Type | Default | Description |
|
|
121
145
|
|-------|------|:-------:|-------------|
|
|
122
|
-
| `url` | string | โ | Proxy list URL or
|
|
146
|
+
| `url` / `urls` / `uri` / `uris` | string \| string[] | โ | Proxy link(s), list URL(s), or any mix |
|
|
123
147
|
| `iterations` | int | `1` | Check rounds |
|
|
124
148
|
| `concurrency` | int | `30` | Parallel checks |
|
|
125
149
|
|
|
150
|
+
All input formats work:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
// Single proxy link
|
|
154
|
+
{ "url": "tg://proxy?server=1.2.3.4&port=443&secret=ee..." }
|
|
155
|
+
|
|
156
|
+
// Single list URL
|
|
157
|
+
{ "url": "https://example.com/proxies.txt" }
|
|
158
|
+
|
|
159
|
+
// Array โ mix of direct links and list URLs
|
|
160
|
+
{ "urls": [
|
|
161
|
+
"tg://proxy?server=1.2.3.4&port=443&secret=ee...",
|
|
162
|
+
"https://t.me/proxy?server=5.6.7.8&port=443&secret=dd...",
|
|
163
|
+
"https://example.com/list.txt"
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
126
168
|
**Response:**
|
|
127
169
|
|
|
128
170
|
```json
|
|
129
171
|
{
|
|
130
|
-
"
|
|
172
|
+
"uris": ["https://example.com/proxies.txt"],
|
|
131
173
|
"iterations": 2,
|
|
132
174
|
"concurrency": 20,
|
|
133
175
|
"count": 150,
|
|
134
176
|
"working": 42,
|
|
135
177
|
"results": [
|
|
136
|
-
{ "server": "1.2.3.4", "port": 443, "sni": "example.com", "ok": true, "ms": 312, "error": null
|
|
178
|
+
{ "proxy": { "raw": "tg://proxy?...", "server": "1.2.3.4", "port": 443, "secret": "ee...", "sni": "example.com" }, "ok": true, "ms": 312, "error": null }
|
|
137
179
|
]
|
|
138
180
|
}
|
|
139
181
|
```
|
|
@@ -164,32 +206,31 @@ const results = await checkProxyLink(
|
|
|
164
206
|
|
|
165
207
|
### `checkProxiesFromURIs(uris, opts)` โ `Promise<Array>`
|
|
166
208
|
|
|
167
|
-
Check proxies from remote URLs, local files, or
|
|
209
|
+
Check proxies from remote URLs, local files, direct proxy links, or any mix. Auto-detects type per entry, de-duplicates automatically.
|
|
168
210
|
|
|
169
211
|
```js
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
'https://example.com/proxies.txt',
|
|
173
|
-
{ apiId: 12345, apiHash: 'abcdef' }
|
|
174
|
-
)
|
|
212
|
+
// Single source
|
|
213
|
+
await checkProxiesFromURIs('https://example.com/proxies.txt', opts)
|
|
175
214
|
|
|
176
|
-
//
|
|
177
|
-
|
|
215
|
+
// Direct proxy link
|
|
216
|
+
await checkProxiesFromURIs('tg://proxy?server=1.2.3.4&port=443&secret=ee...', opts)
|
|
178
217
|
|
|
179
|
-
// Mix
|
|
180
|
-
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'https://example.com/
|
|
218
|
+
// Mix of everything
|
|
219
|
+
await checkProxiesFromURIs([
|
|
220
|
+
'tg://proxy?server=1.2.3.4&port=443&secret=ee...',
|
|
221
|
+
'https://t.me/proxy?server=5.6.7.8&port=443&secret=dd...',
|
|
222
|
+
'https://example.com/list.txt',
|
|
223
|
+
'./local-list.txt'
|
|
184
224
|
], { apiId: 12345, apiHash: 'abcdef', iterations: 2, concurrency: 20 })
|
|
185
225
|
```
|
|
186
226
|
|
|
187
227
|
```
|
|
188
|
-
[mtproto-checker] Loading
|
|
189
|
-
|
|
228
|
+
[mtproto-checker] Loading 4 source(s)...
|
|
229
|
+
โก 1.2.3.4:443
|
|
230
|
+
โก 5.6.7.8:443
|
|
231
|
+
โ https://example.com/list.txt
|
|
190
232
|
โ ./local-list.txt
|
|
191
|
-
|
|
192
|
-
[mtproto-checker] Checking 150 proxies (dc=2, timeout=10s, concurrency=30, iterations=2)...
|
|
233
|
+
[mtproto-checker] Checking 150 proxies (dc=2, timeout=10s, concurrency=20, iterations=2)...
|
|
193
234
|
|
|
194
235
|
[ 1/150] โ 312ms 1.2.3.4:443 [example.com]
|
|
195
236
|
[ 2/150] โ Timeout 5.6.7.8:443
|
package/check.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* CLI usage:
|
|
21
21
|
* TG_API_ID=12345 TG_API_HASH=abcdef CHECK_AUTH_USER=admin CHECK_AUTH_PASSWORD=secret node check.js
|
|
22
|
-
* # starts the HTTP API server on PORT (default
|
|
22
|
+
* # starts the HTTP API server on PORT (default 8080)
|
|
23
23
|
* TG_API_ID=12345 TG_API_HASH=abcdef... node check.js [sources] [options]
|
|
24
24
|
* # sources: any positional http(s) URL, a local file path, or stdin
|
|
25
25
|
* node check.js https://raw.githubusercontent.com/u/r/main/list.txt
|
|
@@ -435,7 +435,14 @@ function loadProxiesFromFile(filePath) {
|
|
|
435
435
|
async function checkProxiesFromURIs(uris, opts) {
|
|
436
436
|
const list = Array.isArray(uris) ? uris : [uris]
|
|
437
437
|
console.error(`[mtproto-checker] Loading ${list.length} source(s)...`)
|
|
438
|
+
const directProxies = []
|
|
438
439
|
const texts = await Promise.all(list.map(uri => {
|
|
440
|
+
const parsed = parseLink(uri)
|
|
441
|
+
if (parsed) {
|
|
442
|
+
console.error(` โก ${parsed.server}:${parsed.port}`)
|
|
443
|
+
directProxies.push(parsed)
|
|
444
|
+
return Promise.resolve('')
|
|
445
|
+
}
|
|
439
446
|
if (/^https?:\/\//i.test(uri)) {
|
|
440
447
|
console.error(` โ ${uri}`)
|
|
441
448
|
return fetchText(uri).catch(err => { console.error(` โ Skipping ${uri}: ${err.message}`); return '' })
|
|
@@ -443,7 +450,15 @@ async function checkProxiesFromURIs(uris, opts) {
|
|
|
443
450
|
console.error(` โ ${uri}`)
|
|
444
451
|
return Promise.resolve(fs.readFileSync(uri, 'utf8'))
|
|
445
452
|
}))
|
|
446
|
-
const
|
|
453
|
+
const fromTexts = mergeProxies(texts)
|
|
454
|
+
const seen = new Set(fromTexts.map(p => `${p.server}:${p.port}:${p.secret}`))
|
|
455
|
+
const proxies = [...fromTexts]
|
|
456
|
+
for (const p of directProxies) {
|
|
457
|
+
const key = `${p.server}:${p.port}:${p.secret}`
|
|
458
|
+
if (seen.has(key)) continue
|
|
459
|
+
seen.add(key)
|
|
460
|
+
proxies.push(p)
|
|
461
|
+
}
|
|
447
462
|
if (proxies.length === 0) {
|
|
448
463
|
console.error('[mtproto-checker] No valid proxy links found.')
|
|
449
464
|
return []
|
|
@@ -645,9 +660,10 @@ function createServer({ auth, checkUrl, logger = console.error }) {
|
|
|
645
660
|
}
|
|
646
661
|
|
|
647
662
|
const body = await readJsonBody(req)
|
|
648
|
-
|
|
663
|
+
const uris = body.url || body.urls || body.uri || body.uris
|
|
664
|
+
if (!uris || (typeof uris === 'string' && uris.trim() === '') || (Array.isArray(uris) && uris.length === 0)) {
|
|
649
665
|
statusCode = 400
|
|
650
|
-
jsonResponse(res, statusCode, { error: 'Request body must include url' })
|
|
666
|
+
jsonResponse(res, statusCode, { error: 'Request body must include url (string or array)' })
|
|
651
667
|
return
|
|
652
668
|
}
|
|
653
669
|
const iterations = body.iterations === undefined ? 1 : body.iterations
|
|
@@ -663,10 +679,10 @@ function createServer({ auth, checkUrl, logger = console.error }) {
|
|
|
663
679
|
return
|
|
664
680
|
}
|
|
665
681
|
|
|
666
|
-
const
|
|
682
|
+
const input = Array.isArray(uris) ? uris.map(u => u.trim()) : [uris.trim()]
|
|
667
683
|
let results
|
|
668
684
|
try {
|
|
669
|
-
results = await checkUrl(
|
|
685
|
+
results = await checkUrl(input, { iterations, concurrency })
|
|
670
686
|
} catch (err) {
|
|
671
687
|
statusCode = 502
|
|
672
688
|
jsonResponse(res, statusCode, {
|
|
@@ -675,15 +691,14 @@ function createServer({ auth, checkUrl, logger = console.error }) {
|
|
|
675
691
|
})
|
|
676
692
|
return
|
|
677
693
|
}
|
|
678
|
-
const report = toReport(results)
|
|
679
694
|
statusCode = 200
|
|
680
695
|
jsonResponse(res, statusCode, {
|
|
681
|
-
|
|
696
|
+
uris: input,
|
|
682
697
|
iterations,
|
|
683
698
|
concurrency,
|
|
684
|
-
count:
|
|
685
|
-
working:
|
|
686
|
-
results
|
|
699
|
+
count: results.length,
|
|
700
|
+
working: results.filter(item => item.ok).length,
|
|
701
|
+
results
|
|
687
702
|
})
|
|
688
703
|
} catch (err) {
|
|
689
704
|
statusCode = err.statusCode || 500
|
|
@@ -711,7 +726,7 @@ async function startServer(opts = {}) {
|
|
|
711
726
|
const apiHash = opts.apiHash ?? process.env.TG_API_HASH
|
|
712
727
|
const user = opts.user ?? process.env.CHECK_AUTH_USER
|
|
713
728
|
const password = opts.password ?? process.env.CHECK_AUTH_PASSWORD
|
|
714
|
-
const port = opts.port ?? parseInt(process.env.PORT || '
|
|
729
|
+
const port = opts.port ?? parseInt(process.env.PORT || '8080', 10)
|
|
715
730
|
|
|
716
731
|
if (!apiId || !apiHash) throw new Error('Set TG_API_ID and TG_API_HASH (get them at https://my.telegram.org).')
|
|
717
732
|
if (!user || !password) throw new Error('Set CHECK_AUTH_USER and CHECK_AUTH_PASSWORD for HTTP Basic auth.')
|
|
@@ -719,7 +734,7 @@ async function startServer(opts = {}) {
|
|
|
719
734
|
|
|
720
735
|
const server = createServer({
|
|
721
736
|
auth: { user, password },
|
|
722
|
-
checkUrl: async (url, requestOpts) =>
|
|
737
|
+
checkUrl: async (url, requestOpts) => checkProxiesFromURIs(url, {
|
|
723
738
|
apiId,
|
|
724
739
|
apiHash,
|
|
725
740
|
iterations: requestOpts.iterations,
|
|
@@ -804,7 +819,7 @@ async function main() {
|
|
|
804
819
|
}
|
|
805
820
|
|
|
806
821
|
module.exports = { checkProxyLink, checkProxiesFromURIs, startServer }
|
|
807
|
-
module.exports._internals = { checkRequestUrl, checkSingleUrl, configureTdlibOnce, createServer, parseArgs, resolveInputProxies, runIterativeChecks, shouldStartServer }
|
|
822
|
+
module.exports._internals = { checkRequestUrl, checkSingleUrl, configureTdlibOnce, createServer, parseArgs, resolveInputProxies, runIterativeChecks, shouldStartServer, parseLink, normalizeSecret, faketlsSni, mergeProxies, loadProxiesFromFile }
|
|
808
823
|
|
|
809
824
|
if (require.main === module) (shouldStartServer(process.argv.slice(2)) ? startServer() : main()).catch(err => {
|
|
810
825
|
console.error(err)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mtproto-checker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Check Telegram MTProto proxies via a real TDLib handshake (testProxy), like tdesktop does",
|
|
5
5
|
"main": "check.js",
|
|
6
6
|
"exports": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"homepage": "https://github.com/Tar4s/mtproto-checker#readme",
|
|
17
17
|
"bin": {
|
|
18
|
-
"
|
|
18
|
+
"mtproto-checker": "check.js"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"check.js",
|