diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-16 20:06:01 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-16 20:06:01 +0200 |
commit | d26849375c70c795fdf664f9dfea68c273b6d483 (patch) | |
tree | 53ad4f0eff3604e80b27ff0abf0438ea6c69d432 /server/src/routes/stream.rs | |
parent | 1cd966f7454f052fda6c6c9ae1597479f05e23d9 (diff) | |
parent | cdf95d7b80bd2b78895671da8f462145bb5db522 (diff) | |
download | jellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar jellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar.bz2 jellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar.zst |
Merge branch 'rewrite-stream'
Diffstat (limited to 'server/src/routes/stream.rs')
-rw-r--r-- | server/src/routes/stream.rs | 136 |
1 files changed, 76 insertions, 60 deletions
diff --git a/server/src/routes/stream.rs b/server/src/routes/stream.rs index 1fb136c..0fbeb3a 100644 --- a/server/src/routes/stream.rs +++ b/server/src/routes/stream.rs @@ -6,13 +6,9 @@ use super::ui::{account::session::Session, error::MyError}; use crate::database::Database; use anyhow::{anyhow, Result}; -use jellybase::{federation::Federation, permission::PermissionSetExt, SECRETS}; -use jellycommon::{ - config::FederationAccount, - stream::StreamSpec, - user::{CreateSessionParams, UserPermission}, - TrackSource, -}; +use jellybase::{assetfed::AssetInner, federation::Federation}; +use jellycommon::{stream::StreamSpec, TrackSource}; +use jellystream::SMediaInfo; use log::{info, warn}; use rocket::{ get, head, @@ -21,15 +17,20 @@ use rocket::{ response::{self, Redirect, Responder}, Either, Request, Response, State, }; -use std::{collections::HashSet, ops::Range}; +use std::{ + collections::{BTreeMap, BTreeSet}, + ops::Range, + sync::Arc, +}; use tokio::io::{duplex, DuplexStream}; -#[head("/n/<_id>/stream?<spec>")] +#[head("/n/<_id>/stream?<spec..>")] pub async fn r_stream_head( _sess: Session, _id: &str, - spec: StreamSpec, + spec: BTreeMap<String, String>, ) -> Result<Either<StreamResponse, Redirect>, MyError> { + let spec = StreamSpec::from_query_kv(&spec).map_err(|x| anyhow!("spec invalid: {x}"))?; let head = jellystream::stream_head(&spec); Ok(Either::Left(StreamResponse { stream: duplex(0).0, @@ -41,70 +42,72 @@ pub async fn r_stream_head( #[get("/n/<id>/stream?<spec..>")] pub async fn r_stream( - session: Session, - federation: &State<Federation>, + _session: Session, + _federation: &State<Federation>, db: &State<Database>, id: &str, range: Option<RequestRange>, - spec: StreamSpec, + spec: BTreeMap<String, String>, ) -> Result<Either<StreamResponse, RedirectResponse>, MyError> { + let spec = StreamSpec::from_query_kv(&spec).map_err(|x| anyhow!("spec invalid: {x}"))?; // TODO perm let node = db .get_node_slug(id)? .ok_or(anyhow!("node does not exist"))?; - let media = node - .media - .as_ref() - .ok_or(anyhow!("item does not contain media"))?; + let media = Arc::new( + node.media + .clone() + .ok_or(anyhow!("item does not contain media"))?, + ); // TODO its unclear how requests with multiple tracks should be handled. - if spec.track.len() == 1 { - let ti = spec.track[0]; - if let TrackSource::Remote(remote_index) = media.tracks[ti].source { - session - .user - .permissions - .assert(&UserPermission::FederatedContent)?; + // if spec.track.len() == 1 { + // let ti = spec.track[0]; + // if let TrackSource::Remote(remote_index) = media.tracks[ti].source { + // session + // .user + // .permissions + // .assert(&UserPermission::FederatedContent)?; - let track = &node.media.as_ref().ok_or(anyhow!("no media"))?.tracks[ti]; - let host = track - .federated - .last() - .ok_or(anyhow!("federation inconsistent"))?; + // let track = &node.media.as_ref().ok_or(anyhow!("no media"))?.tracks[ti]; + // let host = track + // .federated + // .last() + // .ok_or(anyhow!("federation inconsistent"))?; - let FederationAccount { - password, username, .. - } = SECRETS - .federation - .get(host) - .ok_or(anyhow!("no credentials on the server-side"))?; + // let FederationAccount { + // password, username, .. + // } = SECRETS + // .federation + // .get(host) + // .ok_or(anyhow!("no credentials on the server-side"))?; - info!("creating session on {host}"); - let instance = federation.get_instance(host)?.to_owned(); - let session = instance - .login(CreateSessionParams { - username: username.to_owned(), - password: password.to_owned(), - expire: Some(60), - drop_permissions: Some(HashSet::from_iter([ - UserPermission::ManageSelf, - UserPermission::Admin, // in case somebody federated the admin :))) - ])), - }) - .await?; + // info!("creating session on {host}"); + // let instance = federation.get_instance(host)?.to_owned(); + // let session = instance + // .login(CreateSessionParams { + // username: username.to_owned(), + // password: password.to_owned(), + // expire: Some(60), + // drop_permissions: Some(HashSet::from_iter([ + // UserPermission::ManageSelf, + // UserPermission::Admin, // in case somebody federated the admin :))) + // ])), + // }) + // .await?; - let uri = session.stream_url( - node.slug.clone().into(), - &StreamSpec { - track: vec![remote_index], - ..spec - }, - ); - info!("federation redirect"); - return Ok(Either::Right(RedirectResponse(uri))); - } - } + // let uri = session.stream_url( + // node.slug.clone().into(), + // &StreamSpec { + // track: vec![remote_index], + // ..spec + // }, + // ); + // info!("federation redirect"); + // return Ok(Either::Right(RedirectResponse(uri))); + // } + // } info!( "stream request (range={})", @@ -124,7 +127,20 @@ pub async fn r_stream( let head = jellystream::stream_head(&spec); - match jellystream::stream(node, spec, urange, &session.user.permissions).await { + let mut sources = BTreeSet::new(); + for t in &media.tracks { + if let TrackSource::Local(x) = &t.source { + if let AssetInner::LocalTrack(m) = AssetInner::deser(&x.0)? { + sources.insert(m.path); + } + } + } + let media = Arc::new(SMediaInfo { + files: sources, + info: node, + }); + + match jellystream::stream(media, spec, urange).await { Ok(stream) => Ok(Either::Left(StreamResponse { stream, range, |