@stage5/lumine 0.2.98 → 0.2.99

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/lib/admin.js CHANGED
@@ -1935,6 +1935,44 @@ export function parseAdminOperation(options) {
1935
1935
  if (note.length > 1000) {
1936
1936
  throw cliValidationError("--note must be at most 1000 characters.");
1937
1937
  }
1938
+ if (action === "story" || action === "stories") {
1939
+ // A crew's Bridge Builder story page: Mikey's final approval (the
1940
+ // admin bar on the story page does the same). Publishing copies only
1941
+ // the photos/clips every tagged member's parent allowed.
1942
+ const storyUsage =
1943
+ "Usage: lumine admin meetup story list | show <crewId> | approve <crewId> [--note <text>] [--no-announce] | send-back <crewId> --note <text> | unpublish <crewId> --note <text>.";
1944
+ const storyAction = target || "list";
1945
+ if (storyAction === "list") {
1946
+ return readOperation("meetup.story.list", "/cli/admin/meetup-quest/stories", {
1947
+ requiresRun: false,
1948
+ });
1949
+ }
1950
+ if (!["show", "approve", "send-back", "unpublish"].includes(storyAction)) {
1951
+ throw cliValidationError(storyUsage);
1952
+ }
1953
+ const crewId = parseRequiredInteger(extra, "Crew ID", 1);
1954
+ if (storyAction === "show") {
1955
+ return readOperation(
1956
+ "meetup.story.show",
1957
+ `/cli/admin/meetup-quest/stories/by-crew/${crewId}`,
1958
+ { requiresRun: false },
1959
+ );
1960
+ }
1961
+ if (storyAction !== "approve" && !note) {
1962
+ throw cliValidationError(
1963
+ `lumine admin meetup story ${storyAction} <crewId> needs --note <text> (the crew sees it).`,
1964
+ );
1965
+ }
1966
+ return writeOperation(
1967
+ `meetup.story.${storyAction}`,
1968
+ "POST",
1969
+ `/cli/admin/meetup-quest/stories/by-crew/${crewId}/${storyAction}`,
1970
+ storyAction === "approve"
1971
+ ? { note, announce: !options.adminNoAnnounce }
1972
+ : { note },
1973
+ { requiresRun: false },
1974
+ );
1975
+ }
1938
1976
  if (!action || action === "list") {
1939
1977
  return readOperation(
1940
1978
  "meetup.list",
@@ -4892,6 +4930,49 @@ function printMeetupCrew(crew) {
4892
4930
  }
4893
4931
 
4894
4932
  function printMeetupResult({ operation, data, result }) {
4933
+ if (operation.name === "meetup.story.list") {
4934
+ const stories = Array.isArray(data.stories) ? data.stories : [];
4935
+ console.log(`${stories.length} Bridge Builder stor${stories.length === 1 ? "y" : "ies"} waiting for approval:`);
4936
+ for (const story of stories) {
4937
+ console.log(
4938
+ ` crew #${story.crewId} · "${story.title}" · ${story.crewName} (${(story.people || []).join(", ")}) · ${story.itemsPublic} public / ${story.itemsPrivate} private`,
4939
+ );
4940
+ }
4941
+ if (stories.length) console.log("Approve: lumine admin meetup story approve <crewId> (or send-back <crewId> --note).");
4942
+ return;
4943
+ }
4944
+ if (operation.name === "meetup.story.show") {
4945
+ const story = data.story || {};
4946
+ const items = [...(story.photos || []), ...(story.clips || [])];
4947
+ console.log(`Story #${story.storyId} (crew #${story.crewId}) · ${story.status} · "${story.title}"`);
4948
+ console.log(` People: ${(story.people || []).map((p) => `${p.username} (${p.branch})`).join(", ")}`);
4949
+ for (const consent of story.review?.consents || []) {
4950
+ const person = (story.people || []).find((p) => p.userId === consent.userId);
4951
+ console.log(` Parent of ${person?.username || consent.userId}: ${consent.state}`);
4952
+ }
4953
+ for (const item of items) {
4954
+ const gate = item.gate || {};
4955
+ console.log(
4956
+ ` ${item.kind} #${item.id}: ${gate.publishable ? "PUBLIC" : `private (${gate.reason || "live"})`}${item.caption ? ` · ${item.caption}` : ""}${item.url ? ` · ${item.url}` : ""}`,
4957
+ );
4958
+ }
4959
+ if ((story.review?.nameWarnings || []).length) {
4960
+ console.log(` Possible real names: ${story.review.nameWarnings.join(", ")}`);
4961
+ }
4962
+ if (story.body) console.log(`\n${story.body}\n`);
4963
+ return;
4964
+ }
4965
+ if (operation.name.startsWith("meetup.story.")) {
4966
+ const r = data.result || {};
4967
+ if (operation.name === "meetup.story.approve") {
4968
+ console.log(
4969
+ `Published story #${r.storyId} (crew #${r.crewId}): ${(r.publicMediaIds || []).length} public, ${(r.privateMediaIds || []).length} private.${r.announcementSubjectId ? ` Announcement: subject #${r.announcementSubjectId}.` : ""}${(r.failed || []).length ? ` FAILED to process: ${r.failed.map((f) => `#${f.mediaId} ${f.error}`).join("; ")}.` : ""}`,
4970
+ );
4971
+ } else {
4972
+ console.log(`${operation.name === "meetup.story.unpublish" ? "Unpublished" : "Sent back"} story #${r.storyId} (crew #${r.crewId}).`);
4973
+ }
4974
+ return;
4975
+ }
4895
4976
  if (operation.name === "meetup.list") {
4896
4977
  const crews = Array.isArray(data.crews) ? data.crews : [];
4897
4978
  console.log(`${crews.length} meetup crew(s) (${data.filter || "review"}):`);
package/lib/commands.js CHANGED
@@ -2355,6 +2355,7 @@ export function parseArgs(args) {
2355
2355
  const raw = {};
2356
2356
  const positional = [];
2357
2357
  const booleanFlags = new Set([
2358
+ "noAnnounce",
2358
2359
  "noLeaseKeeper",
2359
2360
  "noOpen",
2360
2361
  "open",
@@ -2606,6 +2607,7 @@ export function parseArgs(args) {
2606
2607
  storageSize: raw.size ? String(raw.size) : "",
2607
2608
  adminAttended: raw.attended ? String(raw.attended) : "",
2608
2609
  adminConfirm: raw.confirm === undefined ? "" : String(raw.confirm),
2610
+ adminNoAnnounce: Boolean(raw.noAnnounce),
2609
2611
  adminContextLimit: raw.limit === undefined ? 20 : Number(raw.limit),
2610
2612
  adminRun: raw.run ? String(raw.run) : "",
2611
2613
  adminTarget: raw.target ? String(raw.target) : "",
@@ -3012,6 +3014,7 @@ export function printHelp() {
3012
3014
  lumine admin cardcraft-review list [--status pending|approved|all] [--cursor <id>] | show <id> | approve|reject|revoke <id> [--reason <text>]
3013
3015
  lumine admin storage list [--status pending|approved|rejected|all] [--cursor <id>] | show <user-id-or-username> | approve <request-id> [--size <500MB|1GB|2GB|n MB>] [--reason <text>] | reject <request-id> [--reason <text>] | grant <user-id-or-username> --size <500MB|1GB|2GB|n MB> [--reason <text>]
3014
3016
  lumine admin meetup list [--status review|active|completed|all] | show <crewId> | approve-plan <crewId> [--note <text>] | send-back <crewId> --note <text> | approve <crewId> --attended <userId,userId,...> [--note <text>] | slot <crewId> --confirm <slotIndex> | resend-email <crewId> (Bridge Builder meetup quest)
3017
+ lumine admin meetup story list | show <crewId> | approve <crewId> [--note <text>] [--no-announce] | send-back <crewId> --note <text> | unpublish <crewId> --note <text> (Bridge Builder story pages: publishes only what every tagged member's parent allowed)
3015
3018
  lumine admin reward-activity [--date YYYY-MM-DD] [--days <1..31>] [--build <id>] [--json]
3016
3019
  lumine admin chat-reports list [--status pending|open|reviewing|resolved|dismissed|all] [--cursor <id>] [--json]
3017
3020
  lumine admin chat-reports show <report-id> [--json] (reported message snapshot + surrounding context)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage5/lumine",
3
- "version": "0.2.98",
3
+ "version": "0.2.99",
4
4
  "description": "Command line tools for launching Lumine builds on Twinkle.",
5
5
  "type": "module",
6
6
  "bin": {