diff --git a/package.json b/package.json index c16c1bb..d95bc17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nixamp", - "version": "0.72.1", + "version": "0.73.0", "description": "It really whips the terminal's ass. A Winamp-shaped audio player for your terminal.", "license": "MIT", "type": "module", diff --git a/src/guide-vods.ts b/src/guide-vods.ts index e7567df..984e81f 100644 --- a/src/guide-vods.ts +++ b/src/guide-vods.ts @@ -44,6 +44,8 @@ export interface GuideVod { /** The bases a price may be put on: what the owner may sell, not just share. */ export const SELLABLE_BASES: readonly RoomBasis[] = ["owned", "public-domain"]; +/** What a new video of the owner's costs to download unless it says otherwise (Anthony: "$1 per video"). */ +export const VOD_DEFAULT_PRICE_CENTS = 100; /** $100: a price above that is a typo. */ export const VOD_PRICE_MAX_CENTS = 10_000; @@ -318,8 +320,9 @@ export async function handleVods(request: IncomingMessage, response: ServerRespo const title = typeof body?.title === "string" ? body.title.trim().slice(0, 160) : ""; const note = typeof body?.note === "string" ? body.note.trim().slice(0, 300) : ""; const owner = taken?.by ?? by; - // A price, in dollars: only the owner, only on its own, only what it may sell. Left out, the old one stays. - let priceCents = taken?.priceCents ?? 0; + // A price, in dollars: only the owner, only on its own, only what it may sell. Left out, the old one stays, + // and a new one of the owner's that it may sell costs the default. + let priceCents = taken ? (taken.priceCents ?? 0) : owner === "" && ctx.canControl && SELLABLE_BASES.includes(basis) ? VOD_DEFAULT_PRICE_CENTS : 0; if (body?.price !== undefined && body.price !== null) { const cents = Math.round(Number(body.price) * 100); if (!ctx.canControl || owner !== "") { diff --git a/src/library-usage.ts b/src/library-usage.ts index 000ac53..489d44f 100644 --- a/src/library-usage.ts +++ b/src/library-usage.ts @@ -20,8 +20,8 @@ export const LIBRARY_USAGE = `nixamp library — what this server has, indexed on demand on live.streaming: a link that plays each from the start, from any of your servers (needs nixamp login); --here for this server's own guide (B: owned, permission, licensed, creative-commons, public-domain) - --price USD: sell it as a download on nixamp.com (guide owner, owned or - public-domain only; publish again with --price 0 to stop) + --price USD: its download price on nixamp.com (guide owner, owned or + public-domain only; new ones default to $1, --price 0 for free) nixamp library vods what is published on demand, with each link nixamp library unpublish VOD take one off diff --git a/test/guide-vods.test.ts b/test/guide-vods.test.ts index 73a7829..647d4d2 100644 --- a/test/guide-vods.test.ts +++ b/test/guide-vods.test.ts @@ -174,3 +174,25 @@ test("the owner prices its own sellable file; a bought grant redirects to the fi rmSync(dir, { recursive: true, force: true }); } }); + +test("a new sellable video of the owner's costs $1 unless it says otherwise; a member's is never sold", async () => { + const dir = mkdtempSync(join(tmpdir(), "vods-")); + const store = new VodStore(join(dir, "vods.json")); + const probe = new VodProbe(fakeServer(ITEM)); + let control = true; + const { base, close } = await serve({ store, probe, base: "https://live.streaming.pit.world", get canControl() { return control; }, member: async () => (control ? "" : "acct-1") }); + try { + const post = async (body: unknown) => ((await (await fetch(`${base}/api/v1/guide/vods`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) })).json()) as { vod: { id: string; priceCents?: number } }).vod; + assert.equal((await post({ play: PLAY, basis: "public-domain", agree: true })).priceCents, 100); + assert.equal((await post({ play: PLAY, basis: "public-domain", agree: true, price: 0 })).priceCents, undefined, "--price 0 makes it free"); + assert.equal((await post({ play: PLAY, basis: "public-domain", agree: true })).priceCents, undefined, "and it stays free when published again"); + store.remove((await post({ play: PLAY, basis: "public-domain", agree: true })).id); + control = false; + const members = await post({ play: PLAY, basis: "owned", agree: true }); + assert.ok(members.id); + assert.equal(members.priceCents, undefined, "a member's video"); + } finally { + close(); + rmSync(dir, { recursive: true, force: true }); + } +});