fluncle 0.76.0 → 0.77.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 +201 -10
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -544,7 +544,7 @@ function parseVersion(version) {
|
|
|
544
544
|
var currentVersion;
|
|
545
545
|
var init_version = __esm(() => {
|
|
546
546
|
init_output();
|
|
547
|
-
currentVersion = "0.
|
|
547
|
+
currentVersion = "0.77.0".trim() ? "0.77.0".trim() : "0.1.0";
|
|
548
548
|
});
|
|
549
549
|
|
|
550
550
|
// src/update-notifier.ts
|
|
@@ -1029,6 +1029,7 @@ var init_mixtape_api = __esm(() => {
|
|
|
1029
1029
|
// src/commands/mixtape-youtube.ts
|
|
1030
1030
|
var exports_mixtape_youtube = {};
|
|
1031
1031
|
__export(exports_mixtape_youtube, {
|
|
1032
|
+
resyncYoutube: () => resyncYoutube,
|
|
1032
1033
|
publishYoutubeCommand: () => publishYoutubeCommand,
|
|
1033
1034
|
nextOffset: () => nextOffset,
|
|
1034
1035
|
distributeYoutube: () => distributeYoutube,
|
|
@@ -1084,6 +1085,10 @@ async function publishYoutubeCommand(idOrLogId) {
|
|
|
1084
1085
|
const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
|
|
1085
1086
|
return { url: response.url };
|
|
1086
1087
|
}
|
|
1088
|
+
async function resyncYoutube(mixtapeId) {
|
|
1089
|
+
const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
|
|
1090
|
+
return { url: response.url, videoId: response.videoId };
|
|
1091
|
+
}
|
|
1087
1092
|
async function authYoutubeCommand() {
|
|
1088
1093
|
const response = await adminApiGet("/api/admin/youtube/auth/start");
|
|
1089
1094
|
console.log(`Open this YouTube authorization URL:
|
|
@@ -1189,8 +1194,11 @@ var init_mixtape_youtube = __esm(() => {
|
|
|
1189
1194
|
// src/commands/mixtape-mixcloud.ts
|
|
1190
1195
|
var exports_mixtape_mixcloud = {};
|
|
1191
1196
|
__export(exports_mixtape_mixcloud, {
|
|
1197
|
+
resyncMixcloud: () => resyncMixcloud,
|
|
1192
1198
|
mixtapeDescription: () => mixtapeDescription,
|
|
1193
1199
|
mixcloudSections: () => mixcloudSections,
|
|
1200
|
+
mixcloudSectionFields: () => mixcloudSectionFields,
|
|
1201
|
+
mixcloudEditUrl: () => mixcloudEditUrl,
|
|
1194
1202
|
distributeMixcloud: () => distributeMixcloud,
|
|
1195
1203
|
authMixcloudCommand: () => authMixcloudCommand
|
|
1196
1204
|
});
|
|
@@ -1218,10 +1226,8 @@ async function distributeMixcloud(mixtapeId, audioPath, onProgress, unlisted = f
|
|
|
1218
1226
|
form.append(`tags-${index}-tag`, tag);
|
|
1219
1227
|
}
|
|
1220
1228
|
const sections = mixcloudSections(mixtape.members);
|
|
1221
|
-
for (const [
|
|
1222
|
-
form.append(
|
|
1223
|
-
form.append(`sections-${index}-song`, section.song);
|
|
1224
|
-
form.append(`sections-${index}-start_time`, String(section.start_time));
|
|
1229
|
+
for (const [name, value] of mixcloudSectionFields(sections)) {
|
|
1230
|
+
form.append(name, value);
|
|
1225
1231
|
}
|
|
1226
1232
|
if (unlisted) {
|
|
1227
1233
|
form.append("unlisted", "1");
|
|
@@ -1253,6 +1259,35 @@ async function distributeMixcloud(mixtapeId, audioPath, onProgress, unlisted = f
|
|
|
1253
1259
|
});
|
|
1254
1260
|
return { url };
|
|
1255
1261
|
}
|
|
1262
|
+
async function resyncMixcloud(mixtapeId, onProgress) {
|
|
1263
|
+
const token = await fetchMixcloudToken();
|
|
1264
|
+
const mixtape = await mixtapeGetCommand(mixtapeId);
|
|
1265
|
+
const sections = mixcloudSections(mixtape.members);
|
|
1266
|
+
if (sections.length === 0) {
|
|
1267
|
+
throw new CliError2("mixcloud_no_cues", "No cued members to sync — mark cues on the mixtape first.");
|
|
1268
|
+
}
|
|
1269
|
+
const social = await adminApiGet(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
|
|
1270
|
+
const mixcloud = social.posts.find((post) => post.platform === "mixcloud");
|
|
1271
|
+
const key = mixcloud?.externalId;
|
|
1272
|
+
if (!key) {
|
|
1273
|
+
throw new CliError2("mixcloud_not_distributed", "No Mixcloud cloudcast to re-sync — distribute the mixtape first.");
|
|
1274
|
+
}
|
|
1275
|
+
const form = new FormData;
|
|
1276
|
+
for (const [name, value] of mixcloudSectionFields(sections)) {
|
|
1277
|
+
form.append(name, value);
|
|
1278
|
+
}
|
|
1279
|
+
onProgress?.(`Mixcloud: re-syncing ${sections.length} sections (no re-upload)…`);
|
|
1280
|
+
const response = await fetch(`${mixcloudEditUrl(key)}?access_token=${encodeURIComponent(token)}`, { body: form, method: "POST" });
|
|
1281
|
+
const text = await response.text();
|
|
1282
|
+
if (!response.ok) {
|
|
1283
|
+
throwMixcloudError(response.status, text);
|
|
1284
|
+
}
|
|
1285
|
+
const result = parseUploadResult(text);
|
|
1286
|
+
if (!result.success) {
|
|
1287
|
+
throw new CliError2("mixcloud_edit_rejected", `Mixcloud rejected the section edit: ${result.message ?? text.slice(0, 300)}`);
|
|
1288
|
+
}
|
|
1289
|
+
return { url: mixcloud?.url ?? `https://www.mixcloud.com${key}` };
|
|
1290
|
+
}
|
|
1256
1291
|
async function authMixcloudCommand() {
|
|
1257
1292
|
const response = await adminApiGet("/api/admin/mixcloud/auth/start");
|
|
1258
1293
|
console.log(`Open this Mixcloud authorization URL:
|
|
@@ -1283,6 +1318,18 @@ function mixcloudSections(members) {
|
|
|
1283
1318
|
start_time: Math.floor(member.startMs / 1000)
|
|
1284
1319
|
}));
|
|
1285
1320
|
}
|
|
1321
|
+
function mixcloudSectionFields(sections) {
|
|
1322
|
+
return sections.flatMap((section, index) => [
|
|
1323
|
+
[`sections-${index}-artist`, section.artist],
|
|
1324
|
+
[`sections-${index}-song`, section.song],
|
|
1325
|
+
[`sections-${index}-start_time`, String(section.start_time)]
|
|
1326
|
+
]);
|
|
1327
|
+
}
|
|
1328
|
+
function mixcloudEditUrl(key) {
|
|
1329
|
+
const withLeading = key.startsWith("/") ? key : `/${key}`;
|
|
1330
|
+
const path2 = withLeading.endsWith("/") ? withLeading : `${withLeading}/`;
|
|
1331
|
+
return `${MIXCLOUD_API}/upload${path2}edit/`;
|
|
1332
|
+
}
|
|
1286
1333
|
function mixtapeTags(_mixtape) {
|
|
1287
1334
|
return ["Drum & Bass", "Fluncle"];
|
|
1288
1335
|
}
|
|
@@ -1509,6 +1556,7 @@ var exports_mixtapes = {};
|
|
|
1509
1556
|
__export(exports_mixtapes, {
|
|
1510
1557
|
mixtapesCommand: () => mixtapesCommand,
|
|
1511
1558
|
mixtapeUpdateCommand: () => mixtapeUpdateCommand,
|
|
1559
|
+
mixtapeResyncCommand: () => mixtapeResyncCommand,
|
|
1512
1560
|
mixtapePublishCommand: () => mixtapePublishCommand,
|
|
1513
1561
|
mixtapeMembersCommand: () => mixtapeMembersCommand,
|
|
1514
1562
|
mixtapeListCommand: () => mixtapeListCommand,
|
|
@@ -1615,6 +1663,44 @@ async function mixtapeDistributeCommand(idOrLogId, options, onProgress = () => {
|
|
|
1615
1663
|
}
|
|
1616
1664
|
return { logId, mixtapeId, results };
|
|
1617
1665
|
}
|
|
1666
|
+
async function mixtapeResyncCommand(idOrLogId, options, onProgress = () => {}) {
|
|
1667
|
+
const mixtape = await mixtapeGetCommand(idOrLogId);
|
|
1668
|
+
if (!mixtape.id) {
|
|
1669
|
+
throw new CliError2("mixtape_not_found", `No mixtape with id or log id ${idOrLogId}`);
|
|
1670
|
+
}
|
|
1671
|
+
if (!mixtape.logId) {
|
|
1672
|
+
throw new CliError2("mixtape_no_log_id", "The mixtape isn't published yet — distribute it before re-syncing.");
|
|
1673
|
+
}
|
|
1674
|
+
const mixtapeId = mixtape.id;
|
|
1675
|
+
const explicit = Boolean(options.youtube) || Boolean(options.mixcloud);
|
|
1676
|
+
let doYoutube = Boolean(options.youtube);
|
|
1677
|
+
let doMixcloud = Boolean(options.mixcloud);
|
|
1678
|
+
if (!explicit) {
|
|
1679
|
+
const social = await adminApiGet(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
|
|
1680
|
+
const platforms = new Set(social.posts.map((post) => post.platform));
|
|
1681
|
+
doYoutube = platforms.has("youtube");
|
|
1682
|
+
doMixcloud = platforms.has("mixcloud");
|
|
1683
|
+
if (!doYoutube && !doMixcloud) {
|
|
1684
|
+
throw new CliError2("mixtape_not_distributed", "The mixtape has no YouTube or Mixcloud link to re-sync.");
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
const results = [];
|
|
1688
|
+
if (doYoutube) {
|
|
1689
|
+
onProgress("YouTube: re-syncing description + chapters…");
|
|
1690
|
+
const { resyncYoutube: resyncYoutube2 } = await Promise.resolve().then(() => (init_mixtape_youtube(), exports_mixtape_youtube));
|
|
1691
|
+
const result = await resyncYoutube2(mixtapeId);
|
|
1692
|
+
results.push({ platform: "youtube", url: result.url });
|
|
1693
|
+
onProgress(`YouTube: ${result.url}`);
|
|
1694
|
+
}
|
|
1695
|
+
if (doMixcloud) {
|
|
1696
|
+
onProgress("Mixcloud: re-syncing sections…");
|
|
1697
|
+
const { resyncMixcloud: resyncMixcloud2 } = await Promise.resolve().then(() => (init_mixtape_mixcloud(), exports_mixtape_mixcloud));
|
|
1698
|
+
const result = await resyncMixcloud2(mixtapeId, onProgress);
|
|
1699
|
+
results.push({ platform: "mixcloud", url: result.url });
|
|
1700
|
+
onProgress(`Mixcloud: ${result.url}`);
|
|
1701
|
+
}
|
|
1702
|
+
return { logId: mixtape.logId, mixtapeId, results };
|
|
1703
|
+
}
|
|
1618
1704
|
async function probeDurationMs(filePath) {
|
|
1619
1705
|
try {
|
|
1620
1706
|
const proc = Bun.spawn(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", filePath], { stderr: "ignore", stdout: "pipe" });
|
|
@@ -2401,7 +2487,7 @@ function parseVersion2(version) {
|
|
|
2401
2487
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2402
2488
|
var init_version2 = __esm(() => {
|
|
2403
2489
|
init_output();
|
|
2404
|
-
currentVersion2 = "0.
|
|
2490
|
+
currentVersion2 = "0.77.0".trim() ? "0.77.0".trim() : "0.1.0";
|
|
2405
2491
|
});
|
|
2406
2492
|
|
|
2407
2493
|
// ../../packages/registry/src/index.ts
|
|
@@ -3626,6 +3712,7 @@ var init_preview_archive = __esm(() => {
|
|
|
3626
3712
|
// src/commands/mixtape-youtube.ts
|
|
3627
3713
|
var exports_mixtape_youtube2 = {};
|
|
3628
3714
|
__export(exports_mixtape_youtube2, {
|
|
3715
|
+
resyncYoutube: () => resyncYoutube2,
|
|
3629
3716
|
publishYoutubeCommand: () => publishYoutubeCommand2,
|
|
3630
3717
|
nextOffset: () => nextOffset2,
|
|
3631
3718
|
distributeYoutube: () => distributeYoutube2,
|
|
@@ -3681,6 +3768,10 @@ async function publishYoutubeCommand2(idOrLogId) {
|
|
|
3681
3768
|
const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
|
|
3682
3769
|
return { url: response.url };
|
|
3683
3770
|
}
|
|
3771
|
+
async function resyncYoutube2(mixtapeId) {
|
|
3772
|
+
const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
|
|
3773
|
+
return { url: response.url, videoId: response.videoId };
|
|
3774
|
+
}
|
|
3684
3775
|
async function authYoutubeCommand2() {
|
|
3685
3776
|
const response = await adminApiGet("/api/admin/youtube/auth/start");
|
|
3686
3777
|
console.log(`Open this YouTube authorization URL:
|
|
@@ -3788,6 +3879,7 @@ var exports_mixtapes2 = {};
|
|
|
3788
3879
|
__export(exports_mixtapes2, {
|
|
3789
3880
|
mixtapesCommand: () => mixtapesCommand2,
|
|
3790
3881
|
mixtapeUpdateCommand: () => mixtapeUpdateCommand2,
|
|
3882
|
+
mixtapeResyncCommand: () => mixtapeResyncCommand2,
|
|
3791
3883
|
mixtapePublishCommand: () => mixtapePublishCommand2,
|
|
3792
3884
|
mixtapeMembersCommand: () => mixtapeMembersCommand2,
|
|
3793
3885
|
mixtapeListCommand: () => mixtapeListCommand,
|
|
@@ -3894,6 +3986,44 @@ async function mixtapeDistributeCommand2(idOrLogId, options, onProgress = () =>
|
|
|
3894
3986
|
}
|
|
3895
3987
|
return { logId, mixtapeId, results };
|
|
3896
3988
|
}
|
|
3989
|
+
async function mixtapeResyncCommand2(idOrLogId, options, onProgress = () => {}) {
|
|
3990
|
+
const mixtape = await mixtapeGetCommand(idOrLogId);
|
|
3991
|
+
if (!mixtape.id) {
|
|
3992
|
+
throw new CliError2("mixtape_not_found", `No mixtape with id or log id ${idOrLogId}`);
|
|
3993
|
+
}
|
|
3994
|
+
if (!mixtape.logId) {
|
|
3995
|
+
throw new CliError2("mixtape_no_log_id", "The mixtape isn't published yet — distribute it before re-syncing.");
|
|
3996
|
+
}
|
|
3997
|
+
const mixtapeId = mixtape.id;
|
|
3998
|
+
const explicit = Boolean(options.youtube) || Boolean(options.mixcloud);
|
|
3999
|
+
let doYoutube = Boolean(options.youtube);
|
|
4000
|
+
let doMixcloud = Boolean(options.mixcloud);
|
|
4001
|
+
if (!explicit) {
|
|
4002
|
+
const social = await adminApiGet(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
|
|
4003
|
+
const platforms = new Set(social.posts.map((post) => post.platform));
|
|
4004
|
+
doYoutube = platforms.has("youtube");
|
|
4005
|
+
doMixcloud = platforms.has("mixcloud");
|
|
4006
|
+
if (!doYoutube && !doMixcloud) {
|
|
4007
|
+
throw new CliError2("mixtape_not_distributed", "The mixtape has no YouTube or Mixcloud link to re-sync.");
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
const results = [];
|
|
4011
|
+
if (doYoutube) {
|
|
4012
|
+
onProgress("YouTube: re-syncing description + chapters…");
|
|
4013
|
+
const { resyncYoutube: resyncYoutube3 } = await Promise.resolve().then(() => (init_mixtape_youtube(), exports_mixtape_youtube));
|
|
4014
|
+
const result = await resyncYoutube3(mixtapeId);
|
|
4015
|
+
results.push({ platform: "youtube", url: result.url });
|
|
4016
|
+
onProgress(`YouTube: ${result.url}`);
|
|
4017
|
+
}
|
|
4018
|
+
if (doMixcloud) {
|
|
4019
|
+
onProgress("Mixcloud: re-syncing sections…");
|
|
4020
|
+
const { resyncMixcloud: resyncMixcloud2 } = await Promise.resolve().then(() => (init_mixtape_mixcloud(), exports_mixtape_mixcloud));
|
|
4021
|
+
const result = await resyncMixcloud2(mixtapeId, onProgress);
|
|
4022
|
+
results.push({ platform: "mixcloud", url: result.url });
|
|
4023
|
+
onProgress(`Mixcloud: ${result.url}`);
|
|
4024
|
+
}
|
|
4025
|
+
return { logId: mixtape.logId, mixtapeId, results };
|
|
4026
|
+
}
|
|
3897
4027
|
async function probeDurationMs2(filePath) {
|
|
3898
4028
|
try {
|
|
3899
4029
|
const proc = Bun.spawn(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", filePath], { stderr: "ignore", stdout: "pipe" });
|
|
@@ -4480,8 +4610,11 @@ var init_auth = __esm(() => {
|
|
|
4480
4610
|
// src/commands/mixtape-mixcloud.ts
|
|
4481
4611
|
var exports_mixtape_mixcloud2 = {};
|
|
4482
4612
|
__export(exports_mixtape_mixcloud2, {
|
|
4613
|
+
resyncMixcloud: () => resyncMixcloud2,
|
|
4483
4614
|
mixtapeDescription: () => mixtapeDescription2,
|
|
4484
4615
|
mixcloudSections: () => mixcloudSections2,
|
|
4616
|
+
mixcloudSectionFields: () => mixcloudSectionFields2,
|
|
4617
|
+
mixcloudEditUrl: () => mixcloudEditUrl2,
|
|
4485
4618
|
distributeMixcloud: () => distributeMixcloud2,
|
|
4486
4619
|
authMixcloudCommand: () => authMixcloudCommand2
|
|
4487
4620
|
});
|
|
@@ -4509,10 +4642,8 @@ async function distributeMixcloud2(mixtapeId, audioPath, onProgress, unlisted =
|
|
|
4509
4642
|
form.append(`tags-${index}-tag`, tag);
|
|
4510
4643
|
}
|
|
4511
4644
|
const sections = mixcloudSections2(mixtape.members);
|
|
4512
|
-
for (const [
|
|
4513
|
-
form.append(
|
|
4514
|
-
form.append(`sections-${index}-song`, section.song);
|
|
4515
|
-
form.append(`sections-${index}-start_time`, String(section.start_time));
|
|
4645
|
+
for (const [name, value] of mixcloudSectionFields2(sections)) {
|
|
4646
|
+
form.append(name, value);
|
|
4516
4647
|
}
|
|
4517
4648
|
if (unlisted) {
|
|
4518
4649
|
form.append("unlisted", "1");
|
|
@@ -4544,6 +4675,35 @@ async function distributeMixcloud2(mixtapeId, audioPath, onProgress, unlisted =
|
|
|
4544
4675
|
});
|
|
4545
4676
|
return { url };
|
|
4546
4677
|
}
|
|
4678
|
+
async function resyncMixcloud2(mixtapeId, onProgress) {
|
|
4679
|
+
const token = await fetchMixcloudToken2();
|
|
4680
|
+
const mixtape = await mixtapeGetCommand(mixtapeId);
|
|
4681
|
+
const sections = mixcloudSections2(mixtape.members);
|
|
4682
|
+
if (sections.length === 0) {
|
|
4683
|
+
throw new CliError2("mixcloud_no_cues", "No cued members to sync — mark cues on the mixtape first.");
|
|
4684
|
+
}
|
|
4685
|
+
const social = await adminApiGet(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
|
|
4686
|
+
const mixcloud = social.posts.find((post) => post.platform === "mixcloud");
|
|
4687
|
+
const key = mixcloud?.externalId;
|
|
4688
|
+
if (!key) {
|
|
4689
|
+
throw new CliError2("mixcloud_not_distributed", "No Mixcloud cloudcast to re-sync — distribute the mixtape first.");
|
|
4690
|
+
}
|
|
4691
|
+
const form = new FormData;
|
|
4692
|
+
for (const [name, value] of mixcloudSectionFields2(sections)) {
|
|
4693
|
+
form.append(name, value);
|
|
4694
|
+
}
|
|
4695
|
+
onProgress?.(`Mixcloud: re-syncing ${sections.length} sections (no re-upload)…`);
|
|
4696
|
+
const response = await fetch(`${mixcloudEditUrl2(key)}?access_token=${encodeURIComponent(token)}`, { body: form, method: "POST" });
|
|
4697
|
+
const text = await response.text();
|
|
4698
|
+
if (!response.ok) {
|
|
4699
|
+
throwMixcloudError2(response.status, text);
|
|
4700
|
+
}
|
|
4701
|
+
const result = parseUploadResult2(text);
|
|
4702
|
+
if (!result.success) {
|
|
4703
|
+
throw new CliError2("mixcloud_edit_rejected", `Mixcloud rejected the section edit: ${result.message ?? text.slice(0, 300)}`);
|
|
4704
|
+
}
|
|
4705
|
+
return { url: mixcloud?.url ?? `https://www.mixcloud.com${key}` };
|
|
4706
|
+
}
|
|
4547
4707
|
async function authMixcloudCommand2() {
|
|
4548
4708
|
const response = await adminApiGet("/api/admin/mixcloud/auth/start");
|
|
4549
4709
|
console.log(`Open this Mixcloud authorization URL:
|
|
@@ -4574,6 +4734,18 @@ function mixcloudSections2(members) {
|
|
|
4574
4734
|
start_time: Math.floor(member.startMs / 1000)
|
|
4575
4735
|
}));
|
|
4576
4736
|
}
|
|
4737
|
+
function mixcloudSectionFields2(sections) {
|
|
4738
|
+
return sections.flatMap((section, index) => [
|
|
4739
|
+
[`sections-${index}-artist`, section.artist],
|
|
4740
|
+
[`sections-${index}-song`, section.song],
|
|
4741
|
+
[`sections-${index}-start_time`, String(section.start_time)]
|
|
4742
|
+
]);
|
|
4743
|
+
}
|
|
4744
|
+
function mixcloudEditUrl2(key) {
|
|
4745
|
+
const withLeading = key.startsWith("/") ? key : `/${key}`;
|
|
4746
|
+
const path2 = withLeading.endsWith("/") ? withLeading : `${withLeading}/`;
|
|
4747
|
+
return `${MIXCLOUD_API2}/upload${path2}edit/`;
|
|
4748
|
+
}
|
|
4577
4749
|
function mixtapeTags2(_mixtape) {
|
|
4578
4750
|
return ["Drum & Bass", "Fluncle"];
|
|
4579
4751
|
}
|
|
@@ -7295,6 +7467,10 @@ function addAdminCommands(program2) {
|
|
|
7295
7467
|
const { publishYoutubeCommand: publishYoutubeCommand3 } = await Promise.resolve().then(() => (init_mixtape_youtube2(), exports_mixtape_youtube2));
|
|
7296
7468
|
await runMixtapePublishYoutube(idOrLogId, options, publishYoutubeCommand3);
|
|
7297
7469
|
});
|
|
7470
|
+
adminMixtapes.command("resync").description("Re-push a published mixtape's YouTube chapters + Mixcloud sections from its current cues (no re-upload)").argument("[idOrLogId]").option("--youtube", "Only re-sync YouTube").option("--mixcloud", "Only re-sync Mixcloud").option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
|
|
7471
|
+
const { mixtapeResyncCommand: mixtapeResyncCommand3 } = await Promise.resolve().then(() => (init_mixtapes(), exports_mixtapes));
|
|
7472
|
+
await runMixtapeResync(idOrLogId, options, mixtapeResyncCommand3);
|
|
7473
|
+
});
|
|
7298
7474
|
const adminClips = configureCommand(admin.command("clips").description("Mixtape clip (Fluncle Studio) commands"));
|
|
7299
7475
|
adminClips.action(() => {
|
|
7300
7476
|
adminClips.outputHelp();
|
|
@@ -7854,6 +8030,21 @@ async function runMixtapePublishYoutube(idOrLogId, options, publishYoutubeComman
|
|
|
7854
8030
|
}
|
|
7855
8031
|
console.log(`YouTube video is now public: ${result.url}`);
|
|
7856
8032
|
}
|
|
8033
|
+
async function runMixtapeResync(idOrLogId, options, mixtapeResyncCommand3) {
|
|
8034
|
+
if (!idOrLogId) {
|
|
8035
|
+
throw new Error("Missing mixtape id. Usage: fluncle admin mixtapes resync <idOrLogId>");
|
|
8036
|
+
}
|
|
8037
|
+
const onProgress = options.json ? () => {} : (message) => console.log(message);
|
|
8038
|
+
const result = await mixtapeResyncCommand3(idOrLogId, options, onProgress);
|
|
8039
|
+
if (options.json) {
|
|
8040
|
+
printJson(result);
|
|
8041
|
+
return;
|
|
8042
|
+
}
|
|
8043
|
+
const links = result.results.map((r) => ` ${r.platform}: ${r.url}`).join(`
|
|
8044
|
+
`);
|
|
8045
|
+
console.log(`Re-synced ${result.logId} (fluncle://${result.logId}).
|
|
8046
|
+
${links}`);
|
|
8047
|
+
}
|
|
7857
8048
|
async function runMixtapeDelete(id, options, mixtapeDeleteCommand3) {
|
|
7858
8049
|
if (!id) {
|
|
7859
8050
|
throw new Error("Missing mixtape id. Usage: fluncle admin mixtapes delete <id> --yes");
|
package/package.json
CHANGED