Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
7 changes: 5 additions & 2 deletions src/guide-vods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 !== "") {
Expand Down
4 changes: 2 additions & 2 deletions src/library-usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
22 changes: 22 additions & 0 deletions test/guide-vods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
});
Loading