check.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import fs from "fs-extra";
  2. import zlib from "zlib";
  3. import path from "path";
  4. import AdmZip from "adm-zip";
  5. import fetch from "node-fetch";
  6. import { execSync } from "child_process";
  7. const cwd = process.cwd();
  8. const CLASH_URL_PREFIX =
  9. "https://github.com/Dreamacro/clash/releases/download/premium/";
  10. const CLASH_LATEST_DATE = "2022.01.27";
  11. /**
  12. * get the correct clash release infomation
  13. */
  14. function resolveClash() {
  15. const { platform, arch } = process;
  16. // todo
  17. const map = {
  18. "win32-x64": "clash-windows-386",
  19. "darwin-x64": "clash-darwin-amd64",
  20. "darwin-arm64": "clash-darwin-arm64",
  21. };
  22. const name = map[`${platform}-${arch}`];
  23. if (!name) {
  24. throw new Error(`unsupport platform "${platform}-${arch}"`);
  25. }
  26. const isWin = platform === "win32";
  27. const zip = isWin ? "zip" : "gz";
  28. const url = `${CLASH_URL_PREFIX}${name}-${CLASH_LATEST_DATE}.${zip}`;
  29. const exefile = `${name}${isWin ? ".exe" : ""}`;
  30. const zipfile = `${name}.${zip}`;
  31. return { url, zip, exefile, zipfile };
  32. }
  33. /**
  34. * get the sidecar bin
  35. */
  36. async function resolveSidecar() {
  37. const sidecarDir = path.join(cwd, "src-tauri", "sidecar");
  38. const host = execSync("rustc -vV | grep host").toString().slice(6).trim();
  39. const ext = process.platform === "win32" ? ".exe" : "";
  40. const sidecarFile = `clash-${host}${ext}`;
  41. const sidecarPath = path.join(sidecarDir, sidecarFile);
  42. await fs.mkdirp(sidecarDir);
  43. if (await fs.pathExists(sidecarPath)) return;
  44. // download sidecar
  45. const binInfo = resolveClash();
  46. const tempDir = path.join(cwd, "pre-dev-temp");
  47. const tempZip = path.join(tempDir, binInfo.zipfile);
  48. const tempExe = path.join(tempDir, binInfo.exefile);
  49. await fs.mkdirp(tempDir);
  50. if (!(await fs.pathExists(tempZip))) await downloadFile(binInfo.url, tempZip);
  51. if (binInfo.zip === "zip") {
  52. const zip = new AdmZip(tempZip);
  53. zip.getEntries().forEach((entry) => {
  54. console.log("[INFO]: entry name", entry.entryName);
  55. });
  56. zip.extractAllTo(tempDir, true);
  57. // save as sidecar
  58. await fs.rename(tempExe, sidecarPath);
  59. console.log(`[INFO]: unzip finished`);
  60. } else {
  61. // gz
  62. const readStream = fs.createReadStream(tempZip);
  63. const writeStream = fs.createWriteStream(sidecarPath);
  64. readStream
  65. .pipe(zlib.createGunzip())
  66. .pipe(writeStream)
  67. .on("finish", () => {
  68. console.log(`[INFO]: gunzip finished`);
  69. execSync(`chmod 755 ${sidecarPath}`);
  70. console.log(`[INFO]: chmod binary finished`);
  71. });
  72. }
  73. // delete temp dir
  74. await fs.remove(tempDir);
  75. }
  76. /**
  77. * get the Country.mmdb (not required)
  78. */
  79. async function resolveMmdb() {
  80. const url =
  81. "https://github.com/Dreamacro/maxmind-geoip/releases/latest/download/Country.mmdb";
  82. const resDir = path.join(cwd, "src-tauri", "resources");
  83. const resPath = path.join(resDir, "Country.mmdb");
  84. if (await fs.pathExists(resPath)) return;
  85. await fs.mkdirp(resDir);
  86. await downloadFile(url, resPath);
  87. }
  88. /**
  89. * download file and save to `path`
  90. */
  91. async function downloadFile(url, path) {
  92. console.log(`[INFO]: downloading from "${url}"`);
  93. const response = await fetch(url, {
  94. method: "GET",
  95. headers: { "Content-Type": "application/octet-stream" },
  96. });
  97. const buffer = await response.arrayBuffer();
  98. await fs.writeFile(path, new Uint8Array(buffer));
  99. console.log(`[INFO]: download finished "${url}"`);
  100. }
  101. /// main
  102. resolveSidecar().catch(console.error);
  103. resolveMmdb().catch(console.error);