From 9d6411fd92e73c204425f8dd37dc3cf567f604e4 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 30 Jan 2025 18:34:09 +0100 Subject: avoid transitive crate deps by re-export --- Cargo.lock | 4 - base/Cargo.toml | 1 + base/src/lib.rs | 2 + common/src/config.rs | 1 - common/src/lib.rs | 4 + import/Cargo.toml | 1 - import/src/infojson.rs | 2 +- import/src/lib.rs | 44 ++-- import/src/matroska.rs | 2 +- import/src/tmdb.rs | 10 +- import/src/trakt.rs | 6 +- remuxer/Cargo.toml | 1 - remuxer/src/extract.rs | 2 +- remuxer/src/fragment.rs | 2 +- remuxer/src/lib.rs | 3 +- remuxer/src/metadata.rs | 378 ----------------------------------- remuxer/src/remux.rs | 2 +- remuxer/src/seek_index.rs | 6 +- server/src/routes/external_compat.rs | 6 +- server/src/routes/ui/home.rs | 29 +-- stream/Cargo.toml | 3 +- stream/src/fragment.rs | 13 +- stream/src/hls.rs | 10 +- stream/src/jhls.rs | 15 +- stream/src/lib.rs | 13 +- stream/src/webvtt.rs | 7 +- transcoder/Cargo.toml | 1 - transcoder/src/fragment.rs | 6 +- transcoder/src/subtitles.rs | 2 +- 29 files changed, 119 insertions(+), 457 deletions(-) delete mode 100644 remuxer/src/metadata.rs diff --git a/Cargo.lock b/Cargo.lock index 55c12c8..863b2fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1756,7 +1756,6 @@ dependencies = [ "futures", "jellybase", "jellyclient", - "jellycommon", "log", "rayon", "regex", @@ -1785,7 +1784,6 @@ dependencies = [ "anyhow", "bincode", "jellybase", - "jellycommon", "jellymatroska", "log", "serde", @@ -1798,7 +1796,6 @@ version = "0.1.0" dependencies = [ "anyhow", "jellybase", - "jellycommon", "jellyremuxer", "jellytranscoder", "log", @@ -1873,7 +1870,6 @@ dependencies = [ "image", "imgref", "jellybase", - "jellycommon", "jellyremuxer", "libavif-image", "log", diff --git a/base/Cargo.toml b/base/Cargo.toml index b9e47de..e897404 100644 --- a/base/Cargo.toml +++ b/base/Cargo.toml @@ -22,3 +22,4 @@ aes-gcm-siv = "0.11.1" [features] db_json = [] +rocket = ["jellycommon/rocket"] diff --git a/base/src/lib.rs b/base/src/lib.rs index cf28d85..cb5bae7 100644 --- a/base/src/lib.rs +++ b/base/src/lib.rs @@ -9,6 +9,8 @@ pub mod database; pub mod federation; pub mod permission; +pub use jellycommon as common; + use jellycommon::config::{GlobalConfig, SecretsConfig}; use std::sync::{ atomic::{AtomicBool, Ordering}, diff --git a/common/src/config.rs b/common/src/config.rs index 682fdd7..4ff1477 100644 --- a/common/src/config.rs +++ b/common/src/config.rs @@ -23,7 +23,6 @@ pub struct GlobalConfig { #[serde(default = "default::secrets_path")] pub secrets_path: PathBuf, #[serde(default = "default::transcoding_profiles")] pub transcoding_profiles: Vec, #[serde(default = "default::max_in_memory_cache_size")] pub max_in_memory_cache_size: usize, - #[serde(default)] pub use_in_memory_import_storage: bool, #[serde(default)] pub admin_username: Option, #[serde(default = "default::login_expire")] pub login_expire: i64, #[serde(default)] pub default_permission_set: PermissionSet, diff --git a/common/src/lib.rs b/common/src/lib.rs index 503febd..5dadd1c 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -25,6 +25,7 @@ pub struct NodeID(pub [u8; 32]); #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Node { pub slug: String, + #[serde(default)] pub parents: Vec, pub kind: Option, pub poster: Option, @@ -36,9 +37,12 @@ pub struct Node { pub release_date: Option, // in unix millis pub index: Option, pub media: Option, + #[serde(default)] pub ratings: BTreeMap, pub federated: Option, + #[serde(default)] pub people: BTreeMap>, + #[serde(default)] pub external_ids: BTreeMap, } diff --git a/import/Cargo.toml b/import/Cargo.toml index 988e626..645326d 100644 --- a/import/Cargo.toml +++ b/import/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -jellycommon = { path = "../common" } jellybase = { path = "../base" } jellyclient = { path = "../client" } diff --git a/import/src/infojson.rs b/import/src/infojson.rs index 3e4667e..69c28ca 100644 --- a/import/src/infojson.rs +++ b/import/src/infojson.rs @@ -5,7 +5,7 @@ */ use anyhow::Context; use bincode::{Decode, Encode}; -use jellycommon::chrono::{format::Parsed, Utc}; +use jellybase::common::chrono::{format::Parsed, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/import/src/lib.rs b/import/src/lib.rs index c841294..4203ba1 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -5,16 +5,20 @@ */ use anyhow::{anyhow, Context, Result}; use infojson::YVideo; -use jellybase::{assetfed::AssetInner, database::Database, CONF, SECRETS}; -use jellycommon::{ - Chapter, LocalTrack, MediaInfo, Node, NodeID, NodeKind, Rating, SourceTrack, SourceTrackKind, - TrackSource, +use jellybase::{ + assetfed::AssetInner, + common::{ + Chapter, LocalTrack, MediaInfo, Node, NodeID, NodeKind, Rating, SourceTrack, + SourceTrackKind, TrackSource, + }, + database::Database, + CONF, SECRETS, }; use matroska::matroska_metadata; use rayon::iter::{ParallelDrainRange, ParallelIterator}; use std::{ collections::HashMap, - fs::File, + fs::{read_to_string, File}, io::BufReader, mem::swap, path::{Path, PathBuf}, @@ -118,32 +122,37 @@ fn import_iter_inner(path: &Path, db: &Database, incremental: bool) -> Result Result<()> { - let parent_slug = path - .parent() - .ok_or(anyhow!("no parent"))? - .file_name() - .ok_or(anyhow!("parent no filename"))? - .to_string_lossy(); + let parent_slug = if path == CONF.media_path { + "library".to_string() + } else { + path.parent() + .ok_or(anyhow!("no parent"))? + .file_name() + .ok_or(anyhow!("parent no filename"))? + .to_string_lossy() + .to_string() + }; let parent = NodeID::from_slug(&parent_slug); let filename = path.file_name().unwrap().to_string_lossy(); match filename.as_ref() { - "poster.jpeg" | "poster.webp" => { + "poster.jpeg" | "poster.webp" | "poster.png" => { db.update_node_init(parent, |node| { node.slug = parent_slug.to_string(); node.poster = Some(AssetInner::Media(path.to_owned()).ser()); Ok(()) })?; } - "backdrop.jpeg" | "backdrop.webp" => { + "backdrop.jpeg" | "backdrop.webp" | "backdrop#.png" => { db.update_node_init(parent, |node| { node.slug = parent_slug.to_string(); node.backdrop = Some(AssetInner::Media(path.to_owned()).ser()); Ok(()) })?; } - "info.json" | "info.yaml" => { - let data = serde_yaml::from_reader::<_, Node>(BufReader::new(File::open(path)?))?; + "node.json" | "node.yaml" => { + let raw = format!("slug: {parent_slug}\n{}", read_to_string(path)?); + let data = serde_yaml::from_str::(&raw)?; db.update_node_init(parent, |node| { node.slug = parent_slug.to_string(); fn merge_option(a: &mut Option, b: Option) { @@ -151,9 +160,14 @@ fn import_file(db: &Database, path: &Path) -> Result<()> { *a = b; } } + merge_option(&mut node.kind, data.kind); merge_option(&mut node.title, data.title); merge_option(&mut node.tagline, data.tagline); merge_option(&mut node.description, data.description); + merge_option(&mut node.index, data.index); + merge_option(&mut node.release_date, data.release_date); + node.external_ids.extend(data.external_ids); + Ok(()) })?; } diff --git a/import/src/matroska.rs b/import/src/matroska.rs index 6a33420..f9a59ab 100644 --- a/import/src/matroska.rs +++ b/import/src/matroska.rs @@ -14,8 +14,8 @@ use ebml_struct::{ use jellybase::{ assetfed::AssetInner, cache::{cache_file, cache_memory}, + common::Asset, }; -use jellycommon::Asset; use log::info; use std::{ fs::File, diff --git a/import/src/tmdb.rs b/import/src/tmdb.rs index 522d9d6..678ce61 100644 --- a/import/src/tmdb.rs +++ b/import/src/tmdb.rs @@ -5,10 +5,12 @@ */ use anyhow::{anyhow, bail, Context}; use bincode::{Decode, Encode}; -use jellybase::cache::{async_cache_file, async_cache_memory, CachePath}; -use jellycommon::{ - chrono::{format::Parsed, Utc}, - TmdbKind, +use jellybase::{ + cache::{async_cache_file, async_cache_memory, CachePath}, + common::{ + chrono::{format::Parsed, Utc}, + TmdbKind, + }, }; use log::info; use reqwest::{ diff --git a/import/src/trakt.rs b/import/src/trakt.rs index f37eb74..98532c5 100644 --- a/import/src/trakt.rs +++ b/import/src/trakt.rs @@ -4,8 +4,10 @@ Copyright (C) 2025 metamuffin */ use bincode::{Decode, Encode}; -use jellybase::cache::async_cache_memory; -use jellycommon::{Appearance, ObjectIds, PeopleGroup, Person, TraktKind}; +use jellybase::{ + cache::async_cache_memory, + common::{Appearance, ObjectIds, PeopleGroup, Person, TraktKind}, +}; use reqwest::{ header::{HeaderMap, HeaderName, HeaderValue}, Client, ClientBuilder, diff --git a/remuxer/Cargo.toml b/remuxer/Cargo.toml index 3386717..2313dcc 100644 --- a/remuxer/Cargo.toml +++ b/remuxer/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -jellycommon = { path = "../common" } jellymatroska = { path = "../matroska" } jellybase = { path = "../base" } diff --git a/remuxer/src/extract.rs b/remuxer/src/extract.rs index 364d33c..12e4003 100644 --- a/remuxer/src/extract.rs +++ b/remuxer/src/extract.rs @@ -5,7 +5,7 @@ */ use crate::seek_index::get_seek_index; use anyhow::{anyhow, bail}; -use jellycommon::LocalTrack; +use jellybase::common::LocalTrack; use jellymatroska::{block::Block, read::EbmlReader, Master, MatroskaTag}; use log::debug; use std::{fs::File, io::BufReader, path::PathBuf}; diff --git a/remuxer/src/fragment.rs b/remuxer/src/fragment.rs index 3cd122e..d7adc41 100644 --- a/remuxer/src/fragment.rs +++ b/remuxer/src/fragment.rs @@ -9,7 +9,7 @@ use crate::{ segment_extractor::SegmentExtractIter, }; use anyhow::{anyhow, Context, Result}; -use jellycommon::{LocalTrack, Node, SourceTrackKind}; +use jellybase::common::{LocalTrack, Node, SourceTrackKind}; use jellymatroska::{read::EbmlReader, write::EbmlWriter, Master, MatroskaTag}; use log::{debug, info}; use std::{ diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index 7f5ad1c..3ea16e2 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -5,7 +5,6 @@ */ pub mod extract; pub mod fragment; -pub mod metadata; pub mod remux; pub mod seek_index; pub mod segment_extractor; @@ -14,7 +13,7 @@ pub mod trim_writer; pub use fragment::write_fragment_into; pub use remux::remux_stream_into; -use jellycommon::{SourceTrack, SourceTrackKind}; +use jellybase::common::{SourceTrack, SourceTrackKind}; use jellymatroska::{Master, MatroskaTag}; pub fn ebml_header(webm: bool) -> MatroskaTag { diff --git a/remuxer/src/metadata.rs b/remuxer/src/metadata.rs deleted file mode 100644 index 3e14821..0000000 --- a/remuxer/src/metadata.rs +++ /dev/null @@ -1,378 +0,0 @@ -/* - This file is part of jellything (https://codeberg.org/metamuffin/jellything) - which is licensed under the GNU Affero General Public License (version 3); see /COPYING. - Copyright (C) 2025 metamuffin -*/ -use anyhow::{anyhow, bail, Context, Result}; -use bincode::{Decode, Encode}; -use jellycommon::{Chapter, LocalTrack, SourceTrack, SourceTrackKind, TrackSource}; -use jellymatroska::{ - matroska::MatroskaTag, - read::EbmlReader, - unflatten::{Unflat, Unflatten}, -}; -use log::{debug, error, info, warn}; -use std::{path::PathBuf, time::Instant}; - -#[derive(Default, Clone, Debug, Encode, Decode)] -pub struct MatroskaMetadata { - pub title: Option, - pub description: Option, - pub tagline: Option, - pub tracks: Vec, - pub track_sources: Vec, - pub cover: Option<(String, Vec)>, - pub infojson: Option, - pub chapters: Vec, - pub duration: f64, -} - -pub fn import_metadata(input: &mut EbmlReader) -> Result { - while let Some(item) = input.next() { - let item = match item { - Ok((_, item)) => item, - Err(e) => { - if !matches!(e, jellymatroska::error::Error::Io(_)) { - warn!("{e}"); - } - break; - } - }; - match item { - MatroskaTag::Ebml(_) => { - let mut iter = Unflatten::new_with_end(input, item); - while let Some(Ok(Unflat { - children: _, item, .. - })) = iter.n() - { - match item { - MatroskaTag::DocType(t) => { - if !matches!(t.as_str(), "matroska" | "webm") { - error!("file is neither matroska nor webm but {:?}", t) - } - } - _ => debug!("(re) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Segment(_) => { - info!("extracting metadata..."); - let mut children = Unflatten::new_with_end(input, item); - let t = Instant::now(); - let r = import_read_segment(&mut children)?; - info!("done in {:?}", t.elapsed()); - return Ok(r); - } - _ => debug!("(r) tag ignored: {item:?}"), - } - } - Err(anyhow!("no segment found")) -} - -fn import_read_segment(segment: &mut Unflatten) -> Result { - let (mut timestamp_scale, mut duration) = (None, None); - let mut m = MatroskaMetadata::default(); - - let ( - mut info_found, - mut tags_found, - mut attachments_found, - mut tracks_found, - mut found_chapters, - ) = (false, false, false, false, false); - - while let Some(Ok(Unflat { children, item, .. })) = segment.n() { - match item { - MatroskaTag::SeekHead(_) => {} - MatroskaTag::Info(_) => { - info_found = true; - let mut children = children.unwrap(); - while let Some(Ok(Unflat { - children: _, item, .. - })) = children.n() - { - match item { - MatroskaTag::Title(t) => m.title = Some(t), - MatroskaTag::TimestampScale(v) => timestamp_scale = Some(v), - MatroskaTag::Duration(v) => duration = Some(v), - _ => debug!("(rsi) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Void(_) => {} - MatroskaTag::Tags(_) => { - tags_found = true; - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::Tag(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::SimpleTag(_) => { - let (mut key, mut value) = (None, None); - let mut children = children.unwrap(); - while let Some(Ok(Unflat { - children: _, item, .. - })) = children.n() - { - match item { - MatroskaTag::TagName(k) => key = Some(k), - MatroskaTag::TagString(v) => value = Some(v), - _ => debug!("(rstts) tag ignored: {item:?}"), - } - } - match (key, value) { - (Some(key), Some(value)) => match key.as_str() { - "DESCRIPTION" => m.description = Some(value), - "COMMENT" => m.tagline = Some(value), - _ => debug!("simple tag ignored: {key:?}"), - }, - (None, None) => (), - _ => warn!("simple tag with only one of name/string"), - } - } - _ => debug!("(rstt) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Crc32(_) => {} - _ => debug!("(rst) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Attachments(_) => { - attachments_found = true; - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::AttachedFile(_) => { - let (mut name, mut data, mut mime) = Default::default(); - let mut children = children.unwrap(); - while let Some(Ok(Unflat { - children: _, item, .. - })) = children.n() - { - match item { - MatroskaTag::FileName(n) => name = Some(n), - MatroskaTag::FileData(d) => data = Some(d), - MatroskaTag::FileMimeType(m) => mime = Some(m), - _ => debug!("(rsaa) tag ignored: {item:?}"), - } - } - let (name, data, mime) = ( - name.ok_or(anyhow!("attachment without name"))?, - data.ok_or(anyhow!("attachment without data"))?, - mime.ok_or(anyhow!("attachment without mime type"))?, - ); - info!("attachment found: {name:?} type {mime:?}"); - match (name.as_str(), mime.as_str()) { - ("info.json", "application/json") => { - m.infojson = - Some(String::from_utf8(data).context("info.json invalid")?) - } - (_, "image/jpeg" | "image/png" | "image/webp") => { - m.cover = Some((mime, data)) - } - _ => (), - } - } - _ => debug!("(rsa) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Cues(_) => {} - MatroskaTag::Chapters(_) => { - found_chapters = true; - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::EditionEntry(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::EditionUID(_) - | MatroskaTag::EditionFlagHidden(_) - | MatroskaTag::EditionFlagDefault(_) => {} - MatroskaTag::ChapterAtom(_) => { - let mut children = children.unwrap(); - let mut chap = Chapter::default(); - while let Some(Ok(Unflat { children, item, .. })) = - children.n() - { - match item { - MatroskaTag::ChapterFlagEnabled(_) - | MatroskaTag::ChapterFlagHidden(_) - | MatroskaTag::ChapterUID(_) => (), - MatroskaTag::ChapterTimeStart(t) => { - chap.time_start = Some(t as f64 * 1e-9) - } - MatroskaTag::ChapterTimeEnd(t) => { - chap.time_end = Some(t as f64 * 1e-9) - } - MatroskaTag::ChapterDisplay(_) => { - let mut string = String::new(); - let mut lang = String::new(); - let mut children = children.unwrap(); - while let Some(Ok(Unflat { item, .. })) = - children.n() - { - match item { - MatroskaTag::ChapString(s) => { - string = s - } - MatroskaTag::ChapLanguage(l) => { - lang = l - } - _ => warn!( - "(rscead) tag ignored: {item:?}" - ), - } - } - chap.labels.push((lang, string)) - } - _ => warn!("(rscea) tag ignored: {item:?}"), - } - } - m.chapters.push(chap); - } - _ => warn!("(rsce) tag ignored: {item:?}"), - } - } - if !m.chapters.is_empty() { - info!("{} chapters added", m.chapters.len()); - } - } - _ => warn!("(rsc) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Tracks(_) => { - tracks_found = true; - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::TrackEntry(_) => { - let mut children = children.unwrap(); - let ( - mut index, - mut language, - mut codec, - mut kind, - mut sample_rate, - mut channels, - mut width, - mut height, - mut display_width, - mut display_height, - mut name, - mut fps, - mut bit_depth, - mut codec_private, - mut default_duration, - mut display_unit, - ) = ( - None, None, None, None, None, None, None, None, None, None, None, - None, None, None, None, None, - ); - while let Some(Ok(Unflat { children, item, .. })) = children.n() { - match item { - MatroskaTag::CodecID(b) => codec = Some(b), - MatroskaTag::Language(v) => language = Some(v), - MatroskaTag::TrackNumber(v) => index = Some(v), - MatroskaTag::TrackType(v) => kind = Some(v), - MatroskaTag::Name(v) => name = Some(v), - MatroskaTag::CodecPrivate(v) => codec_private = Some(v), - MatroskaTag::DefaultDuration(v) => default_duration = Some(v), - MatroskaTag::Audio(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { item, .. })) = children.n() { - match item { - MatroskaTag::Channels(v) => { - channels = Some(v as usize) - } - MatroskaTag::SamplingFrequency(v) => { - sample_rate = Some(v) - } - MatroskaTag::BitDepth(v) => bit_depth = Some(v), - _ => (), - } - } - } - MatroskaTag::Video(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { item, .. })) = children.n() { - match item { - MatroskaTag::PixelWidth(v) => width = Some(v), - MatroskaTag::PixelHeight(v) => height = Some(v), - MatroskaTag::DisplayWidth(v) => { - display_width = Some(v) - } - MatroskaTag::DisplayHeight(v) => { - display_height = Some(v) - } - MatroskaTag::DisplayUnit(v) => { - display_unit = Some(v) - } - MatroskaTag::FrameRate(v) => fps = Some(v), - _ => (), - } - } - } - _ => (), - } - } - let track_index = index.unwrap(); - let kind = match kind.ok_or(anyhow!("track type required"))? { - 1 => SourceTrackKind::Video { - fps, - width: width.unwrap(), - height: height.unwrap(), - display_width, - display_height, - display_unit, - }, - 2 => SourceTrackKind::Audio { - bit_depth: bit_depth.map(|x| x as usize), - channels: channels.unwrap_or(1), // TODO - sample_rate: sample_rate.unwrap_or(41_100.0), // TODO - }, - 17 => SourceTrackKind::Subtitles, - _ => bail!("invalid track type"), - }; - m.tracks.push(SourceTrack { - federated: vec![], - default_duration, - source: TrackSource::Local(LocalTrack { - track: track_index as usize, - path: PathBuf::new(), - codec_private, - }), - name: name.unwrap_or_else(|| "unnamed".to_string()), - codec: codec.unwrap(), - language: language.unwrap_or_else(|| "none".to_string()), - kind, - }); - } - MatroskaTag::Crc32(_) => {} - _ => warn!("(rst) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Cluster(_) => {} - - _ => warn!("(rs) tag ignored: {item:?}"), - }; - if info_found && tracks_found && attachments_found && tags_found && found_chapters { - debug!("we found all we need, stopping read early"); - break; - } - } - segment.exit_dirty(); - - if let Some(duration) = duration { - m.duration = (duration * timestamp_scale.unwrap_or(1_000_000) as f64) / 1_000_000_000_f64; - } - - Ok(m) -} diff --git a/remuxer/src/remux.rs b/remuxer/src/remux.rs index ef49620..a2e0d8a 100644 --- a/remuxer/src/remux.rs +++ b/remuxer/src/remux.rs @@ -8,7 +8,7 @@ use crate::{ segment_extractor::SegmentExtractIter, trim_writer::TrimWriter, }; use anyhow::{anyhow, Context}; -use jellycommon::{ +use jellybase::common::{ seek_index::{BlockIndex, SeekIndex}, LocalTrack, Node, SourceTrack, }; diff --git a/remuxer/src/seek_index.rs b/remuxer/src/seek_index.rs index 581ed9a..bd351d9 100644 --- a/remuxer/src/seek_index.rs +++ b/remuxer/src/seek_index.rs @@ -4,8 +4,10 @@ Copyright (C) 2025 metamuffin */ use anyhow::{Context, Result}; -use jellybase::cache::cache_memory; -use jellycommon::seek_index::{BlockIndex, SeekIndex}; +use jellybase::{ + cache::cache_memory, + common::seek_index::{BlockIndex, SeekIndex}, +}; use jellymatroska::{ block::Block, read::EbmlReader, diff --git a/server/src/routes/external_compat.rs b/server/src/routes/external_compat.rs index 7babfa5..eda3537 100644 --- a/server/src/routes/external_compat.rs +++ b/server/src/routes/external_compat.rs @@ -5,6 +5,7 @@ */ use super::ui::{account::session::Session, error::MyResult}; use crate::routes::ui::node::rocket_uri_macro_r_library_node; +use crate::routes::ui::player::{rocket_uri_macro_r_player, PlayerConfig}; use anyhow::anyhow; use jellybase::database::Database; use rocket::{get, response::Redirect, State}; @@ -18,7 +19,10 @@ pub fn r_ext_youtube_watch(_session: Session, db: &State, v: &str) -> Err(anyhow!("element not found"))? }; let node = db.get_node(id)?.ok_or(anyhow!("node missing"))?; - Ok(Redirect::to(rocket::uri!(r_library_node(&node.slug)))) + Ok(Redirect::to(rocket::uri!(r_player( + &node.slug, + PlayerConfig::default() + )))) } #[get("/channel/")] diff --git a/server/src/routes/ui/home.rs b/server/src/routes/ui/home.rs index ebed647..6c6fdbc 100644 --- a/server/src/routes/ui/home.rs +++ b/server/src/routes/ui/home.rs @@ -3,14 +3,19 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin */ -use super::{account::session::Session, layout::LayoutPage, node::NodeCard}; +use super::{ + account::session::Session, + layout::LayoutPage, + node::{DatabaseNodeUserDataExt, NodeCard}, +}; use crate::{ database::Database, routes::ui::{error::MyResult, layout::DynLayoutPage}, }; +use anyhow::Context; use chrono::{Datelike, Utc}; use jellybase::CONF; -use jellycommon::{user::WatchedState, Rating}; +use jellycommon::{user::WatchedState, NodeID, Rating}; use rocket::{get, State}; use tokio::fs::read_to_string; @@ -21,14 +26,12 @@ pub fn r_home(sess: Session, db: &State) -> MyResult { .flat_map(|i| Some(items[cheap_daily_random(i).checked_rem(items.len())?].clone())) .collect::>(); - // let toplevel = T_NODE - // .get(db, "library")? - // .context("root node missing")? - // .into_iter() - // .map(|n| db.get_node_with_userdata(&n, &sess)) - // .collect::>>()? - // .into_iter() - // .collect::>(); + let toplevel = db + .get_node_children(NodeID::from_slug("library")) + .context("root node missing")? + .into_iter() + .map(|n| db.get_node_with_userdata(n, &sess)) + .collect::>>()?; items.sort_by_key(|(n, _)| { n.ratings @@ -68,9 +71,9 @@ pub fn r_home(sess: Session, db: &State) -> MyResult { title: "Home".to_string(), content: markup::new! { h2 { "Explore " @CONF.brand } - // ul.children.hlist {@for (id, node, udata) in &toplevel { - // li { @NodeCard { id, node, udata } } - // }} + ul.children.hlist {@for (node, udata) in &toplevel { + li { @NodeCard { node, udata } } + }} @if !continue_watching.is_empty() { h2 { "Continue Watching" } ul.children.hlist {@for (node, udata) in &continue_watching { diff --git a/stream/Cargo.toml b/stream/Cargo.toml index b66cfca..36979c9 100644 --- a/stream/Cargo.toml +++ b/stream/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -jellycommon = { path = "../common", features = ["rocket"] } -jellybase = { path = "../base" } +jellybase = { path = "../base", features = ["rocket"] } jellytranscoder = { path = "../transcoder" } jellyremuxer = { path = "../remuxer" } diff --git a/stream/src/fragment.rs b/stream/src/fragment.rs index 2dbc716..e276d29 100644 --- a/stream/src/fragment.rs +++ b/stream/src/fragment.rs @@ -4,11 +4,14 @@ Copyright (C) 2025 metamuffin */ use anyhow::{anyhow, bail, Result}; -use jellybase::{permission::PermissionSetExt, CONF}; -use jellycommon::{ - stream::StreamSpec, - user::{PermissionSet, UserPermission}, - LocalTrack, Node, +use jellybase::{ + common::{ + stream::StreamSpec, + user::{PermissionSet, UserPermission}, + LocalTrack, Node, + }, + permission::PermissionSetExt, + CONF, }; use jellytranscoder::fragment::transcode; use log::warn; diff --git a/stream/src/hls.rs b/stream/src/hls.rs index c09b77f..dca1036 100644 --- a/stream/src/hls.rs +++ b/stream/src/hls.rs @@ -5,10 +5,12 @@ */ use anyhow::{anyhow, Result}; -use jellybase::CONF; -use jellycommon::{ - stream::{StreamFormat, StreamSpec}, - LocalTrack, Node, SourceTrackKind, +use jellybase::{ + common::{ + stream::{StreamFormat, StreamSpec}, + LocalTrack, Node, SourceTrackKind, + }, + CONF, }; use std::{fmt::Write, ops::Range, sync::Arc}; use tokio::{ diff --git a/stream/src/jhls.rs b/stream/src/jhls.rs index 28d383f..79fc5fe 100644 --- a/stream/src/jhls.rs +++ b/stream/src/jhls.rs @@ -4,12 +4,15 @@ Copyright (C) 2025 metamuffin */ use anyhow::{anyhow, Result}; -use jellybase::{permission::PermissionSetExt, CONF}; -use jellycommon::{ - jhls::JhlsTrackIndex, - stream::StreamSpec, - user::{PermissionSet, UserPermission}, - LocalTrack, Node, +use jellybase::{ + common::{ + jhls::JhlsTrackIndex, + stream::StreamSpec, + user::{PermissionSet, UserPermission}, + LocalTrack, Node, + }, + permission::PermissionSetExt, + CONF, }; use std::sync::Arc; use tokio::io::{AsyncWriteExt, DuplexStream}; diff --git a/stream/src/lib.rs b/stream/src/lib.rs index 2055440..ca7578d 100644 --- a/stream/src/lib.rs +++ b/stream/src/lib.rs @@ -12,11 +12,14 @@ pub mod webvtt; use anyhow::{anyhow, bail, Context, Result}; use fragment::fragment_stream; use hls::{hls_master_stream, hls_variant_stream}; -use jellybase::{permission::PermissionSetExt, CONF}; -use jellycommon::{ - stream::{StreamFormat, StreamSpec}, - user::{PermissionSet, UserPermission}, - LocalTrack, Node, TrackSource, +use jellybase::{ + common::{ + stream::{StreamFormat, StreamSpec}, + user::{PermissionSet, UserPermission}, + LocalTrack, Node, TrackSource, + }, + permission::PermissionSetExt, + CONF, }; use jhls::jhls_index; use std::{io::SeekFrom, ops::Range, sync::Arc}; diff --git a/stream/src/webvtt.rs b/stream/src/webvtt.rs index 02a4181..f78ac2f 100644 --- a/stream/src/webvtt.rs +++ b/stream/src/webvtt.rs @@ -4,8 +4,11 @@ Copyright (C) 2025 metamuffin */ use anyhow::{anyhow, Context, Result}; -use jellybase::{cache::async_cache_memory, CONF}; -use jellycommon::{stream::StreamSpec, LocalTrack, Node}; +use jellybase::{ + cache::async_cache_memory, + common::{stream::StreamSpec, LocalTrack, Node}, + CONF, +}; use jellyremuxer::extract::extract_track; use jellytranscoder::subtitles::{parse_subtitles, write_webvtt}; use std::sync::Arc; diff --git a/transcoder/Cargo.toml b/transcoder/Cargo.toml index f1e5062..d0ddf9c 100644 --- a/transcoder/Cargo.toml +++ b/transcoder/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -jellycommon = { path = "../common" } jellybase = { path = "../base" } jellyremuxer = { path = "../remuxer" } log = { workspace = true } diff --git a/transcoder/src/fragment.rs b/transcoder/src/fragment.rs index 4b72eaf..8822fa2 100644 --- a/transcoder/src/fragment.rs +++ b/transcoder/src/fragment.rs @@ -5,8 +5,10 @@ */ use crate::LOCAL_VIDEO_TRANSCODING_TASKS; -use jellybase::cache::{async_cache_file, CachePath}; -use jellycommon::jhls::EncodingProfile; +use jellybase::{ + cache::{async_cache_file, CachePath}, + common::jhls::EncodingProfile, +}; use log::{debug, info}; use std::process::Stdio; use tokio::{ diff --git a/transcoder/src/subtitles.rs b/transcoder/src/subtitles.rs index d7e7b29..77b423d 100644 --- a/transcoder/src/subtitles.rs +++ b/transcoder/src/subtitles.rs @@ -4,7 +4,7 @@ Copyright (C) 2025 metamuffin */ use anyhow::{anyhow, bail, Context}; -use jellycommon::jhls::SubtitleCue; +use jellybase::common::jhls::SubtitleCue; use std::fmt::Write; pub fn parse_subtitles( -- cgit v1.2.3-70-g09d2