Clash.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. <?php
  2. /*
  3. * Developed based on
  4. * https://clash.wiki/configuration/configuration-reference.html
  5. * https://docs.gtk.pw/contents/urlscheme.html#%E4%B8%8B%E8%BD%BD%E9%85%8D%E7%BD%AE
  6. */
  7. namespace App\Utils\Clients;
  8. use App\Models\User;
  9. use App\Utils\Library\Templates\Client;
  10. use File;
  11. use Symfony\Component\Yaml\Yaml;
  12. class Clash implements Client
  13. {
  14. public const AGENT = ['clash', 'stash', 'bob_vpn'];
  15. public function getConfig(array $servers, User $user, string $target): array|string
  16. {
  17. $custom_path = '/resources/rules/custom.clash.yaml';
  18. if (str_contains($target, 'bob_vpn')) {
  19. $file_path = '/resources/rules/bob.clash.yaml';
  20. } elseif (File::exists(base_path().$custom_path)) {
  21. $file_path = $custom_path;
  22. } else {
  23. $file_path = '/resources/rules/default.clash.yaml';
  24. }
  25. $appName = sysConfig('website_name');
  26. header("content-disposition:attachment;filename*=UTF-8''".rawurlencode($appName).'.yaml');
  27. header('profile-update-interval: 24');
  28. header('profile-web-page-url:'.sysConfig('website_url'));
  29. if (sysConfig('is_custom_subscribe')) {
  30. // display remaining traffic and expire date
  31. header("subscription-userinfo: upload=$user->u; download=$user->d; total=$user->transfer_enable; expire=".strtotime($user->expired_at));
  32. }
  33. $config = Yaml::parseFile(base_path().$file_path);
  34. // 按照核心区分配置
  35. if (str_contains($target, 'clashforwindows') || str_contains($target, 'clashforandroid') || str_contains($target, 'clashx')) {
  36. $proxyProfiles = Formatters\Clash::build($servers);
  37. } elseif (str_contains($target, 'stash')) {
  38. $proxyProfiles = Formatters\Stash::build($servers);
  39. } else {
  40. $proxyProfiles = Formatters\ClashMeta::build($servers);
  41. }
  42. $config['proxies'] = array_merge($config['proxies'] ?: [], $proxyProfiles['proxies']);
  43. $names = array_column($config['proxies'], 'name');
  44. foreach ($config['proxy-groups'] as $k => $v) {
  45. if (! is_array($config['proxy-groups'][$k]['proxies'])) {
  46. continue;
  47. }
  48. $config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $names);
  49. }
  50. array_unshift($config['rules'], 'DOMAIN,'.$_SERVER['HTTP_HOST'].',DIRECT'); // Set current sub-domain to be direct
  51. return str_replace('$app_name', $appName, Yaml::dump($config, 2, 4, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE));
  52. }
  53. }