fluncle 0.71.0 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +123 -150
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -380,6 +380,107 @@ function formatError(error) {
380
380
  }
381
381
  return String(error);
382
382
  }
383
+ function parseDuration(input) {
384
+ const trimmed = input.trim();
385
+ if (!trimmed) {
386
+ return null;
387
+ }
388
+ if (trimmed.includes(":")) {
389
+ const parts = trimmed.split(":");
390
+ if (parts.length !== 2 && parts.length !== 3) {
391
+ return null;
392
+ }
393
+ const nums = parts.map((part) => Number(part));
394
+ if (nums.some((n) => !Number.isFinite(n) || n < 0)) {
395
+ return null;
396
+ }
397
+ if (parts.length === 3) {
398
+ const [hours, minutes2, seconds2] = nums;
399
+ if (hours === undefined || minutes2 === undefined || seconds2 === undefined) {
400
+ return null;
401
+ }
402
+ if (minutes2 >= 60 || seconds2 >= 60) {
403
+ return null;
404
+ }
405
+ return Math.round((hours * 3600 + minutes2 * 60 + seconds2) * 1000);
406
+ }
407
+ const [minutes, seconds] = nums;
408
+ if (minutes === undefined || seconds === undefined) {
409
+ return null;
410
+ }
411
+ if (seconds >= 60) {
412
+ return null;
413
+ }
414
+ return Math.round((minutes * 60 + seconds) * 1000);
415
+ }
416
+ const value = Number(trimmed);
417
+ return Number.isFinite(value) && value >= 0 ? value : null;
418
+ }
419
+ function isRemix(title) {
420
+ return REMIX_MARKER.test(title);
421
+ }
422
+ function stripVersionSuffix(title) {
423
+ const parts = title.split(/\s+-\s+/);
424
+ if (parts.length > 1 && VERSION_MARKER.test(parts[parts.length - 1] ?? "")) {
425
+ return parts.slice(0, -1).join(" - ").trim();
426
+ }
427
+ return title.trim();
428
+ }
429
+ function tokenize(value) {
430
+ return value.toLowerCase().normalize("NFKD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, " ").trim().split(" ").filter(Boolean);
431
+ }
432
+ function versionTokens(title) {
433
+ const parts = title.split(/\s+-\s+/);
434
+ const tail = parts.length > 1 ? parts[parts.length - 1] ?? "" : "";
435
+ if (parts.length > 1 && VERSION_MARKER.test(tail)) {
436
+ return new Set(tokenize(tail));
437
+ }
438
+ const bracketed = /[([]([^)\]]*?)[)\]]/.exec(title);
439
+ if (bracketed?.[1] && VERSION_MARKER.test(bracketed[1])) {
440
+ return new Set(tokenize(bracketed[1]));
441
+ }
442
+ return new Set;
443
+ }
444
+ function versionMatches(findingTitle, candidateTitle) {
445
+ const findingIsRemix = isRemix(findingTitle);
446
+ const candidateIsRemix = isRemix(candidateTitle);
447
+ if (findingIsRemix) {
448
+ if (!candidateIsRemix) {
449
+ return false;
450
+ }
451
+ const want = [...versionTokens(findingTitle)].filter((t) => !VERSION_STOPWORDS.has(t));
452
+ if (want.length === 0) {
453
+ return true;
454
+ }
455
+ const have = versionTokens(candidateTitle);
456
+ for (const token of want) {
457
+ if (!have.has(token)) {
458
+ return false;
459
+ }
460
+ }
461
+ return true;
462
+ }
463
+ return !candidateIsRemix;
464
+ }
465
+ function baseTitleMatches(findingTitle, candidateTitle) {
466
+ const want = new Set(tokenize(stripVersionSuffix(findingTitle)));
467
+ const have = new Set(tokenize(stripVersionSuffix(candidateTitle)));
468
+ if (want.size === 0) {
469
+ return false;
470
+ }
471
+ for (const token of want) {
472
+ if (!have.has(token)) {
473
+ return false;
474
+ }
475
+ }
476
+ return true;
477
+ }
478
+ var VERSION_MARKER, REMIX_MARKER, VERSION_STOPWORDS;
479
+ var init_util = __esm(() => {
480
+ VERSION_MARKER = /\b(mix|edit|version|remix|dub|vip|bootleg|rework|re-?edit|flip|refix|remaster(?:ed)?|instrumental)\b/i;
481
+ REMIX_MARKER = /\b(remix|bootleg|vip|rework|re-?edit|flip|refix)\b/i;
482
+ VERSION_STOPWORDS = new Set(["mix", "the", "and", "feat", "ft", "edit", "version", "remix"]);
483
+ });
383
484
 
