Passed
Push — main ( 449be3...37d1d7 )
by YeBeKhe
02:19
created

Hy2Singbox()   B

Complexity

Conditions 7
Paths 17

Size

Total Lines 39
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 25
nc 17
nop 1
dl 0
loc 39
rs 8.5866
c 1
b 0
f 0
1
<?php
2
3
header("Content-type: application/json;");
4
5
function create_tehran_timestamp_tomorrow() {
6
  date_default_timezone_set('Asia/Tehran');
7
  $dateTomorrow = new DateTime('tomorrow');
8
  $timestampTomorrow = strtotime($dateTomorrow->format('Y-m-d H:i:s'));
9
  return $timestampTomorrow;
10
}
11
12
function isEvenLength($str) {
13
    $length = strlen($str);
14
    return $length % 2 == 0;
15
}
16
17
function process_jsons($input, $locationNames){
18
    $input[0]['outbounds'] = array_merge($input[0]['outbounds'], array_filter($locationNames));
19
    return $input;
20
}
21
22
function extract_names($input){
23
    foreach($input as $config){
24
        if ($config['tag'] !== ""){
25
             $locationNames[] = $config['tag'];
26
        }
27
    }
28
    return $locationNames;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $locationNames does not seem to be defined for all execution paths leading up to this point.
Loading history...
29
}
30
31
function processWsPath($input) {
32
  if (strpos($input, '/') === 0) {
33
    $input = substr($input, 1);
34
  }
35
  $max_early_data = 0;
36
  if (strpos($input, '?ed=2048') !== false) {
37
    $input = str_replace('?ed=2048', '', $input);
38
    $max_early_data = 2048;
39
  }
40
  $output = [
41
      "path" => "/" . $input,
42
      "max_early_data" => $max_early_data
43
  ];
44
  
45
  return $output;
46
}
47
48
function VmessSingbox($VmessUrl)
49
{
50
    $decode_vmess = decode_vmess($VmessUrl);
51
    if (is_null($decode_vmess["ps"]) || $decode_vmess["ps"] === "") {
52
        return null;
53
    }
54
    $configResult = [
55
        "tag" => $decode_vmess["ps"],
56
        "type" => "vmess",
57
        "server" => $decode_vmess["add"],
58
        "server_port" => intval($decode_vmess["port"]),
59
        "uuid" => $decode_vmess["id"],
60
        "security" => "auto",
61
        "alter_id" => intval($decode_vmess["aid"]),
62
        "global_padding" => false,
63
        "authenticated_length" => true,
64
        "packet_encoding" => "",
65
        "multiplex" => [
66
            "enabled" => false,
67
            "protocol" => "smux",
68
            "max_streams" => 32,
69
        ],
70
    ];
71
72
    if ($decode_vmess["port"] === "443" || $decode_vmess["tls"] === "tls") {
73
        $configResult["tls"] = [
74
            "enabled" => true,
75
            "server_name" =>
76
                $decode_vmess["sni"] !== ""
77
                    ? $decode_vmess["sni"]
78
                    : $decode_vmess["add"],
79
            "insecure" => true,
80
            "disable_sni" => false,
81
            "utls" => [
82
                "enabled" => true,
83
                "fingerprint" => "chrome",
84
            ],
85
        ];
86
    }
87
    
88
    if ($decode_vmess["net"] === "ws") {
89
        $pathProcess = processWsPath($decode_vmess["path"]);
90
        $configResult["transport"] = [
91
            "type" => $decode_vmess["net"],
92
            "path" => $pathProcess['path'],
93
            "headers" => [
94
                "Host" =>
95
                    $decode_vmess["host"] !== ""
96
                        ? $decode_vmess["host"]
97
                        : ($decode_vmess["add"] !== ""
98
                            ? $decode_vmess["add"]
99
                            : ""),
100
            ],
101
            "max_early_data" => $pathProcess['max_early_data'],
102
            "early_data_header_name" => "Sec-WebSocket-Protocol",
103
        ];
104
    } elseif ($decode_vmess["net"] === "grpc") {
105
        $configResult["transport"] = [
106
            "type" => $decode_vmess["net"],
107
            "service_name" => $decode_vmess["path"],
108
            "idle_timeout" => "15s",
109
            "ping_timeout" => "15s",
110
            "permit_without_stream" => false,
111
        ];
112
    }
113
114
    return $configResult;
115
}
116
117
function VlessSingbox($VlessUrl)
118
{
119
    $decoded_vless = parseProxyUrl($VlessUrl, "vless");
120
    //print_r($decoded_vless);
121
    if (is_null($decoded_vless["hash"]) || $decoded_vless["hash"] === "") {
122
        return null;
123
    }
124
    $configResult = [
125
        "tag" => $decoded_vless["hash"],
126
        "type" => "vless",
127
        "server" => $decoded_vless["hostname"],
128
        "server_port" => intval($decoded_vless["port"]),
129
        "uuid" => $decoded_vless["username"],
130
        "flow" => !is_null($decoded_vless["params"]["flow"])
131
            ? "xtls-rprx-vision"
132
            : "",
133
        "packet_encoding" => "xudp",
134
        "multiplex" => [
135
            "enabled" => false,
136
            "protocol" => "smux",
137
            "max_streams" => 32,
138
        ],
139
    ];
140
141
    if (
142
        $decoded_vless["port"] === "443" ||
143
        $decoded_vless["params"]["security"] === "tls" ||
144
        $decoded_vless["params"]["security"] === "reality"
145
    ) {
146
        $configResult["tls"] = [
147
            "enabled" => true,
148
            "server_name" => !is_null($decoded_vless["params"]["sni"])
149
                ? $decoded_vless["params"]["sni"]
150
                : "",
151
            "insecure" => false,
152
            "utls" => [
153
                "enabled" => true,
154
                "fingerprint" => "chrome",
155
            ],
156
        ];
157
158
        if (
159
            $decoded_vless["params"]["security"] === "reality" ||
160
            isset($decoded_vless["params"]["pbk"])
161
        ) {
162
            $configResult["tls"]["reality"] = [
163
                "enabled" => true,
164
                "public_key" => !is_null($decoded_vless["params"]["pbk"])
165
                    ? $decoded_vless["params"]["pbk"]
166
                    : "",
167
                "short_id" => !is_null($decoded_vless["params"]["sid"])
168
                    ? $decoded_vless["params"]["sid"]
169
                    : "",
170
            ];
171
        if (
172
            is_null($decoded_vless["params"]["pbk"]) or
173
            $decoded_vless["params"]["pbk"] === ""
174
        ) {
175
            return null;
176
        }
177
        }
178
    }
179
    $transportTypes = [
180
        "ws" => [
181
            "type" => $decoded_vless["params"]["type"],
182
            "path" => processWsPath($decoded_vless["params"]["path"])['path'],
183
            "headers" => [
184
                "Host" => !is_null($decoded_vless["params"]["host"])
185
                    ? $decoded_vless["params"]["host"]
186
                    : "",
187
            ],
188
            "max_early_data" => processWsPath($decoded_vless["params"]["path"])['max_early_data'],
189
            "early_data_header_name" => "Sec-WebSocket-Protocol",
190
        ],
191
        "grpc" => [
192
            "type" => $decoded_vless["params"]["type"],
193
            "service_name" => $decoded_vless["params"]["serviceName"],
194
            "idle_timeout" => "15s",
195
            "ping_timeout" => "15s",
196
            "permit_without_stream" => false,
197
        ],
198
    ];
199
    if (isset($decoded_vless["params"]["type"])) {
200
        if (
201
            $decoded_vless["params"]["type"] === "ws" ||
202
            $decoded_vless["params"]["type"] === "grpc"
203
        ) {
204
            $configResult["transport"] =
205
                $transportTypes[$decoded_vless["params"]["type"]];
206
        }
207
    }
208
    return $configResult;
209
}
210
211
function TrojanSingbox($TrojanUrl)
212
{
213
    $decoded_trojan = parseProxyUrl($TrojanUrl);
214
    if (is_null($decoded_trojan["hash"]) || $decoded_trojan["hash"] === "") {
215
        return null;
216
    }
217
    $configResult = [
218
        "tag" => $decoded_trojan["hash"],
219
        "type" => "trojan",
220
        "server" => $decoded_trojan["hostname"],
221
        "server_port" => intval($decoded_trojan["port"]),
222
        "password" => $decoded_trojan["username"],
223
        "multiplex" => [
224
            "enabled" => false,
225
            "protocol" => "smux",
226
            "max_streams" => 32,
227
        ],
228
    ];
229
230
    if (
231
        $decoded_trojan["port"] === "443" ||
232
        $decoded_trojan["params"]["security"] === "tls"
233
    ) {
234
        $configResult["tls"] = [
235
            "enabled" => true,
236
            "server_name" => !is_null($decoded_trojan["params"]["sni"])
237
                ? $decoded_trojan["params"]["sni"]
238
                : "",
239
            "insecure" => true,
240
            "utls" => [
241
                "enabled" => true,
242
                "fingerprint" => "chrome",
243
            ],
244
        ];
245
    }
246
247
    $transportTypes = [
248
        "ws" => [
249
            "type" => $decoded_trojan["params"]["type"],
250
            "path" => processWsPath($decoded_trojan["params"]["path"])["path"],
251
            "headers" => [
252
                "Host" => $decoded_trojan["params"]["host"],
253
            ],
254
        ],
255
        "grpc" => [
256
            "type" => $decoded_trojan["params"]["type"],
257
            "service_name" => $decoded_trojan["params"]["serviceName"],
258
            "idle_timeout" => "15s",
259
            "ping_timeout" => "15s",
260
            "permit_without_stream" => false,
261
        ],
262
    ];
263
    if (isset($decoded_trojan["params"]["type"])) {
264
        if (
265
            $decoded_trojan["params"]["type"] === "ws" ||
266
            $decoded_trojan["params"]["type"] === "grpc"
267
        ) {
268
            $configResult["transport"] =
269
                $transportTypes[$decoded_trojan["params"]["type"]];
270
        }
271
    }
272
    return $configResult;
273
}
274
275
function ShadowsocksSingbox($ShadowsocksUrl) {
276
    $decoded_shadowsocks = ParseShadowsocks($ShadowsocksUrl);
277
    if (is_null($decoded_shadowsocks['name']) || $decoded_shadowsocks['name'] === ""){
278
        return null;
279
    }
280
    if ($decoded_shadowsocks['encryption_method'] === "chacha20-poly1305") {
281
        return null;
282
    }
283
    $configResult = [
284
        'tag' => $decoded_shadowsocks['name'],
285
        'type' => "shadowsocks",
286
        'server' => $decoded_shadowsocks['server_address'],
287
        'server_port' => intval($decoded_shadowsocks['server_port']),
288
        'method' => $decoded_shadowsocks['encryption_method'],
289
        'password' => $decoded_shadowsocks['password'],
290
        'plugin' => "",
291
        'plugin_opts' => ""
292
    ];
293
    return $configResult;
294
}
295
296
function TuicSingbox($TuicUrl) {
297
    $decodedTuic = ParseTuic($TuicUrl);
298
    if (
299
        is_null($decodedTuic['hash']) ||
300
        $decodedTuic['hash'] === ""
301
    ) {
302
        return null;
303
    }
304
305
    $configResult = [
306
        "tag" => $decodedTuic["hash"],
307
        "type" => "tuic",
308
        "server" => $decodedTuic['hostname'],
309
        "server_port" => intval($decodedTuic['port']),
310
        "uuid" => $decodedTuic['username'],
311
        "password" => $decodedTuic['pass'],
312
        "congestion_control" => $decodedTuic['params']['congestion_control'],
313
        "udp_relay_mode" => $decodedTuic['params']['udp_relay_mode'],
314
        "zero_rtt_handshake" => false,
315
        "heartbeat" => "10s",
316
        "network" => "tcp",
317
    ];
318
319
    $configResult['tls'] = [
320
            "enabled" => true,
321
            "disable_sni" => isset($decodedTuic['params']['sni']) ? false : true,
322
            "server_name" => isset($decodedTuic['params']['sni']) ? $decodedTuic['params']['sni'] : "",
323
            "insecure" => isset($decodedTuic['params']['allow_insecure']) && intval($decodedTuic['params']['allow_insecure']) === 1 ? true : false,
324
            "alpn" => [
325
                "h3",
326
                "spdy/3.1"
327
            ],
328
        ];
329
    if (!isset($decodedTuic['params']['alpn']) || is_null($decodedTuic['params']['alpn']) || $decodedTuic['params']['alpn'] === "") {
330
      unset($configResult['tls']["alpn"]);
331
    }
332
333
    return $configResult;
334
}
335
336
function Hy2Singbox($Hy2Url) {
337
    $decodedHy2 = ParseTuic($Hy2Url);
338
    if (
339
        is_null($decodedHy2['hash']) ||
340
        $decodedHy2['hash'] === ""
341
    ) {
342
        return null;
343
    }
344
345
    $configResult = [
346
        "tag" => $decodedHy2["hash"],
347
        "type" => "hysteria2",
348
        "server" => $decodedHy2['hostname'],
349
        "server_port" => intval($decodedHy2['port']),
350
        "up_mbps" => 0,
351
        "down_mbps" => 0,
352
        "password" => $decodedHy2['username'],
353
        "network" => "tcp",
354
    ];
355
356
357
    $configResult['obfs'] = [
358
        "type" => $decodedHy2['params']['obfs'],
359
        "password" => $decodedHy2['params']['obfs-password'],
360
    ];
361
    $configResult['tls'] = [
362
            "enabled" => true,
363
            "disable_sni" => isset($decodedHy2['params']['sni']) ? false : true,
364
            "server_name" => isset($decodedHy2['params']['sni']) ? $decodedHy2['params']['sni'] : "",
365
            "insecure" => isset($decodedHy2['params']['insecure']) && intval($decodedHy2['params']['insecure']) === 1 ? true : false,
366
            "alpn" => [
367
                "h3"
368
            ],
369
    ];
370
    /*if (!isset($decodedHy2['params']['alpn']) || is_null($decodedHy2['params']['alpn']) || $decodedHy2['params']['alpn'] === "") {
371
      unset($configResult['tls']["alpn"]);
372
    }*/
373
374
    return $configResult;
375
}
376
377
function GenerateConfig($input, $output, $theType){
378
    $outbound = [];
379
    $v2ray_subscription = str_replace(" ", "%20", $input);
380
381
    $configArray = explode("\n", $v2ray_subscription);
382
    foreach ($configArray as $config) {
383
        $configType = detect_type($config);
384
        $config = str_replace("%20", " ", $config);
385
        switch($configType) {
386
            case "vmess":
387
                $configSingbox = VmessSingbox($config);
388
                break;
389
            case "vless":
390
                $configSingbox = VlessSingbox($config);
391
                break;
392
            case "trojan":
393
                $configSingbox = TrojanSingbox($config);
394
                break;
395
            case "tuic":
396
                $configSingbox = TuicSingbox($config);
397
                break;
398
            case "hy2":
399
                $configSingbox = Hy2Singbox($config);
400
                break;
401
            case "ss":
402
                $configSingbox = ShadowsocksSingbox($config);
403
                break;
404
        }
405
        if (!is_null($configSingbox)){
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $configSingbox does not seem to be defined for all execution paths leading up to this point.
Loading history...
406
            $configName = $configSingbox['tag'];
407
            if (stripos($configName, "RELAY🚩")){
408
                $configLocation = "RELAY🚩";
409
            } else {
410
                $pattern = '/\b[A-Z]{2}\b[\x{1F1E6}-\x{1F1FF}]{2}/u';
411
                preg_match_all($pattern, $configName, $matches);
412
                $configLocation = $matches[0][0];
413
            }
414
            if (!in_array($configSingbox, $outbound[$configLocation])) {
415
                $outbound[$configLocation][] = $configSingbox;
416
            }
417
        }
418
    }
419
    $templateMap = [
420
        "nold" => "nekobox_1.1.7.json", 
421
        "nnew" => "nekobox_1.1.8.json", 
422
        "sfia" => "sfi.json"
423
    ];
424
    $templateBase = json_decode(
425
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
426
        true
427
    );
428
    $templateManual = json_decode(
429
        file_get_contents("modules/singbox/manual.json"), 
430
        true
431
    );
432
    $templateUrltest = json_decode(
433
        file_get_contents("modules/singbox/url_test.json"), 
434
        true
435
    );
436
    
437
    $outboundUrltest =[];
0 ignored issues
show
Unused Code introduced by
The assignment to $outboundUrltest is dead and can be removed.
Loading history...
438
    $outboundSingles = [];
439
    $locationNames = [];
440
    $outboundBasedOnLocationFull = [];
441
    foreach ($outbound as $location => $outboundEachLocation){
442
        $locationNames[] = $location;
443
        $eachLocationNames = extract_names($outboundEachLocation);
444
        $templateUrltest[0]['tag'] = $location;
445
        $outboundBasedOnLocation = process_jsons($templateUrltest, $eachLocationNames);
446
        $outboundBasedOnLocationFull = array_merge($outboundBasedOnLocationFull, $outboundBasedOnLocation);
447
        $outboundSingles = array_merge($outboundSingles, $outboundEachLocation);
448
    }
449
450
    $templateManual = process_jsons($templateManual, $locationNames);
451
    $templateUrltest[0]['tag'] = "URL-TEST | رایگان";
452
    $configNamesFull = extract_names($outboundSingles);
453
    $outboundUrltest = process_jsons($templateUrltest, $configNamesFull);
454
    $outboundUrltest = array_merge($outboundUrltest, $outboundBasedOnLocationFull);
455
456
    $templateBase['outbounds'] = array_merge($templateManual, $outboundUrltest, $outboundSingles,  $templateBase['outbounds']);
457
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
458
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
459
//profile-update-interval: 1
460
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
461
//support-url: https://t.me/v2raycollector
462
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
463
464
";
465
    $createJsonc = $headerText . $finalJson ;
466
    return $createJsonc;
467
}
468
469
function GenerateConfigLite($input, $output, $theType){
470
    $outbound = [];
471
    $v2ray_subscription = $input;
472
473
    $configArray = explode("\n", $v2ray_subscription);
474
    foreach ($configArray as $config) {
475
        $configType = detect_type($config);
476
        switch($configType) {
477
            case "vmess":
478
                $configSingbox = VmessSingbox($config);
479
                break;
480
            case "vless":
481
                $configSingbox = VlessSingbox($config);
482
                break;
483
            case "trojan":
484
                $configSingbox = TrojanSingbox($config);
485
                break;
486
            case "tuic":
487
                $configSingbox = TuicSingbox($config);
488
                break;
489
            case "hy2":
490
                $configSingbox = Hy2Singbox($config);
491
                break;
492
            case "ss":
493
                $configSingbox = ShadowsocksSingbox($config);
494
                break;
495
        }
496
        if (!is_null($configSingbox)){
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $configSingbox does not seem to be defined for all execution paths leading up to this point.
Loading history...
497
            if (!in_array($configSingbox, $outbound)) {
498
                $outbound[] = $configSingbox;
499
            }
500
        }
501
    }
502
    $templateMap = [
503
        "nold" => "nekobox_1.1.7.json", 
504
        "nnew" => "nekobox_1.1.8.json", 
505
        "sfia" => "sfi.json"
506
    ];
507
    $templateBase = json_decode(
508
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
509
        true
510
    );
511
    $templateManual = json_decode(
512
        file_get_contents("modules/singbox/manual.json"), 
513
        true
514
    );
515
    $templateUrltest = json_decode(
516
        file_get_contents("modules/singbox/url_test.json"), 
517
        true
518
    );
519
520
    $names = extract_names($outbound);
521
    $outboundManual = process_jsons($templateManual, $names);
522
    $outboundUrltest = process_jsons($templateUrltest, $names);
523
524
    $templateBase['outbounds'] = array_merge($outboundManual, $outboundUrltest, $outbound,  $templateBase['outbounds']);
525
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
526
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
527
//profile-update-interval: 1
528
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
529
//support-url: https://t.me/v2raycollector
530
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
531
532
";
533
    $createJsonc = $headerText . $finalJson ;
534
    return $createJsonc;
535
}
536