Passed
Push — main ( 72b417...516af1 )
by YeBeKhe
02:02
created

process_jsons()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
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 GenerateConfig($input, $output, $theType){
337
    $outbound = [];
338
    $v2ray_subscription = str_replace(" ", "%20", $input);
339
340
    $configArray = explode("\n", $v2ray_subscription);
341
    foreach ($configArray as $config) {
342
        $configType = detect_type($config);
343
        $config = str_replace("%20", " ", $config);
344
        switch($configType) {
345
            case "vmess":
346
                $configSingbox = VmessSingbox($config);
347
                break;
348
            case "vless":
349
                $configSingbox = VlessSingbox($config);
350
                break;
351
            case "trojan":
352
                $configSingbox = TrojanSingbox($config);
353
                break;
354
            case "tuic":
355
                $configSingbox = TuicSingbox($config);
356
                break;
357
            case "ss":
358
                $configSingbox = ShadowsocksSingbox($config);
359
                break;
360
        }
361
        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...
362
            $configName = $configSingbox['tag'];
363
            if (stripos($configName, "RELAY🚩")){
364
                $configLocation = "RELAY🚩";
365
            } else {
366
                $pattern = '/\b[A-Z]{2}\b[\x{1F1E6}-\x{1F1FF}]{2}/u';
367
                preg_match_all($pattern, $configName, $matches);
368
                $configLocation = $matches[0][0];
369
            }
370
            if (!in_array($configSingbox, $outbound[$configLocation])) {
371
                $outbound[$configLocation][] = $configSingbox;
372
            }
373
        }
374
    }
375
    $templateMap = [
376
        "nold" => "nekobox_1.1.7.json", 
377
        "nnew" => "nekobox_1.1.8.json", 
378
        "sfia" => "sfi.json"
379
    ];
380
    $templateBase = json_decode(
381
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
382
        true
383
    );
384
    $templateManual = json_decode(
385
        file_get_contents("modules/singbox/manual.json"), 
386
        true
387
    );
388
    $templateUrltest = json_decode(
389
        file_get_contents("modules/singbox/url_test.json"), 
390
        true
391
    );
392
    
393
    $outboundUrltest =[];
0 ignored issues
show
Unused Code introduced by
The assignment to $outboundUrltest is dead and can be removed.
Loading history...
394
    $outboundSingles = [];
395
    $locationNames = [];
396
    $outboundBasedOnLocationFull = [];
397
    foreach ($outbound as $location => $outboundEachLocation){
398
        $locationNames[] = $location;
399
        $eachLocationNames = extract_names($outboundEachLocation);
400
        $templateUrltest[0]['tag'] = $location;
401
        $outboundBasedOnLocation = process_jsons($templateUrltest, $eachLocationNames);
402
        $outboundBasedOnLocationFull = array_merge($outboundBasedOnLocationFull, $outboundBasedOnLocation);
403
        $outboundSingles = array_merge($outboundSingles, $outboundEachLocation);
404
    }
405
406
    $templateManual = process_jsons($templateManual, $locationNames);
407
    $templateUrltest[0]['tag'] = "URL-TEST | رایگان";
408
    $configNamesFull = extract_names($outboundSingles);
409
    $outboundUrltest = process_jsons($templateUrltest, $configNamesFull);
410
    $outboundUrltest = array_merge($outboundUrltest, $outboundBasedOnLocationFull);
411
412
    $templateBase['outbounds'] = array_merge($templateManual, $outboundUrltest, $outboundSingles,  $templateBase['outbounds']);
413
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
414
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
415
//profile-update-interval: 1
416
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
417
//support-url: https://t.me/v2raycollector
418
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
419
420
";
421
    $createJsonc = $headerText . $finalJson ;
422
    return $createJsonc;
423
}
424
425
function GenerateConfigLite($input, $output, $theType){
426
    $outbound = [];
427
    $v2ray_subscription = $input;
428
429
    $configArray = explode("\n", $v2ray_subscription);
430
    foreach ($configArray as $config) {
431
        $configType = detect_type($config);
432
        switch($configType) {
433
            case "vmess":
434
                $configSingbox = VmessSingbox($config);
435
                break;
436
            case "vless":
437
                $configSingbox = VlessSingbox($config);
438
                break;
439
            case "trojan":
440
                $configSingbox = TrojanSingbox($config);
441
                break;
442
            case "tuic":
443
                $configSingbox = TuicSingbox($config);
444
                break;
445
            case "ss":
446
                $configSingbox = ShadowsocksSingbox($config);
447
                break;
448
        }
449
        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...
450
            if (!in_array($configSingbox, $outbound)) {
451
                $outbound[] = $configSingbox;
452
            }
453
        }
454
    }
455
    $templateMap = [
456
        "nold" => "nekobox_1.1.7.json", 
457
        "nnew" => "nekobox_1.1.8.json", 
458
        "sfia" => "sfi.json"
459
    ];
460
    $templateBase = json_decode(
461
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
462
        true
463
    );
464
    $templateManual = json_decode(
465
        file_get_contents("modules/singbox/manual.json"), 
466
        true
467
    );
468
    $templateUrltest = json_decode(
469
        file_get_contents("modules/singbox/url_test.json"), 
470
        true
471
    );
472
473
    $names = extract_names($outbound);
474
    $outboundManual = process_jsons($templateManual, $names);
475
    $outboundUrltest = process_jsons($templateUrltest, $names);
476
477
    $templateBase['outbounds'] = array_merge($outboundManual, $outboundUrltest, $outbound,  $templateBase['outbounds']);
478
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
479
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
480
//profile-update-interval: 1
481
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
482
//support-url: https://t.me/v2raycollector
483
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
484
485
";
486
    $createJsonc = $headerText . $finalJson ;
487
    return $createJsonc;
488
}
489