create-file.ts 2.4 KB

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