aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/stream.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/routes/stream.rs')
-rw-r--r--server/src/routes/stream.rs136
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,