fluncle 0.237.0 → 0.239.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 +42 -15
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -622,7 +622,7 @@ function parseVersion(version) {
|
|
|
622
622
|
var currentVersion;
|
|
623
623
|
var init_version = __esm(() => {
|
|
624
624
|
init_output();
|
|
625
|
-
currentVersion = "0.
|
|
625
|
+
currentVersion = "0.239.0".trim() ? "0.239.0".trim() : "0.1.0";
|
|
626
626
|
});
|
|
627
627
|
|
|
628
628
|
// src/update-notifier.ts
|
|
@@ -2335,7 +2335,7 @@ function parseVersion2(version) {
|
|
|
2335
2335
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2336
2336
|
var init_version2 = __esm(() => {
|
|
2337
2337
|
init_output();
|
|
2338
|
-
currentVersion2 = "0.
|
|
2338
|
+
currentVersion2 = "0.239.0".trim() ? "0.239.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -10415,11 +10415,12 @@ var init_admin_artifacts = __esm(() => {
|
|
|
10415
10415
|
});
|
|
10416
10416
|
|
|
10417
10417
|
// ../../packages/contracts/src/orpc/admin-artist-rules.ts
|
|
10418
|
-
var ArtistRuleVerdictSchema, ArtistRuleSourceSchema, ArtistMbidSchema, ArtistNameSchema, ArtistRuleSchema, ArtistRuleInputSchema, AddArtistRuleInputSchema, listArtistRules, addArtistRule, updateArtistRule, removeArtistRule, adminArtistRulesContract;
|
|
10418
|
+
var ArtistRuleVerdictSchema, LabelArtistRuleVerdictSchema, ArtistRuleSourceSchema, ArtistMbidSchema, ArtistNameSchema, ArtistRuleSchema, ArtistRuleInputSchema, AddArtistRuleInputSchema, listArtistRules, addArtistRule, updateArtistRule, removeArtistRule, adminArtistRulesContract;
|
|
10419
10419
|
var init_admin_artist_rules = __esm(() => {
|
|
10420
10420
|
init_dist3();
|
|
10421
10421
|
init_zod();
|
|
10422
|
-
ArtistRuleVerdictSchema = _enum(["allow", "block"]).meta({ id: "ArtistRuleVerdict" });
|
|
10422
|
+
ArtistRuleVerdictSchema = _enum(["allow", "block", "unlisted"]).meta({ id: "ArtistRuleVerdict" });
|
|
10423
|
+
LabelArtistRuleVerdictSchema = _enum(["allow", "block"]).meta({ id: "LabelArtistRuleVerdict" });
|
|
10423
10424
|
ArtistRuleSourceSchema = _enum(["operator", "triage"]).meta({ id: "ArtistRuleSource" });
|
|
10424
10425
|
ArtistMbidSchema = string2().uuid();
|
|
10425
10426
|
ArtistNameSchema = string2().trim().min(1, "Artist name cannot be blank");
|
|
@@ -10438,10 +10439,11 @@ var init_admin_artist_rules = __esm(() => {
|
|
|
10438
10439
|
ArtistRuleInputSchema = object({
|
|
10439
10440
|
artistMbid: ArtistMbidSchema,
|
|
10440
10441
|
artistName: ArtistNameSchema,
|
|
10441
|
-
verdict:
|
|
10442
|
+
verdict: LabelArtistRuleVerdictSchema
|
|
10442
10443
|
}).meta({ id: "ArtistRuleInput" });
|
|
10443
10444
|
AddArtistRuleInputSchema = ArtistRuleInputSchema.extend({
|
|
10444
|
-
artistName: ArtistNameSchema.optional()
|
|
10445
|
+
artistName: ArtistNameSchema.optional(),
|
|
10446
|
+
verdict: ArtistRuleVerdictSchema
|
|
10445
10447
|
}).meta({ id: "AddArtistRuleInput" });
|
|
10446
10448
|
listArtistRules = oc.route({
|
|
10447
10449
|
method: "GET",
|
|
@@ -11433,7 +11435,7 @@ var init_admin_bios = __esm(() => {
|
|
|
11433
11435
|
});
|
|
11434
11436
|
|
|
11435
11437
|
// ../../packages/contracts/src/orpc/admin-catalogue.ts
|
|
11436
|
-
var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, requeueIsrcRecovery, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, MAX_CRAWL_PREPARE_LIMIT = 6, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, crawlCatalogue, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, SpotifyAnchorBreakerStateSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
11438
|
+
var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, requeueIsrcRecovery, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, MAX_CRAWL_PREPARE_LIMIT = 6, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, crawlCatalogue, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
11437
11439
|
var init_admin_catalogue = __esm(() => {
|
|
11438
11440
|
init_dist3();
|
|
11439
11441
|
init_zod();
|
|
@@ -11839,7 +11841,9 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11839
11841
|
source: _enum(["listenbrainz", "spotify-isrc", "spotify-search"]).nullable(),
|
|
11840
11842
|
spotifyIsrcAsked: boolean2(),
|
|
11841
11843
|
spotifySearchDone: boolean2(),
|
|
11844
|
+
spotifySearchEnabled: boolean2(),
|
|
11842
11845
|
spotifyThrottled: boolean2(),
|
|
11846
|
+
stamped: boolean2(),
|
|
11843
11847
|
verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
|
|
11844
11848
|
}));
|
|
11845
11849
|
resolveAnchorReview = oc.route({
|
|
@@ -11908,13 +11912,17 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11908
11912
|
tripped: boolean2(),
|
|
11909
11913
|
trippedAt: string2().nullable()
|
|
11910
11914
|
}).meta({ id: "SpotifyAnchorBreakerState" });
|
|
11915
|
+
AnchorRungFlagsSchema = object({
|
|
11916
|
+
apifyEnabled: boolean2(),
|
|
11917
|
+
spotifySearchEnabled: boolean2()
|
|
11918
|
+
}).meta({ id: "AnchorRungFlags" });
|
|
11911
11919
|
getSpotifyAnchorBreaker = oc.route({
|
|
11912
11920
|
method: "GET",
|
|
11913
11921
|
operationId: "getSpotifyAnchorBreaker",
|
|
11914
11922
|
path: "/admin/catalogue/anchor/breaker",
|
|
11915
|
-
summary: "The Spotify anchor-search throttle breaker: tripped, why,
|
|
11923
|
+
summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
|
|
11916
11924
|
tags: ["Admin"]
|
|
11917
|
-
}).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true) }));
|
|
11925
|
+
}).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true), rungs: AnchorRungFlagsSchema }));
|
|
11918
11926
|
resetSpotifyAnchorBreaker = oc.route({
|
|
11919
11927
|
method: "POST",
|
|
11920
11928
|
operationId: "resetSpotifyAnchorBreaker",
|
|
@@ -18530,6 +18538,9 @@ async function requeueAnchorCommand(trackIds) {
|
|
|
18530
18538
|
async function requeueIsrcRecoveryCommand(input) {
|
|
18531
18539
|
return adminApiPost("/api/v1/admin/catalogue/isrc-recovery/requeue", input);
|
|
18532
18540
|
}
|
|
18541
|
+
async function anchorBreakerCommand() {
|
|
18542
|
+
return adminApiGet("/api/v1/admin/catalogue/anchor/breaker");
|
|
18543
|
+
}
|
|
18533
18544
|
async function forceCaptureCommand(trackId) {
|
|
18534
18545
|
return adminApiPost("/api/v1/admin/catalogue/force-capture", {
|
|
18535
18546
|
trackId
|
|
@@ -18598,8 +18609,8 @@ function artistRuleInput(artistMbid, verdict, artistName) {
|
|
|
18598
18609
|
if (!MBID_PATTERN.test(cleanMbid)) {
|
|
18599
18610
|
throw new Error("Artist MBID must be a MusicBrainz artist MBID");
|
|
18600
18611
|
}
|
|
18601
|
-
if (verdict !== "allow" && verdict !== "block") {
|
|
18602
|
-
throw new Error("Pass --verdict allow|block");
|
|
18612
|
+
if (verdict !== "allow" && verdict !== "block" && verdict !== "unlisted") {
|
|
18613
|
+
throw new Error("Pass --verdict allow|block|unlisted");
|
|
18603
18614
|
}
|
|
18604
18615
|
const cleanName = artistName?.trim();
|
|
18605
18616
|
if (artistName !== undefined && !cleanName) {
|
|
@@ -21230,8 +21241,9 @@ function labelUpdateLines(label, options) {
|
|
|
21230
21241
|
return lines;
|
|
21231
21242
|
}
|
|
21232
21243
|
var ARTIST_RULE_BOUNDARY = "Rules change what the next crawl takes. Everything already here stays.";
|
|
21233
|
-
|
|
21234
|
-
|
|
21244
|
+
var UNLISTED_RULE_BOUNDARY = "Unlisted takes the artist page down. The crawl and everything already here stay.";
|
|
21245
|
+
function artistRuleWriteLine(prefix, boundary = ARTIST_RULE_BOUNDARY) {
|
|
21246
|
+
return `${prefix} \u2014 ${boundary.charAt(0).toLowerCase()}${boundary.slice(1)}`;
|
|
21235
21247
|
}
|
|
21236
21248
|
function artistRuleLines(rules) {
|
|
21237
21249
|
if (rules.length === 0) {
|
|
@@ -22186,6 +22198,20 @@ JSON field reference:
|
|
|
22186
22198
|
}
|
|
22187
22199
|
console.log(`Re-queued ${requeued} of ${trackIds.length} row(s) \u2014 the next anchor tick picks them up at their real priority.`);
|
|
22188
22200
|
});
|
|
22201
|
+
catalogue.command("anchor-breaker").description("Why the anchor rungs are quiet: the throttle breaker, and which rungs are armed").option("--json", "Print JSON", false).action(async (options) => {
|
|
22202
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
22203
|
+
const state = await anchorBreakerCommand();
|
|
22204
|
+
if (options.json) {
|
|
22205
|
+
printJson({ ...state, ok: true });
|
|
22206
|
+
return;
|
|
22207
|
+
}
|
|
22208
|
+
const minutes = Math.ceil(state.cooldownRemainingMs / 60000);
|
|
22209
|
+
console.log(state.tripped ? `BREAKER TRIPPED \u2014 ${state.reason ?? "unknown"}, ~${minutes}m left (${state.throttlesInWindow} throttle(s) in window)` : `BREAKER CLEAR \u2014 ${state.throttlesInWindow} throttle(s) in window`);
|
|
22210
|
+
console.log(`RUNGS \u2014 spotify search ${state.rungs.spotifySearchEnabled ? "ARMED" : "OFF"} \xB7 apify fallback ${state.rungs.apifyEnabled ? "ARMED" : "OFF"}`);
|
|
22211
|
+
if (!state.rungs.spotifySearchEnabled && !state.rungs.apifyEnabled) {
|
|
22212
|
+
console.log("No rung can conclude \u2014 ListenBrainz still runs and can win, but its miss settles nothing.");
|
|
22213
|
+
}
|
|
22214
|
+
});
|
|
22189
22215
|
catalogue.command("requeue-isrc-recovery").description("Clear Deezer-empty ISRC-recovery stamps from a window (dry-run; --apply to take)").requiredOption("--since <iso>", "Inclusive lower bound on the stamp (2026-09-09)").option("--apply", "Actually clear the stamps (default is a dry-run count)", false).option("--json", "Print JSON", false).action(async (options) => {
|
|
22190
22216
|
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
22191
22217
|
const result = await requeueIsrcRecoveryCommand({
|
|
@@ -22406,14 +22432,14 @@ JSON field reference:
|
|
|
22406
22432
|
await Promise.resolve().then(() => init_admin_artists2());
|
|
22407
22433
|
await runArtistsRank(options, rankArtistsCommand);
|
|
22408
22434
|
});
|
|
22409
|
-
artists.command("rule").description("
|
|
22435
|
+
artists.command("rule").description("Rule one MusicBrainz artist: what the crawl takes, or whether they get a page").argument("<artist-mbid>", "The MusicBrainz artist MBID").requiredOption("--verdict <verdict>", "The ruling: allow, block, or unlisted (no public artist page)").option("--name <name>", "Artist name (optional; the server resolves it when omitted)").option("--json", "Print JSON", false).action(async (artistMbid, options) => {
|
|
22410
22436
|
await Promise.resolve().then(() => init_admin_artists2());
|
|
22411
22437
|
const rule = await addArtistRuleCommand(artistRuleInput(artistMbid, options.verdict, options.name));
|
|
22412
22438
|
if (options.json) {
|
|
22413
22439
|
printJson({ ok: true, rule });
|
|
22414
22440
|
return;
|
|
22415
22441
|
}
|
|
22416
|
-
console.log(artistRuleWriteLine(`Rule set for ${rule.resolvedName ?? rule.artistName}: ${rule.verdict.toUpperCase()}
|
|
22442
|
+
console.log(artistRuleWriteLine(`Rule set for ${rule.resolvedName ?? rule.artistName}: ${rule.verdict.toUpperCase()}`, rule.verdict === "unlisted" ? UNLISTED_RULE_BOUNDARY : ARTIST_RULE_BOUNDARY));
|
|
22417
22443
|
});
|
|
22418
22444
|
artists.command("rules").description("List the global artist crawl rules").option("--json", "Print JSON", false).action(async (options) => {
|
|
22419
22445
|
await Promise.resolve().then(() => init_admin_artists2());
|
|
@@ -25548,6 +25574,7 @@ if (__require.main == __require.module) {
|
|
|
25548
25574
|
}
|
|
25549
25575
|
export {
|
|
25550
25576
|
ARTIST_RULE_BOUNDARY,
|
|
25577
|
+
UNLISTED_RULE_BOUNDARY,
|
|
25551
25578
|
artistRuleLines,
|
|
25552
25579
|
createProgram,
|
|
25553
25580
|
labelUpdateLines,
|
package/package.json
CHANGED