fluncle 0.266.0 → 0.268.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 +167 -7
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -386,12 +386,16 @@ __export(exports_env, {
|
|
|
386
386
|
loadEnv: () => loadEnv,
|
|
387
387
|
readOptionalEnv: () => readOptionalEnv
|
|
388
388
|
});
|
|
389
|
+
import { execFileSync } from "node:child_process";
|
|
389
390
|
import { homedir } from "node:os";
|
|
390
391
|
import { join } from "node:path";
|
|
391
392
|
function loadEnv(keys) {
|
|
392
393
|
loadConfig();
|
|
393
394
|
const result = {};
|
|
394
395
|
const missing = [];
|
|
396
|
+
if (keys.includes("FLUNCLE_API_TOKEN")) {
|
|
397
|
+
resolveTokenRef();
|
|
398
|
+
}
|
|
395
399
|
for (const key of keys) {
|
|
396
400
|
const value = process.env[key];
|
|
397
401
|
if (value === undefined) {
|
|
@@ -413,6 +417,21 @@ function getApiBaseUrl() {
|
|
|
413
417
|
loadConfig();
|
|
414
418
|
return (process.env.FLUNCLE_API_BASE_URL ?? "https://www.fluncle.com").replace(/\/+$/, "");
|
|
415
419
|
}
|
|
420
|
+
function resolveTokenRef() {
|
|
421
|
+
const ref = process.env.FLUNCLE_API_TOKEN_REF;
|
|
422
|
+
if (process.env.FLUNCLE_API_TOKEN !== undefined || !ref || false) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
const secretRef = ref.startsWith("op://") ? ref : `op://${ref}`;
|
|
427
|
+
process.env.FLUNCLE_API_TOKEN = execFileSync("op", ["read", "--no-newline", secretRef], {
|
|
428
|
+
encoding: "utf8",
|
|
429
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
430
|
+
});
|
|
431
|
+
} catch {
|
|
432
|
+
throw new Error(`Could not read FLUNCLE_API_TOKEN_REF (${ref}) with op.`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
416
435
|
function loadConfig() {
|
|
417
436
|
const profile = getEnvProfile();
|
|
418
437
|
if (loadedProfile === profile) {
|
|
@@ -632,7 +651,7 @@ function parseVersion(version) {
|
|
|
632
651
|
var currentVersion;
|
|
633
652
|
var init_version = __esm(() => {
|
|
634
653
|
init_output();
|
|
635
|
-
currentVersion = "0.
|
|
654
|
+
currentVersion = "0.268.0".trim() ? "0.268.0".trim() : "0.1.0";
|
|
636
655
|
});
|
|
637
656
|
|
|
638
657
|
// src/update-notifier.ts
|
|
@@ -2345,7 +2364,7 @@ function parseVersion2(version) {
|
|
|
2345
2364
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2346
2365
|
var init_version2 = __esm(() => {
|
|
2347
2366
|
init_output();
|
|
2348
|
-
currentVersion2 = "0.
|
|
2367
|
+
currentVersion2 = "0.268.0".trim() ? "0.268.0".trim() : "0.1.0";
|
|
2349
2368
|
});
|
|
2350
2369
|
|
|
2351
2370
|
// ../../packages/registry/src/index.ts
|
|
@@ -10239,7 +10258,7 @@ var init_zod = __esm(() => {
|
|
|
10239
10258
|
});
|
|
10240
10259
|
|
|
10241
10260
|
// ../../packages/contracts/src/orpc/admin-catalogue.ts
|
|
10242
|
-
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, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, CrawlPipelineSummarySchema, PipelineWatchBoundedCountSchema, getPipeline, crawlCatalogue, commitCrawlNodes, 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, recordAnchorFailure, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, AnchorResolveResultSchema, AnchorCommitResultSchema, prepareAnchor, AnchorPhaseBatchItemFailureSchema, prepareAnchorBatch, resolveAnchorCandidate, commitAnchor, commitAnchorBatch, getAnchorReceipt, getAnchorPaidToken, cancelAnchorPaidResult, resolveAnchorPaidResult, resolveAnchor, resolveAnchorReview, CrawlHoldReasonSchema, CrawlHoldStateSchema, CrawlHoldSchema, listCrawlHolds, resolveCrawlHold, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, LabelReleasesBudgetSchema, getLabelReleasesBudget, setLabelReleasesBudget, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
10261
|
+
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, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, CrawlPipelineSummarySchema, PipelineWatchBoundedCountSchema, getPipeline, crawlCatalogue, commitCrawlNodes, 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, recordAnchorFailure, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, AnchorResolveResultSchema, AnchorCommitResultSchema, prepareAnchor, AnchorPhaseBatchItemFailureSchema, prepareAnchorBatch, resolveAnchorCandidate, commitAnchor, commitAnchorBatch, getAnchorReceipt, getAnchorPaidToken, cancelAnchorPaidResult, resolveAnchorPaidResult, resolveAnchor, ReleaseLinkResultSchema, ReleaseLinkProbeSchema, resolveAnchorReleaseProbe, commitAnchorRelease, resolveAnchorReview, CrawlHoldReasonSchema, CrawlHoldStateSchema, CrawlHoldSchema, listCrawlHolds, resolveCrawlHold, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, setSpotifyConsumerBudget, LabelReleasesBudgetSchema, getLabelReleasesBudget, setLabelReleasesBudget, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
10243
10262
|
var init_admin_catalogue = __esm(() => {
|
|
10244
10263
|
init_dist3();
|
|
10245
10264
|
init_zod();
|
|
@@ -10735,6 +10754,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10735
10754
|
}).meta({ id: "DeezerIsrcCandidate" });
|
|
10736
10755
|
AnchorResolveResultSchema = object({
|
|
10737
10756
|
anchored: boolean2(),
|
|
10757
|
+
anchoredByReleaseLink: number2().int().nonnegative().optional(),
|
|
10738
10758
|
apifyBudgetRemaining: number2().int().nonnegative(),
|
|
10739
10759
|
apifyEligible: boolean2(),
|
|
10740
10760
|
apifyEnabled: boolean2(),
|
|
@@ -10754,7 +10774,18 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10754
10774
|
]),
|
|
10755
10775
|
ok: literal(true),
|
|
10756
10776
|
paidResultToken: string2().optional(),
|
|
10757
|
-
|
|
10777
|
+
releaseLinkAlbumFetchFailed: number2().int().nonnegative().optional(),
|
|
10778
|
+
releaseLinkAlbumsFetched: number2().int().nonnegative().optional(),
|
|
10779
|
+
releaseLinkBackoffSkipped: number2().int().nonnegative().optional(),
|
|
10780
|
+
releaseLinkCacheHits: number2().int().nonnegative().optional(),
|
|
10781
|
+
releaseLinkNoAlbum: number2().int().nonnegative().optional(),
|
|
10782
|
+
source: _enum([
|
|
10783
|
+
"listenbrainz",
|
|
10784
|
+
"listenbrainz-metadata",
|
|
10785
|
+
"release-link",
|
|
10786
|
+
"spotify-isrc",
|
|
10787
|
+
"spotify-search"
|
|
10788
|
+
]).nullable(),
|
|
10758
10789
|
spotifyIsrcAsked: boolean2(),
|
|
10759
10790
|
spotifySearchDone: boolean2(),
|
|
10760
10791
|
spotifySearchEnabled: boolean2(),
|
|
@@ -10888,13 +10919,65 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10888
10919
|
method: "POST",
|
|
10889
10920
|
operationId: "resolveAnchor",
|
|
10890
10921
|
path: "/admin/catalogue/anchor/resolve",
|
|
10891
|
-
summary: "Resolve a catalogue row's Spotify anchor from
|
|
10922
|
+
summary: "Resolve a catalogue row's Spotify anchor from release links, ListenBrainz, and Spotify search",
|
|
10892
10923
|
tags: ["Admin"]
|
|
10893
10924
|
}).input(object({
|
|
10894
10925
|
deezerCandidates: array(DeezerIsrcCandidateSchema).max(DEEZER_CANDIDATE_LIMIT).optional(),
|
|
10895
10926
|
spotifySearch: boolean2().optional(),
|
|
10896
10927
|
trackId: string2().min(1)
|
|
10897
10928
|
})).output(AnchorResolveResultSchema);
|
|
10929
|
+
ReleaseLinkResultSchema = object({
|
|
10930
|
+
albumFetchFailed: number2().int().nonnegative(),
|
|
10931
|
+
albumsFetched: number2().int().nonnegative(),
|
|
10932
|
+
anchored: boolean2(),
|
|
10933
|
+
anchoredCount: number2().int().nonnegative(),
|
|
10934
|
+
backoffSkipped: number2().int().nonnegative(),
|
|
10935
|
+
cacheHits: number2().int().nonnegative(),
|
|
10936
|
+
noAlbum: number2().int().nonnegative(),
|
|
10937
|
+
ok: literal(true),
|
|
10938
|
+
remainder: number2().int().nonnegative().nullable(),
|
|
10939
|
+
throttled: boolean2(),
|
|
10940
|
+
verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
|
|
10941
|
+
});
|
|
10942
|
+
ReleaseLinkProbeSchema = object({
|
|
10943
|
+
evidence: array(object({
|
|
10944
|
+
albumId: string2().nullable(),
|
|
10945
|
+
checkedAt: string2().nullable(),
|
|
10946
|
+
recordingIds: array(string2()).max(1000),
|
|
10947
|
+
releaseId: string2(),
|
|
10948
|
+
siblingTrackIds: array(string2()).max(1000),
|
|
10949
|
+
tracks: array(object({
|
|
10950
|
+
artists: array(object({ id: string2(), name: string2() })),
|
|
10951
|
+
discNumber: number2(),
|
|
10952
|
+
durationMs: number2(),
|
|
10953
|
+
isrc: string2().nullable(),
|
|
10954
|
+
spotifyTrackId: string2(),
|
|
10955
|
+
title: string2(),
|
|
10956
|
+
trackNumber: number2()
|
|
10957
|
+
})).max(1000)
|
|
10958
|
+
})).max(3),
|
|
10959
|
+
issuedAt: number2().int().nonnegative(),
|
|
10960
|
+
result: ReleaseLinkResultSchema.omit({ ok: true }),
|
|
10961
|
+
trackId: string2().min(1)
|
|
10962
|
+
});
|
|
10963
|
+
resolveAnchorReleaseProbe = oc.route({
|
|
10964
|
+
method: "POST",
|
|
10965
|
+
operationId: "resolveAnchorReleaseProbe",
|
|
10966
|
+
path: "/admin/catalogue/anchor/release/probe",
|
|
10967
|
+
summary: "Probe MusicBrainz release links and Spotify album tracks",
|
|
10968
|
+
tags: ["Admin"]
|
|
10969
|
+
}).input(object({ spotifySearch: boolean2().optional(), trackId: string2().min(1) })).output(object({ ok: literal(true), probe: ReleaseLinkProbeSchema, proof: string2() }));
|
|
10970
|
+
commitAnchorRelease = oc.route({
|
|
10971
|
+
method: "POST",
|
|
10972
|
+
operationId: "commitAnchorRelease",
|
|
10973
|
+
path: "/admin/catalogue/anchor/release/commit",
|
|
10974
|
+
summary: "Commit release mappings and a bounded sibling anchor batch",
|
|
10975
|
+
tags: ["Admin"]
|
|
10976
|
+
}).input(object({
|
|
10977
|
+
cursor: number2().int().nonnegative(),
|
|
10978
|
+
probe: ReleaseLinkProbeSchema,
|
|
10979
|
+
proof: string2()
|
|
10980
|
+
})).output(ReleaseLinkResultSchema);
|
|
10898
10981
|
resolveAnchorReview = oc.route({
|
|
10899
10982
|
method: "POST",
|
|
10900
10983
|
operationId: "resolveAnchorReview",
|
|
@@ -11033,6 +11116,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11033
11116
|
"quota_hold",
|
|
11034
11117
|
"breaker_quota",
|
|
11035
11118
|
"breaker_throttle",
|
|
11119
|
+
"daily_budget",
|
|
11036
11120
|
"shared_meter",
|
|
11037
11121
|
"open"
|
|
11038
11122
|
]),
|
|
@@ -11046,10 +11130,37 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11046
11130
|
summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
|
|
11047
11131
|
tags: ["Admin"]
|
|
11048
11132
|
}).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({
|
|
11133
|
+
consumerBudgets: object({
|
|
11134
|
+
anchor: object({
|
|
11135
|
+
callsSpent: number2().int().nullable(),
|
|
11136
|
+
dailyBudget: number2().int().nullable()
|
|
11137
|
+
}),
|
|
11138
|
+
artist_images: object({
|
|
11139
|
+
callsSpent: number2().int().nullable(),
|
|
11140
|
+
dailyBudget: number2().int().nullable()
|
|
11141
|
+
}),
|
|
11142
|
+
public_search: object({
|
|
11143
|
+
callsSpent: number2().int().nullable(),
|
|
11144
|
+
dailyBudget: number2().int().nullable()
|
|
11145
|
+
})
|
|
11146
|
+
}),
|
|
11147
|
+
essentialDailyCalls: number2().int().nullable(),
|
|
11049
11148
|
ok: literal(true),
|
|
11149
|
+
quotaHoldState: _enum(["clear", "held", "unknown"]),
|
|
11150
|
+
quotaHoldUntil: string2().nullable(),
|
|
11050
11151
|
rungs: AnchorRungFlagsSchema,
|
|
11051
11152
|
spotifyDailyCalls: number2().int().nullable()
|
|
11052
11153
|
}));
|
|
11154
|
+
setSpotifyConsumerBudget = oc.route({
|
|
11155
|
+
method: "PUT",
|
|
11156
|
+
operationId: "setSpotifyConsumerBudget",
|
|
11157
|
+
path: "/admin/catalogue/spotify-budget",
|
|
11158
|
+
summary: "Set a Spotify consumer daily budget (operator)",
|
|
11159
|
+
tags: ["Admin"]
|
|
11160
|
+
}).input(object({
|
|
11161
|
+
consumer: _enum(["anchor", "artist_images", "public_search"]),
|
|
11162
|
+
dailyBudget: number2().int().min(0).max(1e6)
|
|
11163
|
+
})).output(object({ ok: literal(true) }));
|
|
11053
11164
|
LabelReleasesBudgetSchema = object({
|
|
11054
11165
|
callsSpent: number2().int().nonnegative(),
|
|
11055
11166
|
dailyBudget: number2().int().nonnegative(),
|
|
@@ -11096,6 +11207,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11096
11207
|
clear_wrong_audio: clearWrongAudio,
|
|
11097
11208
|
commit_anchor: commitAnchor,
|
|
11098
11209
|
commit_anchor_batch: commitAnchorBatch,
|
|
11210
|
+
commit_anchor_release: commitAnchorRelease,
|
|
11099
11211
|
commit_crawl_nodes: commitCrawlNodes,
|
|
11100
11212
|
crawl_catalogue: crawlCatalogue,
|
|
11101
11213
|
flag_wrong_audio: flagWrongAudio,
|
|
@@ -11124,6 +11236,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11124
11236
|
resolve_anchor: resolveAnchor,
|
|
11125
11237
|
resolve_anchor_candidate: resolveAnchorCandidate,
|
|
11126
11238
|
resolve_anchor_paid_result: resolveAnchorPaidResult,
|
|
11239
|
+
resolve_anchor_release_probe: resolveAnchorReleaseProbe,
|
|
11127
11240
|
resolve_anchor_review: resolveAnchorReview,
|
|
11128
11241
|
resolve_crawl_hold: resolveCrawlHold,
|
|
11129
11242
|
set_anchor_apify: setAnchorApify,
|
|
@@ -11131,6 +11244,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11131
11244
|
set_anchor_search: setAnchorSearch,
|
|
11132
11245
|
set_capture_budget: setCaptureBudget,
|
|
11133
11246
|
set_label_releases_budget: setLabelReleasesBudget,
|
|
11247
|
+
set_spotify_consumer_budget: setSpotifyConsumerBudget,
|
|
11134
11248
|
set_track_dismissed: setTrackDismissed,
|
|
11135
11249
|
verify_capture: verifyCapture
|
|
11136
11250
|
};
|
|
@@ -11417,6 +11531,7 @@ var init_admin_artifacts = __esm(() => {
|
|
|
11417
11531
|
tags: ["Admin"]
|
|
11418
11532
|
}).input(strictObject({
|
|
11419
11533
|
consumerId: ConsumerIdSchema,
|
|
11534
|
+
fromSeq: number3().int().nonnegative().optional(),
|
|
11420
11535
|
limit: number3().int().min(1).max(ARTIFACT_CHANGE_API_MAX_LIMIT).default(100)
|
|
11421
11536
|
})).output(ArtifactChangePageSchema);
|
|
11422
11537
|
acknowledgeArtifactChanges = oc.route({
|
|
@@ -14120,7 +14235,7 @@ var init_admin_labels = __esm(() => {
|
|
|
14120
14235
|
method: "PATCH",
|
|
14121
14236
|
operationId: "updateLabel",
|
|
14122
14237
|
path: "/admin/labels/{id}",
|
|
14123
|
-
summary: "Update a label's crawl scope or arm a re-walk (operator; never storage)",
|
|
14238
|
+
summary: "Update a label's crawl scope or arm a re-walk (operator, or an agent applying a ratified triage round; never storage)",
|
|
14124
14239
|
tags: ["Admin"]
|
|
14125
14240
|
}).input(object({
|
|
14126
14241
|
id: string2(),
|
|
@@ -14141,7 +14256,7 @@ var init_admin_labels = __esm(() => {
|
|
|
14141
14256
|
method: "PUT",
|
|
14142
14257
|
operationId: "replaceLabelArtistRules",
|
|
14143
14258
|
path: "/admin/labels/{id}/artists",
|
|
14144
|
-
summary: "Replace one label's complete artist-rule set (operator)",
|
|
14259
|
+
summary: "Replace one label's complete artist-rule set (operator, or an agent applying a ratified triage round)",
|
|
14145
14260
|
tags: ["Admin"]
|
|
14146
14261
|
}).input(object({
|
|
14147
14262
|
id: string2(),
|
|
@@ -17658,6 +17773,7 @@ var contract, CONTRACT_OPERATION_NAMES, CONTRACT_OPERATION_ROUTES;
|
|
|
17658
17773
|
var init_orpc = __esm(() => {
|
|
17659
17774
|
init_dist3();
|
|
17660
17775
|
init_admin_catalogue();
|
|
17776
|
+
init_admin_catalogue();
|
|
17661
17777
|
init_admin_albums();
|
|
17662
17778
|
init_admin_artifacts();
|
|
17663
17779
|
init_admin_artist_rules();
|
|
@@ -19926,6 +20042,15 @@ async function requeueAnchorCommand(trackIds, clearPaid = false) {
|
|
|
19926
20042
|
async function requeueIsrcRecoveryCommand(input) {
|
|
19927
20043
|
return adminApiPost("/api/v1/admin/catalogue/isrc-recovery/requeue", input);
|
|
19928
20044
|
}
|
|
20045
|
+
async function spotifyConsumerBudgetCommand() {
|
|
20046
|
+
return anchorBreakerCommand();
|
|
20047
|
+
}
|
|
20048
|
+
async function setSpotifyConsumerBudgetCommand(consumer, dailyBudget) {
|
|
20049
|
+
return adminApiPut("/api/v1/admin/catalogue/spotify-budget", {
|
|
20050
|
+
consumer,
|
|
20051
|
+
dailyBudget
|
|
20052
|
+
});
|
|
20053
|
+
}
|
|
19929
20054
|
async function labelReleasesBudgetCommand() {
|
|
19930
20055
|
return adminApiGet("/api/v1/admin/catalogue/label-releases-budget");
|
|
19931
20056
|
}
|
|
@@ -24717,6 +24842,40 @@ JSON field reference:
|
|
|
24717
24842
|
}
|
|
24718
24843
|
console.log(`LABEL RELEASES BUDGET \u2014 ${state.callsSpent}/${state.dailyBudget} tap calls today \xB7 ${state.spotifyDailyCalls} Spotify calls total`);
|
|
24719
24844
|
});
|
|
24845
|
+
const spotifyBudget = catalogue.command("spotify-consumer-budget").description("Read or set Spotify daily call budgets by consumer");
|
|
24846
|
+
const showSpotifyConsumerBudget = async (options) => {
|
|
24847
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
24848
|
+
const state = await spotifyConsumerBudgetCommand();
|
|
24849
|
+
if (options.json || spotifyBudget.opts().json) {
|
|
24850
|
+
printJson({
|
|
24851
|
+
consumerBudgets: state.consumerBudgets,
|
|
24852
|
+
ok: true,
|
|
24853
|
+
spotifyDailyCalls: state.spotifyDailyCalls
|
|
24854
|
+
});
|
|
24855
|
+
return;
|
|
24856
|
+
}
|
|
24857
|
+
for (const [consumer, budget] of Object.entries(state.consumerBudgets)) {
|
|
24858
|
+
console.log(`SPOTIFY BUDGET ${consumer} \u2014 ${budget.callsSpent}/${budget.dailyBudget} calls today`);
|
|
24859
|
+
}
|
|
24860
|
+
};
|
|
24861
|
+
spotifyBudget.option("--json", "Print JSON", false).action(showSpotifyConsumerBudget);
|
|
24862
|
+
spotifyBudget.command("get").option("--json", "Print JSON", false).action(showSpotifyConsumerBudget);
|
|
24863
|
+
spotifyBudget.command("set").requiredOption("--consumer <consumer>", "anchor | artist_images | public_search").requiredOption("--calls <n>", "Daily Spotify calls allowed for this consumer").option("--json", "Print JSON", false).action(async (options) => {
|
|
24864
|
+
if (!["anchor", "artist_images", "public_search"].includes(options.consumer)) {
|
|
24865
|
+
throw new Error("--consumer must be anchor, artist_images, or public_search");
|
|
24866
|
+
}
|
|
24867
|
+
const calls = Number(options.calls);
|
|
24868
|
+
if (!Number.isSafeInteger(calls) || calls < 0 || calls > 1e6) {
|
|
24869
|
+
throw new Error("--calls must be an integer from 0 to 1000000");
|
|
24870
|
+
}
|
|
24871
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
24872
|
+
await setSpotifyConsumerBudgetCommand(options.consumer, calls);
|
|
24873
|
+
if (options.json || spotifyBudget.opts().json) {
|
|
24874
|
+
printJson({ calls, consumer: options.consumer, ok: true });
|
|
24875
|
+
return;
|
|
24876
|
+
}
|
|
24877
|
+
console.log(`SPOTIFY BUDGET ${options.consumer} \u2014 ${calls} calls per day`);
|
|
24878
|
+
});
|
|
24720
24879
|
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) => {
|
|
24721
24880
|
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
24722
24881
|
const state = await anchorBreakerCommand();
|
|
@@ -28085,6 +28244,7 @@ var stringOptions = new Set([
|
|
|
28085
28244
|
"--census-pages",
|
|
28086
28245
|
"--composition",
|
|
28087
28246
|
"--consumer-digest",
|
|
28247
|
+
"--consumer",
|
|
28088
28248
|
"--consumer-item-count",
|
|
28089
28249
|
"--content-file",
|
|
28090
28250
|
"--contract",
|
package/package.json
CHANGED