fluncle 0.72.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.
- package/bin/fluncle.mjs +122 -149
- 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.
|
|
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 =
|
|
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 =
|
|
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:
|
|
2395
|
-
name:
|
|
2396
|
-
userId:
|
|
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.
|
|
2596
|
+
currentVersion2 = "0.73.0".trim() ? "0.73.0".trim() : "0.1.0";
|
|
2563
2597
|
});
|
|
2564
2598
|
|
|
2565
2599
|
// ../../packages/registry/src/index.ts
|
|
@@ -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