Passed
Push — main ( 58049a...e785aa )
by YeBeKhe
02:15
created

VmessSingbox()   B

Complexity

Conditions 11
Paths 11

Size

Total Lines 65
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
eloc 50
c 2
b 0
f 0
nc 11
nop 1
dl 0
loc 65
rs 7.3166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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