diff --git a/Cargo.lock b/Cargo.lock index 93f48b267..6dd50fa66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,6 +835,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -884,6 +893,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "regex" version = "1.11.0" @@ -1167,6 +1206,7 @@ dependencies = [ "tokio-current-thread", "tracing", "url", + "uuid", ] [[package]] @@ -1523,6 +1563,29 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" +[[package]] +name = "uuid" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" +dependencies = [ + "getrandom", + "rand", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a86d88347b61a0e17b9908a67efcc594130830bf1045653784358dd023e294" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "version_check" version = "0.9.5" @@ -1724,3 +1787,24 @@ name = "yansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] diff --git a/Cargo.toml b/Cargo.toml index c2c0da198..3fb01afab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,11 +13,7 @@ opt-level = 's' [workspace] resolver = "2" -members = [ - "stremio-core-web", - "stremio-derive", - "stremio-watched-bitfield", -] +members = ["stremio-core-web", "stremio-derive", "stremio-watched-bitfield"] [features] # TODO: env-future-send should be enabled by default @@ -37,13 +33,16 @@ derive = [] # Enable core analytics analytics = [] +# enables WASM specific features for core +wasm = ["uuid/js"] + [dependencies] stremio-derive = { path = "stremio-derive" } stremio-watched-bitfield = { path = "stremio-watched-bitfield" } stremio-official-addons = "=2.0.13" # (De)Serialization -serde = { version = "1", features = ["derive"]} +serde = { version = "1", features = ["derive"] } serde_json = "1.0.*" serde_path_to_error = "0.1" serde_url_params = "0.2" @@ -96,6 +95,12 @@ num = { version = "0.4.0", default-features = false } # Tracing tracing = "0.1" +uuid = { version = "1.12.1", features = [ + "v4", # Lets you generate random UUIDs + "fast-rng", # Use a faster (but still sufficiently random) RNG + "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs +]} + [dev-dependencies] tokio = { version = "1.12", features = ["rt", "macros"] } tokio-current-thread = "=0.2.0-alpha.1" diff --git a/src/models/player.rs b/src/models/player.rs index 3e85c58f4..16ffaaf7a 100644 --- a/src/models/player.rs +++ b/src/models/player.rs @@ -29,7 +29,9 @@ use crate::types::profile::{Profile, Settings as ProfileSettings}; use crate::types::resource::{ MetaItem, SeriesInfo, Stream, StreamSource, StreamUrls, Subtitles, Video, }; -use crate::types::streams::{ConvertedStreamSource, StreamItemState, StreamsBucket, StreamsItemKey}; +use crate::types::streams::{ + ConvertedStreamSource, StreamItemState, StreamsBucket, StreamsItemKey, +}; use stremio_watched_bitfield::WatchedBitField; @@ -639,21 +641,8 @@ impl UpdateWithCtx for Player { .map(|library_item| library_item.state.time_offset), ); - let item_state_update_effects = item_state_update(&mut self.library_item, &self.next_video); - // let item_state_update_effects = if self - // .selected - // .as_ref() - // .and_then(|selected| selected.meta_request.as_ref()) - // .map(|meta_request| &meta_request.path.id) - // != self.selected - // .meta_request - // .as_ref() - // .map(|meta_request| &meta_request.path.id) - // { - // item_state_update(&mut self.library_item, &self.next_video) - // } else { - // Effects::none().unchanged() - // }; + let item_state_update_effects = + item_state_update(&mut self.library_item, &self.next_video); // Set time_offset to 0 as we switch to next video let library_item_effects = self @@ -672,7 +661,7 @@ impl UpdateWithCtx for Player { // Load will actually take care of loading the next video seek_history_effects - .join(item_state_update_effects) + .join(item_state_update_effects) .join( Effects::msg(Msg::Event(Event::PlayerNextVideo { context: self.analytics_context.as_ref().cloned().unwrap_or_default(), @@ -894,13 +883,10 @@ impl UpdateWithCtx for Player { converted_stream.to_owned(), streaming_server_url.as_ref(), ); - + Loadable::Ready((stream_urls, converted_stream.to_owned())) - }, - Err(err) => { - tracing::info!("failed here"); - Loadable::Err(err.to_owned()) - }, + } + Err(err) => Loadable::Err(err.to_owned()), }; eq_update(&mut self.stream, next_stream) @@ -1333,8 +1319,11 @@ fn calculate_outro(library_item: &LibraryItem, closest_duration: u64, closest_ou let duration_diff_in_secs = (library_item.state.duration.abs_diff(closest_duration)).div(1000 * 10) / 10; tracing::debug!( + closest_duration, + closest_outro, "Player: Outro match by duration with difference of {duration_diff_in_secs} seconds" ); + library_item .state .duration @@ -1402,18 +1391,20 @@ fn intro_outro_update( closest_duration.and_then(|(closest_duration, skip_gaps)| { let duration_diff_in_secs = (library_item.state.duration.abs_diff(*closest_duration)).div(1000 * 10) / 10; - tracing::trace!("Player: Intro match by duration with difference of {duration_diff_in_secs} seconds"); - let duration_ration = Ratio::new(library_item.state.duration, *closest_duration); - // even though we checked for len() > 0 make sure we don't panic if somebody decides to remove that check! - skip_gaps.seek_history.first().map(|seek_event| { - IntroData { + let matched_intro = skip_gaps.seek_history.first().map(|seek_event| { + let intro_data = IntroData { from: (duration_ration * seek_event.from).to_integer(), to: (duration_ration * seek_event.to).to_integer(), duration: if duration_diff_in_secs > 0 { Some(seek_event.to.abs_diff(seek_event.from)) } else { None } - } - }) + }; + tracing::debug!(?seek_event, ?intro_data, "Player: Intro match for event by duration with difference of {duration_diff_in_secs} seconds",); + intro_data + })?; + + + Some(matched_intro) }) }; diff --git a/src/models/streaming_server.rs b/src/models/streaming_server.rs index 25674dce1..bf68d7776 100644 --- a/src/models/streaming_server.rs +++ b/src/models/streaming_server.rs @@ -409,8 +409,11 @@ impl UpdateWithCtx for StreamingServer { _ => Effects::none().unchanged(), }, Msg::Internal(Internal::UpdateStreamSource { stream }) => { - let effects = - update_stream_source_effects::(self.base_url.as_ref(), stream.to_owned()); + let effects = update_stream_source_effects::( + self.base_url.clone(), + self.selected.transport_url.clone(), + stream.to_owned(), + ); effects } @@ -979,15 +982,18 @@ pub async fn get_filename( /// Updates the stream_source and generates a correct streaming_url pub fn update_stream_source_effects( - transport_url: Option<&Url>, + base_url: Option, + transport_url: Url, stream: Stream, ) -> Effects { - let streaming_server_url = transport_url.cloned(); + let streaming_server_url = transport_url.clone(); let effect = EffectFuture::Concurrent( - update_stream_source_streaming_url::(streaming_server_url.clone(), stream.clone()) - .map(enclose!((stream) move |result| - Msg::Internal(Internal::StreamingServerStreamSourceResult{ original: stream, result, streaming_server_url }) + update_stream_source_streaming_url::(base_url.clone(), streaming_server_url.clone(), stream.clone()) + .map(enclose!((base_url, streaming_server_url, stream) move |result| + { + tracing::warn!("We have a Result from converting the stream"); + Msg::Internal(Internal::StreamingServerStreamSourceResult{ original: stream, result, streaming_server_url: base_url.map(|_| streaming_server_url) })} )) .boxed_env() ); @@ -998,12 +1004,13 @@ pub fn update_stream_source_effects( /// Updates a StreamSource if it's RAR or ZIP urls by calling the server (if present) /// and creating a streaming url for a given file (either with `file_idx` or `file_must_include`). pub async fn update_stream_source_streaming_url( - transport_url: Option, - mut stream: Stream, + base_url: Option, + streaming_server_url: Url, + stream: Stream, ) -> Result, EnvError> { - match (transport_url, stream.source.to_owned()) { + match (base_url, stream.source.to_owned()) { ( - Some(streaming_server_url), + Some(_), StreamSource::Rar { file_idx, file_must_include, @@ -1014,28 +1021,56 @@ pub async fn update_stream_source_streaming_url( return Err(EnvError::Other("No RAR URLs provided".into())); } - // error on Url::join should never happen. - let create_stream_url = streaming_server_url - .join("rar/stream") - .map_err(|err| EnvError::Other(err.to_string()))?; - - let request = Request::post(create_stream_url.as_str()) - .header(http::header::CONTENT_TYPE, "application/json") - .body(rar_urls) - .expect("request builder failed"); + let streaming_server_url_request = streaming_server_url.clone(); + let key = uuid::Uuid::new_v4().to_string(); + let request_key = key.clone(); + // run concurrently the request for making the zip/create request to the server + E::exec_concurrent(async move { + let create_stream_url = streaming_server_url_request + .join(&format!("rar/create/{request_key}")) + .expect("Url should always be valid"); + + let request = Request::post(create_stream_url.as_str()) + .header(http::header::CONTENT_TYPE, "application/json") + .header(http::header::ACCEPT, "*/*") + // .header(http::header::ORIGIN, "localhost") + .body(rar_urls.clone()) + .expect("request builder failed"); + + tracing::trace!( + "Server Request for rar: {:?}\nJSON Body:{}", + request, + serde_json::to_string(&rar_urls).unwrap() + ); - let response = E::fetch::<_, ArchiveCreateResponse>(request).await?; - let response_key = response - .key - .filter(|key| !key.is_empty()) - .ok_or_else(|| EnvError::Other("Could not create RAR key".into()))?; + let response_key = E::fetch::<_, ArchiveCreateResponse>(request) + .await + .and_then(|response| { + response + .key + .filter(|key| !key.is_empty()) + .ok_or_else(|| EnvError::Other("Could not create rar key".into())) + }); + + match response_key { + Ok(key) => { + tracing::info!("Successful request to the Server for creating a Rar stream with key: {key}") + } + Err(err) => { + tracing::error!( + "Error creating Rar stream, no confirmation returned by the server: {}", + err + ) + } + } + }); let mut stream_url = streaming_server_url .join("rar/stream") .map_err(|err| EnvError::Other(err.to_string()))?; let query_pairs = ArchiveStreamRequest { - response_key, + key, options: ArchiveStreamOptions { file_idx, file_must_include, @@ -1044,10 +1079,56 @@ pub async fn update_stream_source_streaming_url( .to_query_pairs(); stream_url.query_pairs_mut().extend_pairs(query_pairs); - Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })) + return Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })); + // let mut stream_url = streaming_server_url + // .join("rar/stream") + // .map_err(|err| EnvError::Other(err.to_string()))?; + + // let query_pairs = ArchiveStreamRequest { + // key: response_key, + // options: ArchiveStreamOptions { + // file_idx, + // file_must_include, + // }, + // } + // .to_query_pairs(); + // stream_url.query_pairs_mut().extend_pairs(query_pairs); + + // Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })) + // error on Url::join should never happen. + // let create_stream_url = streaming_server_url + // .join("rar/stream") + // .map_err(|err| EnvError::Other(err.to_string()))?; + + // let request = Request::post(create_stream_url.as_str()) + // .header(http::header::CONTENT_TYPE, "application/json") + // .body(rar_urls) + // .expect("request builder failed"); + + // let response = E::fetch::<_, ArchiveCreateResponse>(request).await?; + // let response_key = response + // .key + // .filter(|key| !key.is_empty()) + // .ok_or_else(|| EnvError::Other("Could not create RAR key".into()))?; + + // let mut stream_url = streaming_server_url + // .join("rar/stream") + // .map_err(|err| EnvError::Other(err.to_string()))?; + + // let query_pairs = ArchiveStreamRequest { + // key: response_key, + // options: ArchiveStreamOptions { + // file_idx, + // file_must_include, + // }, + // } + // .to_query_pairs(); + // stream_url.query_pairs_mut().extend_pairs(query_pairs); + + // Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })) } ( - Some(streaming_server_url), + Some(_), StreamSource::Zip { file_idx, file_must_include, @@ -1058,30 +1139,55 @@ pub async fn update_stream_source_streaming_url( return Err(EnvError::Other("No RAR URLs provided".into())); } - let create_stream_url = streaming_server_url - .join("zip/create") - .map_err(|err| EnvError::Other(err.to_string()))?; - - let request = Request::post(create_stream_url.as_str()) - .header(http::header::CONTENT_TYPE, "application/json") - .header(http::header::ACCEPT, "*/*") - .body(zip_urls.clone()) - .expect("request builder failed"); - - tracing::debug!("Server Request for zip: {:?}\nJSON Body:{}", request, serde_json::to_string(&zip_urls).unwrap()); + let streaming_server_url_request = streaming_server_url.clone(); + let key = uuid::Uuid::new_v4().to_string(); + let request_key = key.clone(); + // run concurrently the request for making the zip/create request to the server + E::exec_concurrent(async move { + let create_stream_url = streaming_server_url_request + .join(&format!("zip/create/{request_key}")) + .expect("Url should always be valid"); + + let request = Request::post(create_stream_url.as_str()) + .header(http::header::CONTENT_TYPE, "application/json") + .header(http::header::ACCEPT, "*/*") + .body(zip_urls.clone()) + .expect("request builder failed"); + + tracing::trace!( + "Server Request for zip: {:?}\nJSON Body:{}", + request, + serde_json::to_string(&zip_urls).unwrap() + ); - let response = E::fetch::<_, ArchiveCreateResponse>(request).await?; - let response_key = response - .key - .filter(|key| !key.is_empty()) - .ok_or_else(|| EnvError::Other("Could not create RAR key".into()))?; + let response_key = E::fetch::<_, ArchiveCreateResponse>(request) + .await + .and_then(|response| { + response + .key + .filter(|key| !key.is_empty()) + .ok_or_else(|| EnvError::Other("Could not create zip key".into())) + }); + + match response_key { + Ok(key) => { + tracing::info!("Successful request to the Server for creating a zip stream with key: {key}") + } + Err(err) => { + tracing::error!( + "Error creating zip stream, no confirmation returned by the server: {}", + err + ) + } + } + }); let mut stream_url = streaming_server_url .join("zip/stream") .map_err(|err| EnvError::Other(err.to_string()))?; let query_pairs = ArchiveStreamRequest { - response_key, + key, options: ArchiveStreamOptions { file_idx, file_must_include, @@ -1092,9 +1198,77 @@ pub async fn update_stream_source_streaming_url( Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })) } - (None, StreamSource::Rar { .. } | StreamSource::Zip { .. }) => Err(EnvError::Other( - "Can't play Rar/Zip because streaming server is not running".into(), - )), + (Some(_), StreamSource::Nzb {nzb_url, servers}) => { + if servers.is_empty() { + return Err(EnvError::Other("No server URLs provided".into())); + } + + let streaming_server_url_request = streaming_server_url.clone(); + let key = uuid::Uuid::new_v4().to_string(); + let request_key = key.clone(); + let nzb_body = stream.source.clone(); + // run concurrently the request for making the nzb/create request to the server + E::exec_concurrent(async move { + let create_stream_url = streaming_server_url_request + .join(&format!("nzb/create/{request_key}")) + .expect("Url should always be valid"); + + let request = Request::post(create_stream_url.as_str()) + .header(http::header::CONTENT_TYPE, "application/json") + .header(http::header::ACCEPT, "*/*") + .body(nzb_body.clone()) + .expect("request builder failed"); + + tracing::trace!( + "Server Request for nzb: {:?}\nJSON Body:{}", + request, + serde_json::to_string(&nzb_body).unwrap() + ); + + let response_key = E::fetch::<_, ArchiveCreateResponse>(request) + .await + .and_then(|response| { + response + .key + .filter(|key| !key.is_empty()) + .ok_or_else(|| EnvError::Other("Could not create nzb key".into())) + }); + + match response_key { + Ok(key) => { + tracing::info!("Successful request to the Server for creating a nzb stream with key: {key}") + } + Err(err) => { + tracing::error!( + "Error creating nzb stream, no confirmation returned by the server: {}", + err + ) + } + } + }); + + let mut stream_url = streaming_server_url + .join("nzb/stream") + .map_err(|err| EnvError::Other(err.to_string()))?; + + let query_pairs = ArchiveStreamRequest { + key, + // nzb does not have options + options: ArchiveStreamOptions { + file_idx: None, + file_must_include: vec![], + }, + } + .to_query_pairs(); + stream_url.query_pairs_mut().extend_pairs(query_pairs); + + Ok(stream.to_converted(ConvertedStreamSource::Url { url: stream_url })) + } + (None, StreamSource::Rar { .. } | StreamSource::Zip { .. } | StreamSource::Nzb { .. }) => { + Err(EnvError::Other( + "Can't play Rar/Zip/Uzb because streaming server is not running".into(), + )) + } // no further changes are needed for now // we still need to create torrents, etc. in stremio-video // as it's not part of the current scope diff --git a/src/types/resource/stream.rs b/src/types/resource/stream.rs index 8fb59ea18..374c14577 100644 --- a/src/types/resource/stream.rs +++ b/src/types/resource/stream.rs @@ -185,6 +185,9 @@ impl Stream { file_idx: _, file_must_include: _, } => None, + StreamSource::Nzb { + .. + } => None, StreamSource::Torrent { .. } => { self.magnet_url().map(|magnet_url| magnet_url.to_string()) } @@ -476,7 +479,7 @@ pub enum StreamSource { }, #[serde(rename_all = "camelCase")] Rar { - rar_urls: Vec, + rar_urls: Vec, #[serde(default)] file_idx: Option, #[serde(default, skip_serializing_if = "Vec::is_empty")] @@ -485,7 +488,7 @@ pub enum StreamSource { }, #[serde(rename_all = "camelCase")] Zip { - zip_urls: Vec, + zip_urls: Vec, #[serde(default)] file_idx: Option, #[serde(default, skip_serializing_if = "Vec::is_empty")] @@ -493,6 +496,12 @@ pub enum StreamSource { file_must_include: Vec, }, #[serde(rename_all = "camelCase")] + Nzb { + nzb_url: Url, + #[serde(default)] + servers: Vec, + }, + #[serde(rename_all = "camelCase")] Torrent { #[serde(with = "SerHex::")] info_hash: [u8; 20], @@ -525,6 +534,13 @@ pub enum StreamSource { }, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct ArchiveUrl { + pub url: Url, + /// File size (if known) in Bytes + pub bytes: Option, +} + type ExternalStreamSource = (Option, Option, Option, Option); pub(crate) fn deserialize_stream_source_external<'de, D>( @@ -592,6 +608,11 @@ fn is_default_value(value: &T) -> bool { *value == T::default() } +// ArchiveUrl { +// url: Url, + +// } + #[derive(Clone, derivative::Derivative, Serialize, Debug, PartialEq, Eq)] pub struct StreamUrls { #[serde(default)] diff --git a/src/types/streaming_server/request.rs b/src/types/streaming_server/request.rs index ebec0e85e..d5c6b77b2 100644 --- a/src/types/streaming_server/request.rs +++ b/src/types/streaming_server/request.rs @@ -4,31 +4,29 @@ use url::Url; use crate::types::{streaming_server::PeerSearch, torrent::InfoHash}; -pub struct ArchiveStreamRequest { +pub struct ArchiveStreamRequest { /// The `rar/create` or `zip/create` key returned in the response - pub response_key: String, + pub key: Key, pub options: ArchiveStreamOptions, } impl ArchiveStreamRequest { pub fn to_query_pairs(self) -> Vec<(String, String)> { let options = serde_json::to_value(&self.options).expect("should serialize"); - let options_object = options.as_object().expect("Should be an object"); - vec![ + let mut query_params = vec![ ( "key".into(), - // append the length of the options - // keep in mind that `None` options should always be treated as not-set - // i.e. should not be serialized - format!( - "{key}{length}", - key = self.response_key, - length = options_object.len() - ), + self.key.to_owned() ), - ("o".into(), options.to_string()), - ] + ]; + + if self.options != ArchiveStreamOptions::default() { + query_params.push(("o".into(), options.to_string())); + } + + query_params + } } @@ -37,7 +35,7 @@ impl ArchiveStreamRequest { /// Format: `rar/stream?key={create_key}{options length}&o={options_json_string}` /// /// Where all parameters are url encoded. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ArchiveStreamOptions { #[serde(skip_serializing_if = "Option::is_none")] diff --git a/stremio-core-web/Cargo.toml b/stremio-core-web/Cargo.toml index 156efe0c7..28ae5dae5 100644 --- a/stremio-core-web/Cargo.toml +++ b/stremio-core-web/Cargo.toml @@ -12,7 +12,7 @@ default = ["std", "wasm"] std = [] # enable wasm bindings exports, enabled by default (stremio-core-web crate after all) -wasm = ["env", "dep:wasm-bindgen", "dep:wasm-bindgen-futures", "dep:gloo-utils", "dep:tracing-wasm", "dep:console_error_panic_hook", "dep:js-sys", "dep:web-sys", "getrandom?/js"] +wasm = ["stremio-core/wasm", "env", "dep:wasm-bindgen", "dep:wasm-bindgen-futures", "dep:gloo-utils", "dep:tracing-wasm", "dep:console_error_panic_hook", "dep:js-sys", "dep:web-sys", "getrandom?/js"] # Enable's the wasm Env. impl # (this means that `wasm` feature is a superset of this one) env = ["dep:http", "dep:regex", "dep:hex", "dep:getrandom", "dep:serde_path_to_error"] diff --git a/stremio-core-web/src/env.rs b/stremio-core-web/src/env.rs index ec502bd31..d500f0f40 100644 --- a/stremio-core-web/src/env.rs +++ b/stremio-core-web/src/env.rs @@ -139,6 +139,7 @@ impl WebEnv { StreamSource::Torrent { .. } => "Torrent", StreamSource::Rar { .. } => "Rar", StreamSource::Zip { .. } => "Zip", + StreamSource::Nzb { .. } => "Nzb", StreamSource::External { .. } => "External", StreamSource::PlayerFrame { .. } => "PlayerFrame" } @@ -267,11 +268,6 @@ impl Env for WebEnv { { let (parts, body) = request.into_parts(); let url = parts.uri.to_string(); - let url = if url.ends_with("zip/create") { - "http://127.0.0.1/zip/create".into() - } else { - url - }; let method = parts.method.as_str(); let headers = { let mut headers = HashMap::new(); @@ -303,8 +299,7 @@ impl Env for WebEnv { let body = match serde_json::to_string(&body) { Ok(ref body) if body != "null" && parts.method != Method::GET => { let js_value = JsValue::from_str(body); - tracing::info!("JsValue Body: {:?}", &js_value); - tracing::info!("url: {:?}", &url); + // tracing::info!("url: {} JsValue Body: {:?}", &url, &js_value); Some(js_value) } _ => None, @@ -318,11 +313,16 @@ impl Env for WebEnv { let request = web_sys::Request::new_with_str_and_init(&url, &request_options) .expect("request builder failed"); let promise = global().fetch_with_request(&request); - async { - tracing::info!("{:?}", &promise); + async move { let js_fut = JsFuture::from(promise); let resp = js_fut.await.map_err(|error| { - tracing::info!("{:?}", error); + tracing::error!( + "{:?}\n Method: {} Url: {}\nBody{}", + error, + parts.method, + url, + body.map(|js_value| js_value.as_string().unwrap_or_default()).unwrap_or_default() + ); EnvError::Fetch( error .dyn_into::() diff --git a/stremio-core-web/src/model/serialize_player.rs b/stremio-core-web/src/model/serialize_player.rs index db7d5700f..d3d96151e 100644 --- a/stremio-core-web/src/model/serialize_player.rs +++ b/stremio-core-web/src/model/serialize_player.rs @@ -105,7 +105,6 @@ mod model { #[serde(rename_all = "camelCase")] pub struct Player<'a> { pub selected: Option>, - #[serde(skip_serializing_if = "Loadable::is_loading")] pub stream: Loadable, &'a EnvError>, pub meta_item: Option, &'a ResourceError>>, pub subtitles: Vec>,