fluncle 0.258.0 → 0.260.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 +287 -9
- 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.260.0".trim() ? "0.260.0".trim() : "0.1.0";
|
|
626
626
|
});
|
|
627
627
|
|
|
628
628
|
// src/update-notifier.ts
|
|
@@ -2258,7 +2258,7 @@ var init_about = __esm(() => {
|
|
|
2258
2258
|
heading: "For the nerds",
|
|
2259
2259
|
links: [
|
|
2260
2260
|
{ label: "The Galaxy (game)", url: "https://galaxy.fluncle.com" },
|
|
2261
|
-
{ label: "SSH (
|
|
2261
|
+
{ label: "SSH (the rave terminal)", url: "ssh rave.fluncle.com" },
|
|
2262
2262
|
{ label: "Source", url: "https://github.com/mauricekleine/fluncle" }
|
|
2263
2263
|
]
|
|
2264
2264
|
}
|
|
@@ -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.260.0".trim() ? "0.260.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -3293,7 +3293,7 @@ var init_src = __esm(() => {
|
|
|
3293
3293
|
},
|
|
3294
3294
|
{
|
|
3295
3295
|
command: "fluncle random",
|
|
3296
|
-
exposedContent: ["the archive throws
|
|
3296
|
+
exposedContent: ["the archive throws a banger back"],
|
|
3297
3297
|
kind: "cli",
|
|
3298
3298
|
name: "cli.random",
|
|
3299
3299
|
weights: { cli: "secondary" }
|
|
@@ -3879,6 +3879,24 @@ var init_src = __esm(() => {
|
|
|
3879
3879
|
title: "Healthcheck prober",
|
|
3880
3880
|
weights: { status: "hidden" }
|
|
3881
3881
|
},
|
|
3882
|
+
{
|
|
3883
|
+
command: "fluncle admin digests send",
|
|
3884
|
+
exposedContent: [
|
|
3885
|
+
"send new releases from followed artists and labels to signed-in crew each Friday"
|
|
3886
|
+
],
|
|
3887
|
+
kind: "cron",
|
|
3888
|
+
name: "cron.follow-digest",
|
|
3889
|
+
operatorNotes: "Friday 17:00 Amsterdam, a template-only host-timer sweep. The Worker owns recipient selection, the enabled-by-default kill switch, Resend idempotency keys, and per-call send cap. The box uses only its agent token. Source: docs/agents/hermes/scripts/follow-digest-sweep.*.",
|
|
3890
|
+
probeConfig: {
|
|
3891
|
+
cadenceMs: 7 * 24 * 60 * MINUTE_MS,
|
|
3892
|
+
cronName: "fluncle-follow-digest",
|
|
3893
|
+
kind: "cron",
|
|
3894
|
+
schedule: { time: "17:00", tz: "Europe/Amsterdam", weekday: 5 }
|
|
3895
|
+
},
|
|
3896
|
+
statusDescription: "sends new releases from the artists and labels you follow",
|
|
3897
|
+
title: "Your follows",
|
|
3898
|
+
weights: { status: "secondary" }
|
|
3899
|
+
},
|
|
3882
3900
|
{
|
|
3883
3901
|
command: "fluncle admin newsletter draft",
|
|
3884
3902
|
exposedContent: [
|
|
@@ -10776,6 +10794,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10776
10794
|
gateReason: _enum([
|
|
10777
10795
|
"friday_window",
|
|
10778
10796
|
"flag_off",
|
|
10797
|
+
"quota_hold",
|
|
10779
10798
|
"breaker_quota",
|
|
10780
10799
|
"breaker_throttle",
|
|
10781
10800
|
"shared_meter",
|
|
@@ -15742,6 +15761,113 @@ var init_editions = __esm(() => {
|
|
|
15742
15761
|
};
|
|
15743
15762
|
});
|
|
15744
15763
|
|
|
15764
|
+
// ../../packages/contracts/src/orpc/follow-digest.ts
|
|
15765
|
+
var TokenSchema, sendFollowDigests, getFollowDigestState, setFollowDigestState, unsubscribeFollowDigest, subscribeFollowDigest, listDigestFollows, deleteDigestFollow, followDigestContract;
|
|
15766
|
+
var init_follow_digest = __esm(() => {
|
|
15767
|
+
init_dist3();
|
|
15768
|
+
init_zod();
|
|
15769
|
+
TokenSchema = string2().min(10).max(1024);
|
|
15770
|
+
sendFollowDigests = oc.route({
|
|
15771
|
+
method: "POST",
|
|
15772
|
+
operationId: "sendFollowDigests",
|
|
15773
|
+
path: "/admin/follow-digests/send",
|
|
15774
|
+
summary: "Send the weekly digest to eligible followers in a bounded batch",
|
|
15775
|
+
tags: ["Admin"]
|
|
15776
|
+
}).input(object({
|
|
15777
|
+
cursor: string2().optional(),
|
|
15778
|
+
dryRun: boolean2().optional(),
|
|
15779
|
+
limit: number2().int().min(1).max(50).optional()
|
|
15780
|
+
})).output(object({
|
|
15781
|
+
capped: boolean2(),
|
|
15782
|
+
considered: number2(),
|
|
15783
|
+
dryRun: boolean2(),
|
|
15784
|
+
empty: number2(),
|
|
15785
|
+
failed: number2(),
|
|
15786
|
+
nextCursor: string2().optional(),
|
|
15787
|
+
ok: literal(true),
|
|
15788
|
+
paused: boolean2(),
|
|
15789
|
+
sent: number2(),
|
|
15790
|
+
skipped: number2(),
|
|
15791
|
+
unknown: number2(),
|
|
15792
|
+
weekKey: string2()
|
|
15793
|
+
}));
|
|
15794
|
+
getFollowDigestState = oc.route({
|
|
15795
|
+
method: "GET",
|
|
15796
|
+
operationId: "getFollowDigestState",
|
|
15797
|
+
path: "/admin/follow-digests/state",
|
|
15798
|
+
summary: "Read the follow digest kill switch",
|
|
15799
|
+
tags: ["Admin"]
|
|
15800
|
+
}).output(object({ ok: literal(true), paused: boolean2() }));
|
|
15801
|
+
setFollowDigestState = oc.route({
|
|
15802
|
+
method: "PUT",
|
|
15803
|
+
operationId: "setFollowDigestState",
|
|
15804
|
+
path: "/admin/follow-digests/state",
|
|
15805
|
+
summary: "Pause or resume weekly follow digests",
|
|
15806
|
+
tags: ["Admin"]
|
|
15807
|
+
}).input(object({ paused: boolean2() })).output(object({ ok: literal(true), paused: boolean2() }));
|
|
15808
|
+
unsubscribeFollowDigest = oc.route({
|
|
15809
|
+
inputStructure: "detailed",
|
|
15810
|
+
method: "POST",
|
|
15811
|
+
operationId: "unsubscribeFollowDigest",
|
|
15812
|
+
path: "/follow-digest/unsubscribe",
|
|
15813
|
+
summary: "Unsubscribe a signed follow digest recipient",
|
|
15814
|
+
tags: ["Follow digest"]
|
|
15815
|
+
}).input(object({
|
|
15816
|
+
body: object({
|
|
15817
|
+
"List-Unsubscribe": literal("One-Click").optional(),
|
|
15818
|
+
token: TokenSchema.optional()
|
|
15819
|
+
}).optional(),
|
|
15820
|
+
query: object({ token: TokenSchema.optional() })
|
|
15821
|
+
})).output(object({ ok: literal(true), subscribed: literal(false) }));
|
|
15822
|
+
subscribeFollowDigest = oc.route({
|
|
15823
|
+
inputStructure: "detailed",
|
|
15824
|
+
method: "POST",
|
|
15825
|
+
operationId: "subscribeFollowDigest",
|
|
15826
|
+
path: "/follow-digest/subscribe",
|
|
15827
|
+
summary: "Subscribe a signed follow digest recipient",
|
|
15828
|
+
tags: ["Follow digest"]
|
|
15829
|
+
}).input(object({
|
|
15830
|
+
body: object({ token: TokenSchema.optional() }).optional(),
|
|
15831
|
+
query: object({ token: TokenSchema.optional() })
|
|
15832
|
+
})).output(object({ ok: literal(true), subscribed: literal(true) }));
|
|
15833
|
+
listDigestFollows = oc.route({
|
|
15834
|
+
method: "GET",
|
|
15835
|
+
operationId: "listDigestFollows",
|
|
15836
|
+
path: "/follow-digest/follows",
|
|
15837
|
+
summary: "List follows for a signed digest recipient",
|
|
15838
|
+
tags: ["Follow digest"]
|
|
15839
|
+
}).input(object({ token: TokenSchema })).output(object({
|
|
15840
|
+
follows: array(object({
|
|
15841
|
+
id: string2(),
|
|
15842
|
+
kind: _enum(["artist", "label"]),
|
|
15843
|
+
name: string2(),
|
|
15844
|
+
slug: string2()
|
|
15845
|
+
})),
|
|
15846
|
+
ok: literal(true),
|
|
15847
|
+
subscribed: boolean2()
|
|
15848
|
+
}));
|
|
15849
|
+
deleteDigestFollow = oc.route({
|
|
15850
|
+
inputStructure: "detailed",
|
|
15851
|
+
method: "DELETE",
|
|
15852
|
+
operationId: "deleteDigestFollow",
|
|
15853
|
+
path: "/follow-digest/follows/{id}",
|
|
15854
|
+
summary: "Remove one follow for a signed digest recipient",
|
|
15855
|
+
tags: ["Follow digest"]
|
|
15856
|
+
}).input(object({
|
|
15857
|
+
params: object({ id: string2().min(1) }),
|
|
15858
|
+
query: object({ token: TokenSchema })
|
|
15859
|
+
})).output(object({ ok: literal(true) }));
|
|
15860
|
+
followDigestContract = {
|
|
15861
|
+
delete_digest_follow: deleteDigestFollow,
|
|
15862
|
+
get_follow_digest_state: getFollowDigestState,
|
|
15863
|
+
list_digest_follows: listDigestFollows,
|
|
15864
|
+
send_follow_digests: sendFollowDigests,
|
|
15865
|
+
set_follow_digest_state: setFollowDigestState,
|
|
15866
|
+
subscribe_follow_digest: subscribeFollowDigest,
|
|
15867
|
+
unsubscribe_follow_digest: unsubscribeFollowDigest
|
|
15868
|
+
};
|
|
15869
|
+
});
|
|
15870
|
+
|
|
15745
15871
|
// ../../packages/contracts/src/orpc/health.ts
|
|
15746
15872
|
var getHealth, healthContract;
|
|
15747
15873
|
var init_health = __esm(() => {
|
|
@@ -15759,6 +15885,74 @@ var init_health = __esm(() => {
|
|
|
15759
15885
|
};
|
|
15760
15886
|
});
|
|
15761
15887
|
|
|
15888
|
+
// ../../packages/contracts/src/orpc/me-follows.ts
|
|
15889
|
+
var FollowKindSchema, FollowSchema, SaveFollowBodySchema, listPrivateFollows, savePrivateFollow, deletePrivateFollow, revokePrivateFollowLinkAccess, meFollowsContract;
|
|
15890
|
+
var init_me_follows = __esm(() => {
|
|
15891
|
+
init_dist3();
|
|
15892
|
+
init_zod();
|
|
15893
|
+
FollowKindSchema = _enum(["artist", "label"]).meta({ id: "FollowKind" });
|
|
15894
|
+
FollowSchema = object({
|
|
15895
|
+
createdAt: string2(),
|
|
15896
|
+
entityId: string2(),
|
|
15897
|
+
id: string2(),
|
|
15898
|
+
includeSimilar: boolean2(),
|
|
15899
|
+
kind: FollowKindSchema,
|
|
15900
|
+
name: string2(),
|
|
15901
|
+
slug: string2()
|
|
15902
|
+
}).meta({ id: "Follow" });
|
|
15903
|
+
SaveFollowBodySchema = looseObject({
|
|
15904
|
+
entityId: unknown().optional(),
|
|
15905
|
+
intent: unknown().optional(),
|
|
15906
|
+
kind: unknown().optional()
|
|
15907
|
+
});
|
|
15908
|
+
listPrivateFollows = oc.route({
|
|
15909
|
+
method: "GET",
|
|
15910
|
+
operationId: "listPrivateFollows",
|
|
15911
|
+
path: "/me/follows",
|
|
15912
|
+
summary: "List the artists and labels the signed-in user follows",
|
|
15913
|
+
tags: ["Me"]
|
|
15914
|
+
}).output(object({ follows: array(FollowSchema), ok: literal(true) }));
|
|
15915
|
+
savePrivateFollow = oc.route({
|
|
15916
|
+
method: "POST",
|
|
15917
|
+
operationId: "savePrivateFollow",
|
|
15918
|
+
path: "/me/follows",
|
|
15919
|
+
summary: "Follow an artist or label for the signed-in user",
|
|
15920
|
+
tags: ["Me"]
|
|
15921
|
+
}).input(SaveFollowBodySchema).output(object({
|
|
15922
|
+
follow: object({
|
|
15923
|
+
createdAt: string2(),
|
|
15924
|
+
entityId: string2(),
|
|
15925
|
+
id: string2(),
|
|
15926
|
+
includeSimilar: boolean2(),
|
|
15927
|
+
kind: FollowKindSchema,
|
|
15928
|
+
name: string2(),
|
|
15929
|
+
slug: string2()
|
|
15930
|
+
}),
|
|
15931
|
+
followsEmail: boolean2(),
|
|
15932
|
+
ok: literal(true)
|
|
15933
|
+
}));
|
|
15934
|
+
deletePrivateFollow = oc.route({
|
|
15935
|
+
method: "DELETE",
|
|
15936
|
+
operationId: "deletePrivateFollow",
|
|
15937
|
+
path: "/me/follows/{id}",
|
|
15938
|
+
summary: "Unfollow an artist or label for the signed-in user",
|
|
15939
|
+
tags: ["Me"]
|
|
15940
|
+
}).input(object({ id: string2() })).output(object({ ok: literal(true) }));
|
|
15941
|
+
revokePrivateFollowLinkAccess = oc.route({
|
|
15942
|
+
method: "POST",
|
|
15943
|
+
operationId: "revokePrivateFollowLinkAccess",
|
|
15944
|
+
path: "/me/follow-link-access/revoke",
|
|
15945
|
+
summary: "Revoke emailed follows management links for the signed-in user",
|
|
15946
|
+
tags: ["Me"]
|
|
15947
|
+
}).output(object({ ok: literal(true), token: string2() }));
|
|
15948
|
+
meFollowsContract = {
|
|
15949
|
+
delete_private_follow: deletePrivateFollow,
|
|
15950
|
+
list_private_follows: listPrivateFollows,
|
|
15951
|
+
revoke_private_follow_link_access: revokePrivateFollowLinkAccess,
|
|
15952
|
+
save_private_follow: savePrivateFollow
|
|
15953
|
+
};
|
|
15954
|
+
});
|
|
15955
|
+
|
|
15762
15956
|
// ../../packages/contracts/src/orpc/me-galaxy.ts
|
|
15763
15957
|
var GalaxyProgressSchema, GalaxyMergeBodySchema, GalaxyLogBodySchema, getPrivateGalaxyProgress, mergePrivateGalaxyProgress, collectPrivateGalaxyLog, GalaxyCollectionItemSchema, GalaxyCompletionSchema, listPrivateGalaxyCollection, meGalaxyContract;
|
|
15764
15958
|
var init_me_galaxy = __esm(() => {
|
|
@@ -15971,6 +16165,7 @@ var init_me_saved = __esm(() => {
|
|
|
15971
16165
|
init_zod();
|
|
15972
16166
|
SavedFindingSchema = object({
|
|
15973
16167
|
artists: array(string2()),
|
|
16168
|
+
href: string2().optional(),
|
|
15974
16169
|
imageUrl: string2().optional(),
|
|
15975
16170
|
logId: string2().optional(),
|
|
15976
16171
|
note: string2().optional(),
|
|
@@ -16078,6 +16273,7 @@ var PrivateSubmissionSchema, ProfileBodySchema, getCurrentPrivateUser, getPrivat
|
|
|
16078
16273
|
var init_me2 = __esm(() => {
|
|
16079
16274
|
init_dist3();
|
|
16080
16275
|
init_zod();
|
|
16276
|
+
init_me_follows();
|
|
16081
16277
|
init_me_galaxy();
|
|
16082
16278
|
init_me_preferences();
|
|
16083
16279
|
init_me_recs();
|
|
@@ -16135,6 +16331,8 @@ var init_me2 = __esm(() => {
|
|
|
16135
16331
|
ok: literal(true),
|
|
16136
16332
|
summary: object({
|
|
16137
16333
|
credentials: string2(),
|
|
16334
|
+
followDigest: string2().optional(),
|
|
16335
|
+
follows: string2().optional(),
|
|
16138
16336
|
galaxyProgress: string2(),
|
|
16139
16337
|
preferences: string2().optional(),
|
|
16140
16338
|
recSeeds: string2().optional(),
|
|
@@ -16155,6 +16353,23 @@ var init_me2 = __esm(() => {
|
|
|
16155
16353
|
}).output(object({
|
|
16156
16354
|
export: object({
|
|
16157
16355
|
account: PublicUserSchema,
|
|
16356
|
+
followDigest: object({
|
|
16357
|
+
lastReleaseCount: number2().nullable(),
|
|
16358
|
+
lastSentAt: string2().nullable(),
|
|
16359
|
+
lastWeekKey: string2().nullable(),
|
|
16360
|
+
unsubscribedAt: string2().nullable(),
|
|
16361
|
+
updatedAt: string2()
|
|
16362
|
+
}).nullable().optional(),
|
|
16363
|
+
followDigestDeliveries: array(object({
|
|
16364
|
+
attempts: number2(),
|
|
16365
|
+
claimedAt: string2(),
|
|
16366
|
+
id: string2(),
|
|
16367
|
+
payloadJson: string2(),
|
|
16368
|
+
sentAt: string2().nullable(),
|
|
16369
|
+
status: string2(),
|
|
16370
|
+
weekKey: string2()
|
|
16371
|
+
})).optional(),
|
|
16372
|
+
follows: array(FollowSchema).optional(),
|
|
16158
16373
|
generatedAt: string2(),
|
|
16159
16374
|
id: string2(),
|
|
16160
16375
|
preferences: UserPreferencesSchema,
|
|
@@ -16298,6 +16513,7 @@ var init_me_watches = __esm(() => {
|
|
|
16298
16513
|
kind: unknown().optional()
|
|
16299
16514
|
});
|
|
16300
16515
|
listPrivateWatches = oc.route({
|
|
16516
|
+
deprecated: true,
|
|
16301
16517
|
method: "GET",
|
|
16302
16518
|
operationId: "listPrivateWatches",
|
|
16303
16519
|
path: "/me/watches",
|
|
@@ -16305,6 +16521,7 @@ var init_me_watches = __esm(() => {
|
|
|
16305
16521
|
tags: ["Me"]
|
|
16306
16522
|
}).output(object({ ok: literal(true), watches: array(WatchSchema) }));
|
|
16307
16523
|
savePrivateWatch = oc.route({
|
|
16524
|
+
deprecated: true,
|
|
16308
16525
|
method: "POST",
|
|
16309
16526
|
operationId: "savePrivateWatch",
|
|
16310
16527
|
path: "/me/watches",
|
|
@@ -16321,6 +16538,7 @@ var init_me_watches = __esm(() => {
|
|
|
16321
16538
|
})
|
|
16322
16539
|
}));
|
|
16323
16540
|
deletePrivateWatch = oc.route({
|
|
16541
|
+
deprecated: true,
|
|
16324
16542
|
method: "DELETE",
|
|
16325
16543
|
operationId: "deletePrivateWatch",
|
|
16326
16544
|
path: "/me/watches/{id}",
|
|
@@ -16838,6 +17056,7 @@ var init_orpc = __esm(() => {
|
|
|
16838
17056
|
init_admin_users();
|
|
16839
17057
|
init_devices();
|
|
16840
17058
|
init_editions();
|
|
17059
|
+
init_follow_digest();
|
|
16841
17060
|
init_health();
|
|
16842
17061
|
init_me2();
|
|
16843
17062
|
init_me_frontier();
|
|
@@ -16846,6 +17065,7 @@ var init_orpc = __esm(() => {
|
|
|
16846
17065
|
init_me_recs();
|
|
16847
17066
|
init_me_saved();
|
|
16848
17067
|
init_me_sets();
|
|
17068
|
+
init_me_follows();
|
|
16849
17069
|
init_me_watches();
|
|
16850
17070
|
init_mix();
|
|
16851
17071
|
init_mixtapes2();
|
|
@@ -16858,6 +17078,7 @@ var init_orpc = __esm(() => {
|
|
|
16858
17078
|
init_submissions();
|
|
16859
17079
|
init_tracks();
|
|
16860
17080
|
init_albums2();
|
|
17081
|
+
init_follow_digest();
|
|
16861
17082
|
init_artists2();
|
|
16862
17083
|
init_labels2();
|
|
16863
17084
|
init_mix();
|
|
@@ -16908,6 +17129,7 @@ var init_orpc = __esm(() => {
|
|
|
16908
17129
|
init_me_recs();
|
|
16909
17130
|
init_me_saved();
|
|
16910
17131
|
init_me_sets();
|
|
17132
|
+
init_me_follows();
|
|
16911
17133
|
init_me_watches();
|
|
16912
17134
|
init_mixtapes2();
|
|
16913
17135
|
init_newsletter();
|
|
@@ -16946,6 +17168,7 @@ var init_orpc = __esm(() => {
|
|
|
16946
17168
|
...adminFunnelContract,
|
|
16947
17169
|
...adminHealthContract,
|
|
16948
17170
|
...adminHubCountsContract,
|
|
17171
|
+
...followDigestContract,
|
|
16949
17172
|
...adminLabelsContract,
|
|
16950
17173
|
...adminLogbookContract,
|
|
16951
17174
|
...adminMigrationsContract,
|
|
@@ -16972,6 +17195,7 @@ var init_orpc = __esm(() => {
|
|
|
16972
17195
|
...meRecsContract,
|
|
16973
17196
|
...meSavedContract,
|
|
16974
17197
|
...meSetsContract,
|
|
17198
|
+
...meFollowsContract,
|
|
16975
17199
|
...meWatchesContract,
|
|
16976
17200
|
...mixContract,
|
|
16977
17201
|
...mixtapesContract,
|
|
@@ -17883,6 +18107,22 @@ var init_publish = __esm(() => {
|
|
|
17883
18107
|
init_api();
|
|
17884
18108
|
});
|
|
17885
18109
|
|
|
18110
|
+
// src/commands/digests.ts
|
|
18111
|
+
async function sendFollowDigestsCommand(options) {
|
|
18112
|
+
return adminApiPost("/api/v1/admin/follow-digests/send", options);
|
|
18113
|
+
}
|
|
18114
|
+
async function getFollowDigestStateCommand() {
|
|
18115
|
+
const result = await adminApiGet("/api/v1/admin/follow-digests/state");
|
|
18116
|
+
return result.paused;
|
|
18117
|
+
}
|
|
18118
|
+
async function setFollowDigestStateCommand(paused) {
|
|
18119
|
+
const result = await adminApiPut("/api/v1/admin/follow-digests/state", { paused });
|
|
18120
|
+
return result.paused;
|
|
18121
|
+
}
|
|
18122
|
+
var init_digests = __esm(() => {
|
|
18123
|
+
init_api();
|
|
18124
|
+
});
|
|
18125
|
+
|
|
17886
18126
|
// src/commands/capture.ts
|
|
17887
18127
|
async function captureBudgetCommand() {
|
|
17888
18128
|
return adminApiGet("/api/v1/admin/catalogue/capture-budget");
|
|
@@ -21816,7 +22056,7 @@ function artistRuleLines(rules) {
|
|
|
21816
22056
|
}
|
|
21817
22057
|
function createProgram() {
|
|
21818
22058
|
const program = configureCommand(new Command);
|
|
21819
|
-
program.name("fluncle").description(fluncleTagline
|
|
22059
|
+
program.name("fluncle").description(fluncleTagline).option("--env <local|production>", "Config profile to load (default: production)").showSuggestionAfterError(false).addHelpCommand("help [command]", "Display help for command").hook("preAction", (_thisCommand, actionCommand) => {
|
|
21820
22060
|
const options = actionCommand.optsWithGlobals();
|
|
21821
22061
|
setEnvProfile(options.env);
|
|
21822
22062
|
}).addHelpText("before", `
|
|
@@ -21857,7 +22097,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
21857
22097
|
await notifyIfUpdateAvailable(args);
|
|
21858
22098
|
}
|
|
21859
22099
|
function configureCommand(command) {
|
|
21860
|
-
return command.exitOverride().addHelpCommand(false).configureOutput({
|
|
22100
|
+
return command.exitOverride().helpOption("-h, --help", "Display help for command").addHelpCommand(false).configureOutput({
|
|
21861
22101
|
writeErr: () => {}
|
|
21862
22102
|
});
|
|
21863
22103
|
}
|
|
@@ -21906,7 +22146,7 @@ function addListenCommands(program) {
|
|
|
21906
22146
|
const openCommands = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
21907
22147
|
await runOpen(target, [], options, openCommands);
|
|
21908
22148
|
});
|
|
21909
|
-
program.command("random").description("The archive throws
|
|
22149
|
+
program.command("random").description("The archive throws a banger back").option("--json", "Print JSON", false).action(async (options) => {
|
|
21910
22150
|
await Promise.resolve().then(() => init_random());
|
|
21911
22151
|
await runRandom(options, randomCommand);
|
|
21912
22152
|
});
|
|
@@ -21968,7 +22208,7 @@ function addAdminCommands(program) {
|
|
|
21968
22208
|
admin.action(() => {
|
|
21969
22209
|
admin.outputHelp();
|
|
21970
22210
|
});
|
|
21971
|
-
admin.command("help", { hidden: true }).description("
|
|
22211
|
+
admin.command("help", { hidden: true }).description("Display help for command").action(() => {
|
|
21972
22212
|
admin.outputHelp();
|
|
21973
22213
|
});
|
|
21974
22214
|
admin.command("queue").description("The attention queue: what's waiting, and the day's dispatch").option("--json", "Print JSON", false).action(async (options) => {
|
|
@@ -22441,6 +22681,44 @@ JSON field reference:
|
|
|
22441
22681
|
await Promise.resolve().then(() => init_publish());
|
|
22442
22682
|
await runPublishAdvancePause(false, options, publishAdvancePauseCommand);
|
|
22443
22683
|
});
|
|
22684
|
+
const adminFollowDigests = configureCommand(admin.command("digests").description("Weekly email digest for followed artists and labels"));
|
|
22685
|
+
adminFollowDigests.action(() => adminFollowDigests.outputHelp());
|
|
22686
|
+
adminFollowDigests.command("status").description("Read the follow digest kill switch").option("--json", "Print JSON", false).action(async (options) => {
|
|
22687
|
+
await Promise.resolve().then(() => init_digests());
|
|
22688
|
+
const paused = await getFollowDigestStateCommand();
|
|
22689
|
+
if (options.json) {
|
|
22690
|
+
printJson({ ok: true, paused });
|
|
22691
|
+
} else {
|
|
22692
|
+
console.log(paused ? "Follow digests are paused." : "Follow digests are running.");
|
|
22693
|
+
}
|
|
22694
|
+
});
|
|
22695
|
+
for (const [verb, paused] of [
|
|
22696
|
+
["pause", true],
|
|
22697
|
+
["resume", false]
|
|
22698
|
+
]) {
|
|
22699
|
+
adminFollowDigests.command(verb).description(paused ? "Pause follow digests" : "Resume follow digests").option("--json", "Print JSON", false).action(async (options) => {
|
|
22700
|
+
await Promise.resolve().then(() => init_digests());
|
|
22701
|
+
const result = await setFollowDigestStateCommand(paused);
|
|
22702
|
+
if (options.json) {
|
|
22703
|
+
printJson({ ok: true, paused: result });
|
|
22704
|
+
} else {
|
|
22705
|
+
console.log(result ? "Follow digests are paused." : "Follow digests are running.");
|
|
22706
|
+
}
|
|
22707
|
+
});
|
|
22708
|
+
}
|
|
22709
|
+
adminFollowDigests.command("send").description("Send one bounded follow digest batch").option("--cursor <id>", "Continue after this user id").option("--limit <number>", "Maximum users to consider").option("--dry-run", "Count eligible emails without sending").option("--json", "Print JSON", false).action(async (options) => {
|
|
22710
|
+
await Promise.resolve().then(() => init_digests());
|
|
22711
|
+
const result = await sendFollowDigestsCommand({
|
|
22712
|
+
cursor: options.cursor,
|
|
22713
|
+
dryRun: options.dryRun,
|
|
22714
|
+
limit: options.limit === undefined ? undefined : Number(options.limit)
|
|
22715
|
+
});
|
|
22716
|
+
if (options.json) {
|
|
22717
|
+
printJson(result);
|
|
22718
|
+
} else {
|
|
22719
|
+
console.log(`Considered ${result.considered}; sent ${result.sent}; empty ${result.empty}; next ${result.nextCursor ?? "done"}.`);
|
|
22720
|
+
}
|
|
22721
|
+
});
|
|
22444
22722
|
const adminCapture = configureCommand(admin.command("capture").description("The metered audio-capture budget and its kill switch"));
|
|
22445
22723
|
adminCapture.action(() => {
|
|
22446
22724
|
adminCapture.outputHelp();
|
|
@@ -26243,7 +26521,7 @@ Listen:
|
|
|
26243
26521
|
fluncle open [--limit 20] [--browser|--app] Pick a track, open it in Spotify
|
|
26244
26522
|
fluncle open playlist [--browser|--app] Open Fluncle's Findings in Spotify
|
|
26245
26523
|
fluncle open telegram [--browser|--app] Open the Telegram feed
|
|
26246
|
-
fluncle random [--json] The archive throws
|
|
26524
|
+
fluncle random [--json] The archive throws a banger back
|
|
26247
26525
|
fluncle subscribe [email] Fresh bangers, every Friday
|
|
26248
26526
|
|
|
26249
26527
|
Browse:
|
package/package.json
CHANGED