Passed
Push — main ( 6ef1fc...e615cc )
by YeBeKhe
01:59
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;
29
}
30
31
function VmessSingbox($VmessUrl) {
32
    $decode_vmess = decode_vmess($VmessUrl);
33
    if (is_null($decode_vmess['ps']) || $decode_vmess['ps'] === ""){
34
        return null;
35
    }
36
    $configResult = array(
37
        "tag"=> $decode_vmess['ps'],
38
        "type"=> "vmess",
39
        "server"=> $decode_vmess['add'],
40
        "server_port"=> intval($decode_vmess['port']),
41
        "uuid"=> $decode_vmess['id'],
42
        "security"=> "auto",
43
        "alter_id"=> intval($decode_vmess['aid']),
44
        "global_padding"=> false,
45
        "authenticated_length"=> true,
46
        "packet_encoding"=> "",
47
        "multiplex"=> array(
48
          "enabled"=> false,
49
          "protocol"=> "smux",
50
          "max_streams"=> 32
51
        )
52
    );
53
54
    if ($decode_vmess['port'] === "443" || $decode_vmess['tls'] === "tls") {
55
        $configResult["tls"] = array(
56
            "enabled" => true,
57
            "server_name" => $decode_vmess['sni'] !== "" ? $decode_vmess['sni'] : $decode_vmess['add'],
58
            "insecure" => true,
59
            "disable_sni" => false,
60
            "utls"=> array(
61
                "enabled"=> true,
62
                "fingerprint"=> "chrome"
63
              )
64
        );
65
    }
66
67
    if ($decode_vmess['net'] === "ws") {
68
        $configResult["transport"] = array(
69
            "type" => $decode_vmess['net'],
70
            "path" => "/" . $decode_vmess['path'],
71
            "headers" => array(
72
                "Host" => $decode_vmess['host'] !== "" ? $decode_vmess['host'] : $decode_vmess['add'] !== "" ? $decode_vmess['add'] : ""
73
            ),
74
            "max_early_data" => 0,
75
            "early_data_header_name" => "Sec-WebSocket-Protocol"
76
        );
77
    } elseif ($decode_vmess['net'] === "grpc") {
78
        $configResult["transport"] = array(
79
            "type" => $decode_vmess['net'],
80
            "service_name" => $decode_vmess['path'],
81
            "idle_timeout" => "15s",
82
            "ping_timeout" => "15s",
83
            "permit_without_stream" => false
84
        );
85
    }
86
87
    return $configResult;
88
}
89
90
function VlessSingbox($VlessUrl)
91
{
92
    $decoded_vless = parseProxyUrl($VlessUrl, "vless");
93
    //print_r($decoded_vless);
94
    if (is_null($decoded_vless["hash"]) || $decoded_vless["hash"] === "") {
95
        return null;
96
    }
97
    $configResult = [
98
        "tag" => $decoded_vless["hash"],
99
        "type" => "vless",
100
        "server" => $decoded_vless["hostname"],
101
        "server_port" => intval($decoded_vless["port"]),
102
        "uuid" => $decoded_vless["username"],
103
        "flow" => !is_null($decoded_vless["params"]["flow"])
104
            ? "xtls-rprx-vision"
105
            : "",
106
        "packet_encoding" => "xudp",
107
        "multiplex" => [
108
            "enabled" => false,
109
            "protocol" => "smux",
110
            "max_streams" => 32,
111
        ],
112
    ];
113
114
    if (
115
        $decoded_vless["port"] === "443" ||
116
        $decoded_vless["params"]["security"] === "tls" ||
117
        $decoded_vless["params"]["security"] === "reality"
118
    ) {
119
        $configResult["tls"] = [
120
            "enabled" => true,
121
            "server_name" => !is_null($decoded_vless["params"]["sni"])
122
                ? $decoded_vless["params"]["sni"]
123
                : "",
124
            "insecure" => false,
125
            "utls" => [
126
                "enabled" => true,
127
                "fingerprint" => "chrome",
128
            ],
129
        ];
130
131
        if (
132
            $decoded_vless["params"]["security"] === "reality" ||
133
            isset($decoded_vless["params"]["pbk"])
134
        ) {
135
            $configResult["tls"]["reality"] = [
136
                "enabled" => true,
137
                "public_key" => !is_null($decoded_vless["params"]["pbk"])
138
                    ? $decoded_vless["params"]["pbk"]
139
                    : "",
140
                "short_id" => !is_null($decoded_vless["params"]["sid"])
141
                    ? $decoded_vless["params"]["sid"]
142
                    : "",
143
            ];
144
        if (
145
            is_null($decoded_vless["params"]["pbk"]) or
146
            $decoded_vless["params"]["pbk"] === ""
147
        ) {
148
            return null;
149
        }
150
        if (
151
            !isEvenLength($decoded_vless["params"]["sid"]) && 
152
            !is_null($decoded_vless["params"]["sid"])
153
           ) {
154
            return null;
155
        }
156
        }
157
    }
158
    $transportTypes = [
159
        "ws" => [
160
            "type" => $decoded_vless["params"]["type"],
161
            "path" => "/" . $decoded_vless["params"]["path"],
162
            "headers" => [
163
                "Host" => !is_null($decoded_vless["params"]["host"])
164
                    ? $decoded_vless["params"]["host"]
165
                    : "",
166
            ],
167
            "max_early_data" => 0,
168
            "early_data_header_name" => "Sec-WebSocket-Protocol",
169
        ],
170
        "grpc" => [
171
            "type" => $decoded_vless["params"]["type"],
172
            "service_name" => $decoded_vless["params"]["serviceName"],
173
            "idle_timeout" => "15s",
174
            "ping_timeout" => "15s",
175
            "permit_without_stream" => false,
176
        ],
177
    ];
178
    if (isset($decoded_vless["params"]["type"])) {
179
        if (
180
            $decoded_vless["params"]["type"] === "ws" ||
181
            $decoded_vless["params"]["type"] === "grpc"
182
        ) {
183
            $configResult["transport"] =
184
                $transportTypes[$decoded_vless["params"]["type"]];
185
        }
186
    }
187
    return $configResult;
188
}
189
190
function TrojanSingbox($TrojanUrl){
191
    $decoded_trojan = parseProxyUrl($TrojanUrl);
192
    if (is_null($decoded_trojan['hash']) || $decoded_trojan['hash'] === ""){
193
        return null;
194
    }
195
    $configResult = array(
196
        "tag"=> $decoded_trojan['hash'],
197
        "type"=> "trojan",
198
        "server"=> $decoded_trojan['hostname'],
199
        "server_port"=> intval($decoded_trojan['port']),
200
        "password"=> $decoded_trojan['username'],
201
        "multiplex"=> array(
202
          "enabled"=> false,
203
          "protocol"=> "smux",
204
          "max_streams"=> 32
205
        )
206
    );
207
208
    if ($decoded_trojan['port'] === "443" || $decoded_trojan['params']["security"] === "tls"){
209
        $configResult['tls'] = array(
210
            "enabled"=> true,
211
            "server_name"=> !is_null($decoded_trojan['params']['sni']) ? $decoded_trojan['params']['sni'] : "",
212
            "insecure"=> true,
213
            "utls"=> array(
214
                "enabled"=> true,
215
                "fingerprint"=> "chrome"
216
            )
217
        );
218
    }
219
220
    $transportTypes = array(
221
        "ws" => array(
222
            "type"=> $decoded_trojan['params']["type"],
223
            "path"=> "/" . $decoded_trojan['params']["path"],
224
            "headers"=> array(
225
                "Host"=> $decoded_trojan['params']["host"]
226
            )
227
          ),
228
          "grpc" => array(
229
            "type" => $decoded_trojan['params']["type"],
230
            "service_name" => $decoded_trojan['params']["serviceName"],
231
            "idle_timeout" => "15s",
232
            "ping_timeout" => "15s",
233
            "permit_without_stream" => false
234
          )
235
    );
236
    if (isset($decoded_trojan['params']["type"])){
237
        if ($decoded_trojan['params']["type"] === "ws" || $decoded_trojan['params']["type"] === "grpc"){
238
            $configResult["transport"] = $transportTypes[$decoded_trojan['params']["type"]];
239
        }
240
    }
241
    return $configResult;
242
}
243
244
function ShadowsocksSingbox($ShadowsocksUrl) {
245
    $decoded_shadowsocks = ParseShadowsocks($ShadowsocksUrl);
246
    if (is_null($decoded_shadowsocks['name']) || $decoded_shadowsocks['name'] === ""){
247
        return null;
248
    }
249
    $configResult = [
250
        'tag' => $decoded_shadowsocks['name'],
251
        'type' => "shadowsocks",
252
        'server' => $decoded_shadowsocks['server_address'],
253
        'server_port' => intval($decoded_shadowsocks['server_port']),
254
        'method' => $decoded_shadowsocks['encryption_method'],
255
        'password' => $decoded_shadowsocks['password'],
256
        'plugin' => "",
257
        'plugin_opts' => ""
258
    ];
259
    return $configResult;
260
}
261
262
function TuicSingbox($TuicUrl) {
263
    $decodedTuic = ParseTuic($TuicUrl);
264
    if (
265
        is_null($decodedTuic['hash']) ||
266
        $decodedTuic['hash'] === ""
267
    ) {
268
        return null;
269
    }
270
271
    $configResult = [
272
        "tag" => $decodedTuic["hash"],
273
        "type" => "tuic",
274
        "server" => $decodedTuic['hostname'],
275
        "server_port" => intval($decodedTuic['port']),
276
        "uuid" => $decodedTuic['username'],
277
        "password" => $decodedTuic['password'],
278
        "congestion_control" => $decodedTuic['params']['congestion_control'],
279
        "udp_relay_mode" => $decodedTuic['params']['udp_relay_mode'],
280
        "zero_rtt_handshake" => false,
281
        "heartbeat" => "10s",
282
        "network" => "tcp",
283
    ];
284
285
    $configResult['tls'] = [
286
            "enabled" => true,
287
            "disable_sni" => isset($decodedTuic['params']['sni']) ? false : true,
288
            "server_name" => isset($decodedTuic['params']['sni']) ? $decodedTuic['params']['sni'] : "",
289
            "insecure" => isset($decodedTuic['params']['allow_insecure']) && intval($decodedTuic['params']['allow_insecure']) === 1 ? true : false,
290
            "alpn" => [
291
                "h3",
292
                "spdy/3.1"
293
            ],
294
        ];
295
    if (!isset($decodedTuic['params']['alpn']) || is_null($decodedTuic['params']['alpn']) || $decodedTuic['params']['alpn'] === "") {
296
      unset($configResult['tls']["alpn"])
297
    }
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected '}', expecting ';' on line 297 at column 4
Loading history...
298
299
    return $configResult;
300
}
301
302
function GenerateConfig($input, $output, $theType){
303
    $outbound = [];
304
    $v2ray_subscription = str_replace(" ", "%20", $input);
305
306
    $configArray = explode("\n", $v2ray_subscription);
307
    foreach ($configArray as $config) {
308
        $configType = detect_type($config);
309
        $config = str_replace("%20", " ", $config);
310
        switch($configType) {
311
            case "vmess":
312
                $configSingbox = VmessSingbox($config);
313
                break;
314
            case "vless":
315
                $configSingbox = VlessSingbox($config);
316
                break;
317
            case "trojan":
318
                $configSingbox = TrojanSingbox($config);
319
                break;
320
            case "tuic":
321
                $configSingbox = TuicSingbox($config);
322
                break;
323
            case "ss":
324
                $configSingbox = ShadowsocksSingbox($config);
325
                break;
326
        }
327
        if (!is_null($configSingbox)){
328
            $configName = $configSingbox['tag'];
329
            if (stripos($configName, "RELAY🚩")){
330
                $configLocation = "RELAY🚩";
331
            } else {
332
                $pattern = '/\b[A-Z]{2}\b[\x{1F1E6}-\x{1F1FF}]{2}/u';
333
                preg_match_all($pattern, $configName, $matches);
334
                $configLocation = $matches[0][0];
335
            }
336
            if (!in_array($configSingbox, $outbound[$configLocation])) {
337
                $outbound[$configLocation][] = $configSingbox;
338
            }
339
        }
340
    }
341
    $templateMap = [
342
        "nold" => "nekobox_1.1.7.json", 
343
        "nnew" => "nekobox_1.1.8.json", 
344
        "sfia" => "sfi.json"
345
    ];
346
    $templateBase = json_decode(
347
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
348
        true
349
    );
350
    $templateManual = json_decode(
351
        file_get_contents("modules/singbox/manual.json"), 
352
        true
353
    );
354
    $templateUrltest = json_decode(
355
        file_get_contents("modules/singbox/url_test.json"), 
356
        true
357
    );
358
    
359
    $outboundUrltest =[];
360
    $outboundSingles = [];
361
    $locationNames = [];
362
    $outboundBasedOnLocationFull = [];
363
    foreach ($outbound as $location => $outboundEachLocation){
364
        $locationNames[] = $location;
365
        $eachLocationNames = extract_names($outboundEachLocation);
366
        $templateUrltest[0]['tag'] = $location;
367
        $outboundBasedOnLocation = process_jsons($templateUrltest, $eachLocationNames);
368
        $outboundBasedOnLocationFull = array_merge($outboundBasedOnLocationFull, $outboundBasedOnLocation);
369
        $outboundSingles = array_merge($outboundSingles, $outboundEachLocation);
370
    }
371
372
    $templateManual = process_jsons($templateManual, $locationNames);
373
    $templateUrltest[0]['tag'] = "URL-TEST | رایگان";
374
    $configNamesFull = extract_names($outboundSingles);
375
    $outboundUrltest = process_jsons($templateUrltest, $configNamesFull);
376
    $outboundUrltest = array_merge($outboundUrltest, $outboundBasedOnLocationFull);
377
378
    $templateBase['outbounds'] = array_merge($templateManual, $outboundUrltest, $outboundSingles,  $templateBase['outbounds']);
379
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
380
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
381
//profile-update-interval: 1
382
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
383
//support-url: https://t.me/v2raycollector
384
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
385
386
";
387
    $createJsonc = $headerText . $finalJson ;
388
    return $createJsonc;
389
}
390
391
function GenerateConfigLite($input, $output, $theType){
392
    $outbound = [];
393
    $v2ray_subscription = $input;
394
395
    $configArray = explode("\n", $v2ray_subscription);
396
    foreach ($configArray as $config) {
397
        $configType = detect_type($config);
398
        switch($configType) {
399
            case "vmess":
400
                $configSingbox = VmessSingbox($config);
401
                break;
402
            case "vless":
403
                $configSingbox = VlessSingbox($config);
404
                break;
405
            case "trojan":
406
                $configSingbox = TrojanSingbox($config);
407
                break;
408
            case "tuic":
409
                $configSingbox = TuicSingbox($config);
410
                break;
411
            case "ss":
412
                $configSingbox = ShadowsocksSingbox($config);
413
                break;
414
        }
415
        if (!is_null($configSingbox)){
416
            if (!in_array($configSingbox, $outbound)) {
417
                $outbound[] = $configSingbox;
418
            }
419
        }
420
    }
421
    $templateMap = [
422
        "nold" => "nekobox_1.1.7.json", 
423
        "nnew" => "nekobox_1.1.8.json", 
424
        "sfia" => "sfi.json"
425
    ];
426
    $templateBase = json_decode(
427
        file_get_contents("modules/singbox/" . $templateMap[$output]), 
428
        true
429
    );
430
    $templateManual = json_decode(
431
        file_get_contents("modules/singbox/manual.json"), 
432
        true
433
    );
434
    $templateUrltest = json_decode(
435
        file_get_contents("modules/singbox/url_test.json"), 
436
        true
437
    );
438
439
    $names = extract_names($outbound);
440
    $outboundManual = process_jsons($templateManual, $names);
441
    $outboundUrltest = process_jsons($templateUrltest, $names);
442
443
    $templateBase['outbounds'] = array_merge($outboundManual, $outboundUrltest, $outbound,  $templateBase['outbounds']);
444
    $finalJson = json_encode($templateBase, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
445
    $headerText = "//profile-title: base64:" . base64_encode("TVC | " . strtoupper($theType)) . "
446
//profile-update-interval: 1
447
//subscription-userinfo: upload=0; download=0; total=10737418240000000; expire=2546249531
448
//support-url: https://t.me/v2raycollector
449
//profile-web-page-url: https://github.com/yebekhe/TelegramV2rayCollector
450
451
";
452
    $createJsonc = $headerText . $finalJson ;
453
    return $createJsonc;
454
}
455