384
485
  // src/output.ts
385
486
  function isJsonFailure(value) {
@@ -423,7 +524,7 @@ function parseVersion(version) {
423
524
  var currentVersion;
424
525
  var init_version = __esm(() => {
425
526
  init_output();
426
- currentVersion = "0.71.0".trim() ? "0.71.0".trim() : "0.1.0";
527
+ currentVersion = "0.73.0".trim() ? "0.73.0".trim() : "0.1.0";
427
528
  });
428
529
 
429
530
  // src/update-notifier.ts
@@ -1431,43 +1532,8 @@ function parseCueSheet(text) {
1431
1532
  }
1432
1533
  return entries;
1433
1534
  }
1434
- function parseDuration(input) {
1435
- const trimmed = input.trim();
1436
- if (!trimmed) {
1437
- return null;
1438
- }
1439
- if (trimmed.includes(":")) {
1440
- const parts = trimmed.split(":");
1441
- if (parts.length !== 2 && parts.length !== 3) {
1442
- return null;
1443
- }
1444
- const nums = parts.map((part) => Number(part));
1445
- if (nums.some((n) => !Number.isFinite(n) || n < 0)) {
1446
- return null;
1447
- }
1448
- if (parts.length === 3) {
1449
- const [hours, minutes2, seconds2] = nums;
1450
- if (hours === undefined || minutes2 === undefined || seconds2 === undefined) {
1451
- return null;
1452
- }
1453
- if (minutes2 >= 60 || seconds2 >= 60) {
1454
- return null;
1455
- }
1456
- return Math.round((hours * 3600 + minutes2 * 60 + seconds2) * 1000);
1457
- }
1458
- const [minutes, seconds] = nums;
1459
- if (minutes === undefined || seconds === undefined) {
1460
- return null;
1461
- }
1462
- if (seconds >= 60) {
1463
- return null;
1464
- }
1465
- return Math.round((minutes * 60 + seconds) * 1000);
1466
- }
1467
- const value = Number(trimmed);
1468
- return Number.isFinite(value) && value >= 0 ? value : null;
1469
- }
1470
1535
  var init_mixtapes = __esm(() => {
1536
+ init_util();
1471
1537
  init_api();
1472
1538
  init_output();
1473
1539
  });
@@ -1765,7 +1831,7 @@ function buildBody2(options) {
1765
1831
  body.soundcloudUrl = options.soundcloudUrl;
1766
1832
  }
1767
1833
  if (options.durationMs !== undefined) {
1768
- const parsed = parseDuration2(options.durationMs);
1834
+ const parsed = parseDuration(options.durationMs);
1769
1835
  if (parsed === null) {
1770
1836
  throw new CliError2("invalid_duration", "Duration must be mm:ss or h:mm:ss, or a millisecond count");
1771
1837
  }
@@ -1821,7 +1887,7 @@ function parseCueSheet2(text) {
1821
1887
  if (time === undefined || ref === undefined) {
1822
1888
  continue;
1823
1889
  }
1824
- const startMs = parseDuration2(time);
1890
+ const startMs = parseDuration(time);
1825
1891
  if (startMs === null) {
1826
1892
  continue;
1827
1893
  }
@@ -1832,43 +1898,8 @@ function parseCueSheet2(text) {
1832
1898
  }
1833
1899
  return entries;
1834
1900
  }
1835
- function parseDuration2(input) {
1836
- const trimmed = input.trim();
1837
- if (!trimmed) {
1838
- return null;
1839
- }
1840
- if (trimmed.includes(":")) {
1841
- const parts = trimmed.split(":");
1842
- if (parts.length !== 2 && parts.length !== 3) {
1843
- return null;
1844
- }
1845
- const nums = parts.map((part) => Number(part));
1846
- if (nums.some((n) => !Number.isFinite(n) || n < 0)) {
1847
- return null;
1848
- }
1849
- if (parts.length === 3) {
1850
- const [hours, minutes2, seconds2] = nums;
1851
- if (hours === undefined || minutes2 === undefined || seconds2 === undefined) {
1852
- return null;
1853
- }
1854
- if (minutes2 >= 60 || seconds2 >= 60) {
1855
- return null;
1856
- }
1857
- return Math.round((hours * 3600 + minutes2 * 60 + seconds2) * 1000);
1858
- }
1859
- const [minutes, seconds] = nums;
1860
- if (minutes === undefined || seconds === undefined) {
1861
- return null;
1862
- }
1863
- if (seconds >= 60) {
1864
- return null;
1865
- }
1866
- return Math.round((minutes * 60 + seconds) * 1000);
1867
- }
1868
- const value = Number(trimmed);
1869
- return Number.isFinite(value) && value >= 0 ? value : null;
1870
- }
1871
1901
  var init_mixtapes2 = __esm(() => {
1902
+ init_util();
1872
1903
  init_api();
1873
1904
  init_output();
1874
1905
  });
@@ -1881,7 +1912,9 @@ function artistTitle(track) {
1881
1912
  return `${track.artists.join(", ")} — ${track.title}`;
1882
1913
  }
1883
1914
  var COORD_FALLBACK = "—";
1884
- var init_format = () => {};
1915
+ var init_format = __esm(() => {
1916
+ init_util();
1917
+ });
1885
1918
 
1886
1919
  // src/interactive.ts
1887
1920
  import { createInterface } from "node:readline/promises";
@@ -2388,12 +2421,13 @@ async function meCommand() {
2388
2421
  if (!me.user) {
2389
2422
  throw new Error("Your sign-in expired. Run `fluncle login` to link this device again.");
2390
2423
  }
2424
+ const user = me.user;
2391
2425
  return {
2392
2426
  collectedCount: progress.collectedLogIds.length,
2393
2427
  deaths: progress.deaths,
2394
- joinedAt: me.user.createdAt,
2395
- name: me.user.displayUsername ?? me.user.username ?? "cosmonaut",
2396
- userId: me.user.id,
2428
+ joinedAt: user.createdAt,
2429
+ name: user.displayUsername ?? user.username ?? "cosmonaut",
2430
+ userId: user.id,
2397
2431
  wins: progress.wins
2398
2432
  };
2399
2433
  }
@@ -2559,7 +2593,7 @@ function parseVersion2(version) {
2559
2593
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2560
2594
  var init_version2 = __esm(() => {
2561
2595
  init_output();
2562
- currentVersion2 = "0.71.0".trim() ? "0.71.0".trim() : "0.1.0";
2596
+ currentVersion2 = "0.73.0".trim() ? "0.73.0".trim() : "0.1.0";
2563
2597
  });
2564
2598
 
2565
2599
  // ../../packages/registry/src/index.ts
@@ -2745,7 +2779,7 @@ var init_src = __esm(() => {
2745
2779
  ],
2746
2780
  kind: "subdomain",
2747
2781
  name: "subdomain.onion",
2748
- operatorNotes: "An onionspray mirror. Advertised via Tor Browser's Onion-Location pill. Probed on /status as service `onion`. Runbook: docs/tor.md.",
2782
+ operatorNotes: "An onionspray mirror. Advertised via Tor Browser's Onion-Location pill. Probed on /status as service `onion`.",
2749
2783
  probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2750
2784
  subdomain: "p53pc2uzfu2tnih4cd6wd42ok6zup2uttj6xdmjdccy5kqo33fyppkqd.onion",
2751
2785
  url: "http://p53pc2uzfu2tnih4cd6wd42ok6zup2uttj6xdmjdccy5kqo33fyppkqd.onion",
@@ -3581,73 +3615,6 @@ var init_admin_tracks = __esm(() => {
3581
3615
  init_recent2();
3582
3616
  });
3583
3617
 
3584
- // src/version-match.ts
3585
- function isRemix(title) {
3586
- return REMIX_MARKER.test(title);
3587
- }
3588
- function stripVersionSuffix(title) {
3589
- const parts = title.split(/\s+-\s+/);
3590
- if (parts.length > 1 && VERSION_MARKER.test(parts[parts.length - 1] ?? "")) {
3591
- return parts.slice(0, -1).join(" - ").trim();
3592
- }
3593
- return title.trim();
3594
- }
3595
- function tokenize(value) {
3596
- return value.toLowerCase().normalize("NFKD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, " ").trim().split(" ").filter(Boolean);
3597
- }
3598
- function versionTokens(title) {
3599
- const parts = title.split(/\s+-\s+/);
3600
- const tail = parts.length > 1 ? parts[parts.length - 1] ?? "" : "";
3601
- if (parts.length > 1 && VERSION_MARKER.test(tail)) {
3602
- return new Set(tokenize(tail));
3603
- }
3604
- const bracketed = /[([]([^)\]]*?)[)\]]/.exec(title);
3605
- if (bracketed?.[1] && VERSION_MARKER.test(bracketed[1])) {
3606
- return new Set(tokenize(bracketed[1]));
3607
- }
3608
- return new Set;
3609
- }
3610
- function versionMatches(findingTitle, candidateTitle) {
3611
- const findingIsRemix = isRemix(findingTitle);
3612
- const candidateIsRemix = isRemix(candidateTitle);
3613
- if (findingIsRemix) {
3614
- if (!candidateIsRemix) {
3615
- return false;
3616
- }
3617
- const want = [...versionTokens(findingTitle)].filter((t) => !VERSION_STOPWORDS.has(t));
3618
- if (want.length === 0) {
3619
- return true;
3620
- }
3621
- const have = versionTokens(candidateTitle);
3622
- for (const token of want) {
3623
- if (!have.has(token)) {
3624
- return false;
3625
- }
3626
- }
3627
- return true;
3628
- }
3629
- return !candidateIsRemix;
3630
- }
3631
- function baseTitleMatches(findingTitle, candidateTitle) {
3632
- const want = new Set(tokenize(stripVersionSuffix(findingTitle)));
3633
- const have = new Set(tokenize(stripVersionSuffix(candidateTitle)));
3634
- if (want.size === 0) {
3635
- return false;
3636
- }
3637
- for (const token of want) {
3638
- if (!have.has(token)) {
3639
- return false;
3640
- }
3641
- }
3642
- return true;
3643
- }
3644
- var VERSION_MARKER, REMIX_MARKER, VERSION_STOPWORDS;
3645
- var init_version_match = __esm(() => {
3646
- VERSION_MARKER = /\b(mix|edit|version|remix|dub|vip|bootleg|rework|re-?edit|flip|refix|remaster(?:ed)?|instrumental)\b/i;
3647
- REMIX_MARKER = /\b(remix|bootleg|vip|rework|re-?edit|flip|refix)\b/i;
3648
- VERSION_STOPWORDS = new Set(["mix", "the", "and", "feat", "ft", "edit", "version", "remix"]);
3649
- });
3650
-
3651
3618
  // src/commands/preview-archive.ts
3652
3619
  var exports_preview_archive = {};
3653
3620
  __export(exports_preview_archive, {
@@ -3844,8 +3811,8 @@ function normalize(value) {
3844
3811
  }
3845
3812
  var DURATION_TOLERANCE_S = 5;
3846
3813
  var init_preview_archive = __esm(() => {
3814
+ init_util();
3847
3815
  init_api();
3848
- init_version_match();
3849
3816
  });
3850
3817
 
3851
3818
  // src/commands/mixtape-youtube.ts
@@ -4854,7 +4821,9 @@ function trackDetailLines(track) {
4854
4821
  return lines;
4855
4822
  }
4856
4823
  var COORD_FALLBACK2 = "—";
4857
- var init_format2 = () => {};
4824
+ var init_format2 = __esm(() => {
4825
+ init_util();
4826
+ });
4858
4827
 
4859
4828
  // src/cli.ts
4860
4829
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
@@ -6966,6 +6935,10 @@ function toJsonFailure(error) {
6966
6935
  ok: false
6967
6936
  };
6968
6937
  }
6938
+
6939
+ // src/retry.ts
6940
+ init_util();
6941
+
6969
6942
  // src/cli.ts
6970
6943
  function createProgram() {
6971
6944
  const program2 = configureCommand(new Command);
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.71.0"
34
+ "version": "0.73.0"
35
35
  }