create-file.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // @ts-check
  2. import { readFileByLine } from './fetch-remote-text-by-line';
  3. import { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset } from './clash';
  4. export async function compareAndWriteFile(linesA: string[], filePath: string) {
  5. let isEqual = true;
  6. const file = Bun.file(filePath);
  7. const linesALen = linesA.length;
  8. if (!(await file.exists())) {
  9. console.log(`${filePath} does not exists, writing...`);
  10. isEqual = false;
  11. } else if (linesALen === 0) {
  12. console.log(`Nothing to write to ${filePath}...`);
  13. isEqual = false;
  14. } else {
  15. let index = 0;
  16. for await (const lineB of readFileByLine(file)) {
  17. const lineA = linesA[index];
  18. index++;
  19. if (typeof lineA !== 'string') {
  20. // The file becomes smaller
  21. isEqual = false;
  22. break;
  23. }
  24. if (lineA[0] === '#' && lineB[0] === '#') {
  25. continue;
  26. }
  27. if (lineA !== lineB) {
  28. isEqual = false;
  29. break;
  30. }
  31. }
  32. if (index !== linesALen) {
  33. // The file becomes larger
  34. isEqual = false;
  35. }
  36. }
  37. if (isEqual) {
  38. console.log(`Same Content, bail out writing: ${filePath}`);
  39. return;
  40. }
  41. const writer = file.writer();
  42. for (let i = 0; i < linesALen; i++) {
  43. writer.write(`${linesA[i]}\n`);
  44. }
  45. return writer.end();
  46. }
  47. export const withBannerArray = (title: string, description: string[], date: Date, content: string[]) => {
  48. return [
  49. '########################################',
  50. `# ${title}`,
  51. `# Last Updated: ${date.toISOString()}`,
  52. `# Size: ${content.length}`,
  53. ...description.map(line => (line ? `# ${line}` : '#')),
  54. '########################################',
  55. ...content,
  56. '################# END ###################'
  57. ];
  58. };
  59. export const createRuleset = (
  60. title: string, description: string[], date: Date, content: string[],
  61. type: 'ruleset' | 'domainset', surgePath: string, clashPath: string
  62. ) => {
  63. const surgeContent = withBannerArray(title, description, date, content);
  64. let _clashContent;
  65. switch (type) {
  66. case 'domainset':
  67. _clashContent = surgeDomainsetToClashDomainset(content);
  68. break;
  69. case 'ruleset':
  70. _clashContent = surgeRulesetToClashClassicalTextRuleset(content);
  71. break;
  72. default:
  73. throw new TypeError(`Unknown type: ${type as any}`);
  74. }
  75. const clashContent = withBannerArray(title, description, date, _clashContent);
  76. return [
  77. compareAndWriteFile(surgeContent, surgePath),
  78. compareAndWriteFile(clashContent, clashPath)
  79. ];
  80. };