aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock75
-rw-r--r--Cargo.toml10
-rw-r--r--client/Cargo.toml11
-rw-r--r--client/src/lib.rs70
-rw-r--r--server/Cargo.toml2
-rw-r--r--server/src/routes/api/mod.rs24
-rw-r--r--server/src/routes/stream.rs54
-rw-r--r--server/src/routes/ui/error.rs7
-rw-r--r--server/src/routes/ui/player.rs9
9 files changed, 165 insertions, 97 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8d9fa71..fda0efc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -127,9 +127,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.71"
+version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
[[package]]
name = "argon2"
@@ -256,7 +256,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -273,7 +273,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -484,7 +484,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -631,7 +631,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -650,7 +650,7 @@ name = "ebml_derive"
version = "0.1.0"
dependencies = [
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -1173,6 +1173,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
+name = "jellyclient"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "jellycommon",
+ "log",
+ "reqwest",
+ "serde_json",
+]
+
+[[package]]
name = "jellycommon"
version = "0.1.0"
dependencies = [
@@ -1216,13 +1227,13 @@ dependencies = [
"chashmap",
"chrono",
"env_logger",
+ "jellyclient",
"jellycommon",
"jellyremuxer",
"log",
"markup",
"once_cell",
"rand 0.8.5",
- "reqwest",
"rocket",
"serde",
"serde_json",
@@ -1297,9 +1308,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.18"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [
"value-bag",
]
@@ -1489,7 +1500,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -1632,7 +1643,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -1658,7 +1669,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -1715,9 +1726,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.59"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
@@ -1730,7 +1741,7 @@ checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
"version_check",
"yansi",
]
@@ -1846,7 +1857,7 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -1969,7 +1980,7 @@ dependencies = [
"proc-macro2",
"quote",
"rocket_http",
- "syn 2.0.18",
+ "syn 2.0.28",
"unicode-xid",
]
@@ -2072,29 +2083,29 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.164"
+version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
+checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.164"
+version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
+checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
name = "serde_json"
-version = "1.0.96"
+version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
dependencies = [
"itoa",
"ryu",
@@ -2256,9 +2267,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.18"
+version = "2.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
dependencies = [
"proc-macro2",
"quote",
@@ -2304,7 +2315,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -2396,7 +2407,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -2494,7 +2505,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
]
[[package]]
@@ -2713,7 +2724,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
"wasm-bindgen-shared",
]
@@ -2747,7 +2758,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.18",
+ "syn 2.0.28",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
diff --git a/Cargo.toml b/Cargo.toml
index d64f4b3..1e73144 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,11 @@
[workspace]
-members = ["server", "remuxer", "common", "tools", "matroska", "ebml_derive"]
+members = [
+ "server",
+ "remuxer",
+ "common",
+ "tools",
+ "matroska",
+ "ebml_derive",
+ "client",
+]
resolver = "2"
diff --git a/client/Cargo.toml b/client/Cargo.toml
new file mode 100644
index 0000000..a2bed77
--- /dev/null
+++ b/client/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "jellyclient"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+jellycommon = { path = "../common" }
+log = "0.4.19"
+reqwest = "0.11.18"
+anyhow = "1.0.72"
+serde_json = "1.0.104"
diff --git a/client/src/lib.rs b/client/src/lib.rs
new file mode 100644
index 0000000..a4d0b01
--- /dev/null
+++ b/client/src/lib.rs
@@ -0,0 +1,70 @@
+use reqwest::Client;
+use serde_json::json;
+use std::time::Duration;
+
+pub struct Instance {
+ pub host: String,
+ pub tls: bool,
+}
+pub struct Session(pub String);
+
+impl Instance {
+ pub fn base(&self) -> String {
+ format!(
+ "{}://{}",
+ if self.tls { "https" } else { "http" },
+ self.host
+ )
+ }
+}
+impl Session {
+ pub fn session_param(&self) -> String {
+ format!("session={}", self.0)
+ }
+}
+
+pub fn stream(
+ instance: &Instance,
+ session: &Session,
+ id: &str,
+ tracks: &[usize],
+ webm: bool,
+) -> String {
+ format!(
+ "{}/n/{}/stream?tracks={}&webm={}&{}",
+ instance.base(),
+ id,
+ tracks
+ .iter()
+ .map(|v| format!("{v}"))
+ .collect::<Vec<_>>()
+ .join(","),
+ if webm { "1" } else { "0" },
+ session.session_param()
+ )
+}
+
+pub async fn login(
+ instance: &Instance,
+ username: String,
+ password: String,
+ expire: Duration,
+) -> anyhow::Result<Session> {
+ let p = serde_json::to_string(&json!({
+ "expire": expire.as_secs(),
+ "password": password,
+ "username": username,
+ }))
+ .unwrap();
+
+ let r = Client::builder()
+ .build()?
+ .post(format!("{}/api/account/login", instance.base()))
+ .body(p)
+ .send()
+ .await?
+ .json()
+ .await?;
+
+ Ok(Session(r))
+}
diff --git a/server/Cargo.toml b/server/Cargo.toml
index 4617a18..487c4fc 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
jellycommon = { path = "../common" }
jellyremuxer = { path = "../remuxer" }
+jellyclient = { path = "../client" }
serde = { version = "1.0.163", features = ["derive"] }
bincode = { version = "2.0.0-rc.3", features = ["serde", "derive"] }
@@ -29,7 +30,6 @@ tokio-util = { version = "0.7.8", features = ["io", "io-util"] }
markup = "0.13.1"
rocket = { version = "0.5.0-rc.3", features = ["secrets", "json"] }
-reqwest = "0.11.18"
sled = "0.34.7"
typed-sled = "0.2.3"
diff --git a/server/src/routes/api/mod.rs b/server/src/routes/api/mod.rs
index 84dd6a8..b39950c 100644
--- a/server/src/routes/api/mod.rs
+++ b/server/src/routes/api/mod.rs
@@ -9,7 +9,6 @@ use super::ui::{
error::MyResult,
};
use crate::database::Database;
-use reqwest::Client;
use rocket::{get, post, response::Redirect, serde::json::Json, State};
use serde_json::{json, Value};
@@ -28,26 +27,3 @@ pub fn r_api_account_login(database: &State<Database>, data: Json<LoginForm>) ->
let token = login_logic(database, &data.username, &data.password)?;
Ok(json!(token))
}
-pub async fn c_api_account_login(
- host: &str,
- tls: bool,
- username: String,
- password: String,
- expire: u64,
-) -> MyResult<String> {
- Ok(Client::builder()
- .build()?
- .post(format!(
- "{}://{host}/api/account/login",
- if tls { "https" } else { "http" }
- ))
- .body(serde_json::to_string(&LoginForm {
- expire,
- password,
- username,
- })?)
- .send()
- .await?
- .json()
- .await?)
-}
diff --git a/server/src/routes/stream.rs b/server/src/routes/stream.rs
index 19a3f09..1277646 100644
--- a/server/src/routes/stream.rs
+++ b/server/src/routes/stream.rs
@@ -4,7 +4,7 @@
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
use super::ui::{account::session::Session, error::MyError};
-use crate::{database::Database, routes::api::c_api_account_login, uri, CONF};
+use crate::{database::Database, CONF};
use anyhow::{anyhow, Result};
use jellycommon::MediaSource;
use jellyremuxer::RemuxerContext;
@@ -16,23 +16,13 @@ use rocket::{
response::{self, Redirect, Responder},
Either, Request, Response, State,
};
-use std::ops::{Deref, Range};
+use std::{
+ ops::{Deref, Range},
+ time::Duration,
+};
use tokio::io::{duplex, DuplexStream};
use tokio_util::io::SyncIoBridge;
-pub fn stream_uri(id: &str, tracks: &[u64], webm: bool) -> String {
- format!(
- "/n/{}/stream?tracks={}&webm={}",
- id,
- tracks
- .iter()
- .map(|v| format!("{v}"))
- .collect::<Vec<_>>()
- .join(","),
- if webm { "1" } else { "0" }
- )
-}
-
#[get("/n/<id>/stream?<tracks>&<webm>")]
pub async fn r_stream(
_sess: Session,
@@ -49,6 +39,11 @@ pub async fn r_stream(
.source
.ok_or(anyhow!("item does not contain media"))?;
+ let tracks = tracks
+ .split(',')
+ .map(|e| e.parse().map_err(|_| anyhow!("invalid number")))
+ .collect::<Result<Vec<_>, _>>()?;
+
let source_tracks = match source {
MediaSource::Local { tracks } => tracks,
MediaSource::Remote { host, remote_id } => {
@@ -56,15 +51,22 @@ pub async fn r_stream(
.remote_credentials
.get(&host)
.ok_or(anyhow!("no credentials on the server-side"))?;
- let token =
- c_api_account_login(&host, false, username.to_owned(), password.to_owned(), 60)
- .await?;
- let uri = format!(
- "{}://{host}{}&session={}",
- if *tls { "https" } else { "http" },
- uri!(r_stream(remote_id, tracks, webm)),
- token
+ let instance = jellyclient::Instance { host, tls: *tls };
+ let session = jellyclient::login(
+ &instance,
+ username.to_owned(),
+ password.to_owned(),
+ Duration::from_secs(60),
+ )
+ .await?;
+
+ let uri = jellyclient::stream(
+ &instance,
+ &session,
+ &remote_id,
+ &tracks,
+ webm.unwrap_or(false),
);
return Ok(Either::Right(Redirect::found(uri)));
}
@@ -79,13 +81,7 @@ pub async fn r_stream(
);
let (a, b) = duplex(4096);
-
let remuxer = remuxer.deref().clone();
- let tracks = tracks
- .split(',')
- .map(|e| e.parse().map_err(|_| anyhow!("invalid number")))
- .collect::<Result<Vec<_>, _>>()?;
-
let b = SyncIoBridge::new(b);
let urange = match &range {
diff --git a/server/src/routes/ui/error.rs b/server/src/routes/ui/error.rs
index d911a41..01aebd3 100644
--- a/server/src/routes/ui/error.rs
+++ b/server/src/routes/ui/error.rs
@@ -90,9 +90,4 @@ impl From<serde_json::Error> for MyError {
fn from(err: serde_json::Error) -> Self {
MyError(anyhow::anyhow!("{err}"))
}
-}
-impl From<reqwest::Error> for MyError {
- fn from(err: reqwest::Error) -> Self {
- MyError(anyhow::anyhow!("{err}"))
- }
-}
+} \ No newline at end of file
diff --git a/server/src/routes/ui/player.rs b/server/src/routes/ui/player.rs
index 2af9d9e..e295b02 100644
--- a/server/src/routes/ui/player.rs
+++ b/server/src/routes/ui/player.rs
@@ -7,7 +7,7 @@ use super::{account::session::Session, layout::LayoutPage};
use crate::{
database::Database,
routes::{
- stream::stream_uri,
+ stream::rocket_uri_macro_r_stream,
ui::{
assets::{rocket_uri_macro_r_item_assets, AssetRole},
error::MyResult,
@@ -21,7 +21,6 @@ use jellycommon::{Node, SourceTrackKind};
use markup::DynRender;
use rocket::{get, FromForm, State};
-
#[derive(FromForm, Default, Clone, Debug)]
pub struct PlayerConfig {
pub a: Option<u64>,
@@ -47,7 +46,9 @@ pub fn r_player(
.chain(conf.v.into_iter())
.chain(conf.a.into_iter())
.chain(conf.s.into_iter())
- .collect::<Vec<_>>();
+ .map(|e| format!("{e}"))
+ .collect::<Vec<_>>()
+ .join(",");
let conf = player_conf(item.clone(), !tracks.is_empty())?;
Ok(LayoutPage {
@@ -57,7 +58,7 @@ pub fn r_player(
@if tracks.is_empty() {
img.backdrop[src=uri!(r_item_assets(&id, AssetRole::Backdrop)).to_string()];
} else {
- video[src=stream_uri(&id, &tracks, true), controls]{}
+ video[src=uri!(r_stream(&id, &tracks, Some(true))), controls]{}
}
@conf
},