nixamp 0.28.1 → 0.28.2

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/dist/owner.js CHANGED
@@ -136,6 +136,8 @@ export function needsMember(path, method = "GET") {
136
136
  return true;
137
137
  if (method === "POST" && /^\/api\/channels\/[^/]+\/keep$/.test(path))
138
138
  return true;
139
+ if (method === "POST" && /^\/api\/channels\/[^/]+\/(?:start|stop|restart)$/.test(path))
140
+ return true;
139
141
  // A link -- a YouTube page, an IPTV feed, a file somewhere -- is the one
140
142
  // thing a member can go live with that needs nothing on the server first,
141
143
  // and it was the one thing they could not. Going live with one is the same
package/dist/server.js CHANGED
@@ -3480,14 +3480,18 @@ export function createHandler(engine, options) {
3480
3480
  return;
3481
3481
  }
3482
3482
  if (!check.allowed) {
3483
- if (member !== "" && needsMember(path, request.method ?? "GET")) {
3483
+ const ownedChannel = channelId === "" ? "" : options.channels?.info(channelId)?.startedBy ?? "";
3484
+ const memberOwnsChannel = member !== "" && ownedChannel === member;
3485
+ if (member !== "" && (needsMember(path, request.method ?? "GET") || memberOwnsChannel)) {
3484
3486
  // Metered per member, before anything is done: going live is a
3485
3487
  // decoder on this machine, and a script could ask for one a
3486
3488
  // second. Three a minute is a person; more is not.
3487
- const refused = await memberThrottle.handle(requestFor(request));
3488
- if (refused) {
3489
- await answerWith(response, refused);
3490
- return;
3489
+ if (needsMember(path, request.method ?? "GET")) {
3490
+ const refused = await memberThrottle.handle(requestFor(request));
3491
+ if (refused) {
3492
+ await answerWith(response, refused);
3493
+ return;
3494
+ }
3491
3495
  }
3492
3496
  liveBy = member;
3493
3497
  }
@@ -4406,7 +4410,7 @@ export function createHandler(engine, options) {
4406
4410
  json(response, 200, { ok: true, channel: id, name });
4407
4411
  return;
4408
4412
  }
4409
- if (action === undefined && request.method === "DELETE") {
4413
+ if ((action === undefined && request.method === "DELETE") || (action === "stop" && request.method === "POST")) {
4410
4414
  // A member takes off what they put on, and nothing else.
4411
4415
  if (liveBy && channels.info(id)?.startedBy !== liveBy) {
4412
4416
  json(response, 403, { error: "that stream is not yours to take off" });
@@ -4444,7 +4448,7 @@ export function createHandler(engine, options) {
4444
4448
  * take it off, put it back -- without having to know the source, which
4445
4449
  * a browser is never told.
4446
4450
  */
4447
- if (action === "restart") {
4451
+ if (action === "start" || action === "restart") {
4448
4452
  if (!channels.has(id)) {
4449
4453
  json(response, 404, { error: "nothing is playing on that channel" });
4450
4454
  return;
@@ -4453,6 +4457,10 @@ export function createHandler(engine, options) {
4453
4457
  json(response, 409, { error: "that channel is published into this server; restart it at the publisher" });
4454
4458
  return;
4455
4459
  }
4460
+ if (liveBy && channels.info(id)?.startedBy !== liveBy) {
4461
+ json(response, 403, { error: "that stream is not yours to restart" });
4462
+ return;
4463
+ }
4456
4464
  const restarted = channels.restart(id);
4457
4465
  json(response, restarted ? 200 : 409, { ok: restarted });
4458
4466
  return;
@@ -4472,6 +4480,10 @@ export function createHandler(engine, options) {
4472
4480
  // a member, counted and marked like anything else they put on.
4473
4481
  if (liveBy) {
4474
4482
  const info = channels.info(id);
4483
+ if (info && info.startedBy && info.startedBy !== liveBy) {
4484
+ json(response, 403, { error: "that stream is not yours to keep" });
4485
+ return;
4486
+ }
4475
4487
  if (info && !info.startedBy && !channels.isEphemeral(id)) {
4476
4488
  json(response, 403, { error: "that stream is the owner's" });
4477
4489
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nixamp",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "It really whips the terminal's ass. A Winamp-shaped audio player for your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/owner.ts CHANGED
@@ -148,6 +148,7 @@ export function needsMember(path: string, method = "GET"): boolean {
148
148
  if (method === "POST" && /^\/api\/tracks\/\d+\/live$/.test(path)) return true;
149
149
  if (method === "POST" && /^\/api\/catalogs\/[^/]+\/entries\/[^/]+\/live$/.test(path)) return true;
150
150
  if (method === "POST" && /^\/api\/channels\/[^/]+\/keep$/.test(path)) return true;
151
+ if (method === "POST" && /^\/api\/channels\/[^/]+\/(?:start|stop|restart)$/.test(path)) return true;
151
152
  // A link -- a YouTube page, an IPTV feed, a file somewhere -- is the one
152
153
  // thing a member can go live with that needs nothing on the server first,
153
154
  // and it was the one thing they could not. Going live with one is the same
package/src/server.ts CHANGED
@@ -3926,14 +3926,18 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
3926
3926
  return;
3927
3927
  }
3928
3928
  if (!check.allowed) {
3929
- if (member !== "" && needsMember(path, request.method ?? "GET")) {
3929
+ const ownedChannel = channelId === "" ? "" : options.channels?.info(channelId)?.startedBy ?? "";
3930
+ const memberOwnsChannel = member !== "" && ownedChannel === member;
3931
+ if (member !== "" && (needsMember(path, request.method ?? "GET") || memberOwnsChannel)) {
3930
3932
  // Metered per member, before anything is done: going live is a
3931
3933
  // decoder on this machine, and a script could ask for one a
3932
3934
  // second. Three a minute is a person; more is not.
3933
- const refused = await memberThrottle.handle(requestFor(request));
3934
- if (refused) {
3935
- await answerWith(response, refused);
3936
- return;
3935
+ if (needsMember(path, request.method ?? "GET")) {
3936
+ const refused = await memberThrottle.handle(requestFor(request));
3937
+ if (refused) {
3938
+ await answerWith(response, refused);
3939
+ return;
3940
+ }
3937
3941
  }
3938
3942
  liveBy = member;
3939
3943
  } else {
@@ -4858,7 +4862,7 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
4858
4862
  return;
4859
4863
  }
4860
4864
 
4861
- if (action === undefined && request.method === "DELETE") {
4865
+ if ((action === undefined && request.method === "DELETE") || (action === "stop" && request.method === "POST")) {
4862
4866
  // A member takes off what they put on, and nothing else.
4863
4867
  if (liveBy && channels.info(id)?.startedBy !== liveBy) {
4864
4868
  json(response, 403, { error: "that stream is not yours to take off" });
@@ -4898,7 +4902,7 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
4898
4902
  * take it off, put it back -- without having to know the source, which
4899
4903
  * a browser is never told.
4900
4904
  */
4901
- if (action === "restart") {
4905
+ if (action === "start" || action === "restart") {
4902
4906
  if (!channels.has(id)) {
4903
4907
  json(response, 404, { error: "nothing is playing on that channel" });
4904
4908
  return;
@@ -4907,6 +4911,10 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
4907
4911
  json(response, 409, { error: "that channel is published into this server; restart it at the publisher" });
4908
4912
  return;
4909
4913
  }
4914
+ if (liveBy && channels.info(id)?.startedBy !== liveBy) {
4915
+ json(response, 403, { error: "that stream is not yours to restart" });
4916
+ return;
4917
+ }
4910
4918
  const restarted = channels.restart(id);
4911
4919
  json(response, restarted ? 200 : 409, { ok: restarted });
4912
4920
  return;
@@ -4927,6 +4935,10 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
4927
4935
  // a member, counted and marked like anything else they put on.
4928
4936
  if (liveBy) {
4929
4937
  const info = channels.info(id);
4938
+ if (info && info.startedBy && info.startedBy !== liveBy) {
4939
+ json(response, 403, { error: "that stream is not yours to keep" });
4940
+ return;
4941
+ }
4930
4942
  if (info && !info.startedBy && !channels.isEphemeral(id)) {
4931
4943
  json(response, 403, { error: "that stream is the owner's" });
4932
4944
  return;
@@ -1 +1 @@
1
- import{t as e}from"./index-HDrZHpqb.js";var t=3;async function n(n){let{media:r,src:i,isTv:a}=n,{default:o}=await e(async()=>{let{default:e}=await import(`./hls-n74Cnh8A.js`);return{default:e}},[]);if(!o.isSupported())return n.onError(`This browser cannot play HLS streams.`),{destroy:()=>void 0,levels:()=>[]};let s=new o({...a?{maxBufferLength:60,maxMaxBufferLength:120,backBufferLength:30,liveSyncDurationCount:4}:{backBufferLength:90},enableWorker:!0}),c=0,l=!1;s.on(o.Events.ERROR,(e,r)=>{if(!l&&r.fatal){if(c>=t){n.onError(`This stream kept failing and has been stopped.`),s.destroy();return}switch(c+=1,r.type){case o.ErrorTypes.NETWORK_ERROR:n.onNotice(`Reconnecting…`),s.startLoad();break;case o.ErrorTypes.MEDIA_ERROR:n.onNotice(`Recovering…`),s.recoverMediaError();break;default:n.onError(`This stream could not be played.`),s.destroy()}}}),s.on(o.Events.MANIFEST_PARSED,()=>{l||(n.onNotice(null),n.onReady?.({live:s.levels.length>0&&!Number.isFinite(r.duration),levels:u()}))}),s.on(o.Events.LEVEL_LOADED,(e,t)=>{l||n.onReady?.({live:t.details.live,levels:u()})}),s.on(o.Events.FRAG_BUFFERED,()=>{l||n.onNotice(null)});function u(){return s.levels.map((e,t)=>({index:t,height:e.height||null,bitrate:e.bitrate||null,label:e.height?`${String(e.height)}p`:`${String(Math.round((e.bitrate||0)/1e3))}k`}))}return s.loadSource(i),s.attachMedia(r),{destroy(){l=!0,s.destroy()},levels:u,setLevel(e){s.currentLevel=e},currentLevel:()=>s.autoLevelEnabled?-1:s.currentLevel}}export{n as createHlsEngine};
1
+ import{t as e}from"./index-BqcDIh2Q.js";var t=3;async function n(n){let{media:r,src:i,isTv:a}=n,{default:o}=await e(async()=>{let{default:e}=await import(`./hls-n74Cnh8A.js`);return{default:e}},[]);if(!o.isSupported())return n.onError(`This browser cannot play HLS streams.`),{destroy:()=>void 0,levels:()=>[]};let s=new o({...a?{maxBufferLength:60,maxMaxBufferLength:120,backBufferLength:30,liveSyncDurationCount:4}:{backBufferLength:90},enableWorker:!0}),c=0,l=!1;s.on(o.Events.ERROR,(e,r)=>{if(!l&&r.fatal){if(c>=t){n.onError(`This stream kept failing and has been stopped.`),s.destroy();return}switch(c+=1,r.type){case o.ErrorTypes.NETWORK_ERROR:n.onNotice(`Reconnecting…`),s.startLoad();break;case o.ErrorTypes.MEDIA_ERROR:n.onNotice(`Recovering…`),s.recoverMediaError();break;default:n.onError(`This stream could not be played.`),s.destroy()}}}),s.on(o.Events.MANIFEST_PARSED,()=>{l||(n.onNotice(null),n.onReady?.({live:s.levels.length>0&&!Number.isFinite(r.duration),levels:u()}))}),s.on(o.Events.LEVEL_LOADED,(e,t)=>{l||n.onReady?.({live:t.details.live,levels:u()})}),s.on(o.Events.FRAG_BUFFERED,()=>{l||n.onNotice(null)});function u(){return s.levels.map((e,t)=>({index:t,height:e.height||null,bitrate:e.bitrate||null,label:e.height?`${String(e.height)}p`:`${String(Math.round((e.bitrate||0)/1e3))}k`}))}return s.loadSource(i),s.attachMedia(r),{destroy(){l=!0,s.destroy()},levels:u,setLevel(e){s.currentLevel=e},currentLevel:()=>s.autoLevelEnabled?-1:s.currentLevel}}export{n as createHlsEngine};