diff options
| -rw-r--r-- | Cargo.lock | 203 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | common/Cargo.toml | 1 | ||||
| -rw-r--r-- | common/src/helpers.rs | 91 | ||||
| -rw-r--r-- | common/src/impl.rs | 18 | ||||
| -rw-r--r-- | common/src/lib.rs | 232 | ||||
| -rw-r--r-- | common/src/routes.rs | 4 | ||||
| -rw-r--r-- | common/src/user.rs | 15 | ||||
| -rw-r--r-- | database/Cargo.toml | 2 | ||||
| -rw-r--r-- | database/src/lib.rs | 65 | ||||
| -rw-r--r-- | import/asset_token/src/lib.rs | 5 | ||||
| -rw-r--r-- | import/src/lib.rs | 54 | ||||
| -rw-r--r-- | logic/src/assets.rs | 2 | ||||
| -rw-r--r-- | logic/src/filter_sort.rs | 20 | ||||
| -rw-r--r-- | logic/src/home.rs | 6 | ||||
| -rw-r--r-- | server/src/compat/jellyfin/mod.rs | 2 | ||||
| -rw-r--r-- | ui/src/node_page.rs | 8 | ||||
| -rw-r--r-- | ui/src/props.rs | 18 |
18 files changed, 321 insertions, 426 deletions
@@ -148,22 +148,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -412,12 +412,6 @@ dependencies = [ [[package]] name = "bitstream-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" - -[[package]] -name = "bitstream-io" version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" @@ -483,12 +477,6 @@ dependencies = [ [[package]] name = "built" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" - -[[package]] -name = "built" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" @@ -519,15 +507,15 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.45" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ "find-msvc-tools", "jobserver", @@ -542,16 +530,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f4c707c6a209cbe82d10abd08e1ea8995e9ea937d2550646e02798948992be0" [[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec 1.15.1", - "target-lexicon", -] - -[[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -778,9 +756,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -924,7 +902,7 @@ checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" [[package]] name = "ebml" version = "0.1.0" -source = "git+https://codeberg.org/metamuffin/ebml-rs#d5b998e076331172adf2a6cfd4043f5219fc8143" +source = "git+https://codeberg.org/metamuffin/ebml-rs#b93e9c26f3b465cd747d28a7ade6f5617bcf3f44" dependencies = [ "ebml-derive", ] @@ -932,7 +910,7 @@ dependencies = [ [[package]] name = "ebml-derive" version = "0.1.0" -source = "git+https://codeberg.org/metamuffin/ebml-rs#d5b998e076331172adf2a6cfd4043f5219fc8143" +source = "git+https://codeberg.org/metamuffin/ebml-rs#b93e9c26f3b465cd747d28a7ade6f5617bcf3f44" dependencies = [ "darling", "quote", @@ -1099,9 +1077,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "flate2" @@ -1263,9 +1241,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1310,9 +1288,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.13.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +checksum = "f954a9e9159ec994f73a30a12b96a702dde78f5547bcb561174597924f7d4162" dependencies = [ "color_quant", "weezl", @@ -1516,9 +1494,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", @@ -1542,7 +1520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.3.1", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-util", "rustls", "rustls-pki-types", @@ -1554,9 +1532,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ "base64", "bytes", @@ -1565,7 +1543,7 @@ dependencies = [ "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.7.0", + "hyper 1.8.1", "ipnet", "libc", "percent-encoding", @@ -1719,9 +1697,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.8" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", @@ -1733,12 +1711,12 @@ dependencies = [ "num-traits", "png", "qoi", - "ravif 0.11.20", + "ravif", "rayon", "rgb", "tiff", - "zune-core", - "zune-jpeg", + "zune-core 0.5.0", + "zune-jpeg 0.5.5", ] [[package]] @@ -1902,7 +1880,6 @@ dependencies = [ name = "jellycommon" version = "0.1.0" dependencies = [ - "bincode", "blake3", "chrono", "hex", @@ -1915,11 +1892,11 @@ name = "jellydb" version = "0.1.0" dependencies = [ "anyhow", - "bincode", "jellycommon", "log", "redb", "serde", + "serde_json", "tantivy", ] @@ -2104,8 +2081,8 @@ dependencies = [ "libavif-image", "log", "matroska", - "rav1e 0.8.1", - "ravif 0.12.0", + "rav1e", + "ravif", "rayon", "rgb", "serde", @@ -2371,7 +2348,7 @@ dependencies = [ [[package]] name = "matroska" version = "0.1.0" -source = "git+https://codeberg.org/metamuffin/ebml-rs#d5b998e076331172adf2a6cfd4043f5219fc8143" +source = "git+https://codeberg.org/metamuffin/ebml-rs#b93e9c26f3b465cd747d28a7ade6f5617bcf3f44" dependencies = [ "ebml", "serde", @@ -3125,41 +3102,6 @@ dependencies = [ [[package]] name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io 2.6.0", - "built 0.7.7", - "cfg-if", - "interpolate_name", - "itertools 0.12.1", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", - "simd_helpers", - "system-deps", - "thiserror 1.0.69", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "rav1e" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" @@ -3170,8 +3112,8 @@ dependencies = [ "arrayvec", "av-scenechange", "av1-grain", - "bitstream-io 4.9.0", - "built 0.8.0", + "bitstream-io", + "built", "cc", "cfg-if", "interpolate_name", @@ -3197,21 +3139,6 @@ dependencies = [ [[package]] name = "ravif" -version = "0.11.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e 0.7.1", - "rayon", - "rgb", -] - -[[package]] -name = "ravif" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" @@ -3220,7 +3147,7 @@ dependencies = [ "imgref", "loop9", "quick-error", - "rav1e 0.8.1", + "rav1e", "rayon", "rgb", ] @@ -3341,7 +3268,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-rustls", "hyper-util", "js-sys", @@ -3875,19 +3802,6 @@ dependencies = [ ] [[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] name = "tantivy" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4034,12 +3948,6 @@ dependencies = [ ] [[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] name = "tempfile" version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4112,7 +4020,7 @@ dependencies = [ "half", "quick-error", "weezl", - "zune-jpeg", + "zune-jpeg 0.4.21", ] [[package]] @@ -4468,9 +4376,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unit-prefix" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "universal-hash" @@ -4572,12 +4480,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] -name = "version-compare" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" - -[[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4712,9 +4614,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009936b22a61d342859b5f0ea64681cbb35a358ab548e2a44a8cf0dac2d980b8" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wide" @@ -5212,6 +5114,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" + +[[package]] name = "zune-inflate" version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5226,5 +5134,14 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "zune-core", + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fb7703e32e9a07fb3f757360338b3a567a5054f21b5f52a666752e333d58e" +dependencies = [ + "zune-core 0.5.0", ] @@ -18,7 +18,6 @@ members = [ resolver = "3" [workspace.dependencies] -# rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "2cf38a5aa37fe046e46b03740835787f0396307b" } rocket = "0.5" rocket_ws = "0.1" diff --git a/common/Cargo.toml b/common/Cargo.toml index cbe940b..37e9c6c 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] serde = { version = "1.0.228", features = ["derive", "rc"] } -bincode = { version = "2.0.1", features = ["derive"] } chrono = { version = "0.4.42", features = ["serde"] } blake3 = "1.8.2" hex = "0.4.3" diff --git a/common/src/helpers.rs b/common/src/helpers.rs index 18b8e2b..44e9468 100644 --- a/common/src/helpers.rs +++ b/common/src/helpers.rs @@ -3,7 +3,9 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ -use std::ops::Deref; + +use crate::{CreditCategory, IdentifierType}; +use std::{fmt::Display, ops::Deref, str::FromStr}; #[derive(PartialEq)] pub struct SortAnyway<T>(pub T); @@ -29,3 +31,90 @@ impl<T> Deref for SortAnyway<T> { &self.0 } } + +impl Display for CreditCategory { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + CreditCategory::Cast => "cast", + CreditCategory::Writing => "writing", + CreditCategory::Directing => "directing", + CreditCategory::Art => "art", + CreditCategory::Sound => "sound", + CreditCategory::Camera => "camera", + CreditCategory::Lighting => "lighting", + CreditCategory::Crew => "crew", + CreditCategory::Editing => "editing", + CreditCategory::Production => "production", + CreditCategory::Vfx => "vfx", + CreditCategory::CostumeMakeup => "costume_makeup", + CreditCategory::CreatedBy => "created_by", + CreditCategory::Performance => "performance", + CreditCategory::Instrument => "instrument", + CreditCategory::Vocal => "vocal", + CreditCategory::Arranger => "arranger", + CreditCategory::Producer => "producer", + CreditCategory::Engineer => "engineer", + }) + } +} +impl FromStr for CreditCategory { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(match s { + "cast" => CreditCategory::Cast, + "writing" => CreditCategory::Writing, + "directing" => CreditCategory::Directing, + "art" => CreditCategory::Art, + "sound" => CreditCategory::Sound, + "camera" => CreditCategory::Camera, + "lighting" => CreditCategory::Lighting, + "crew" => CreditCategory::Crew, + "editing" => CreditCategory::Editing, + "production" => CreditCategory::Production, + "vfx" => CreditCategory::Vfx, + "costume_makeup" => CreditCategory::CostumeMakeup, + "created_by" => CreditCategory::CreatedBy, + "performance" => CreditCategory::Performance, + "instrument" => CreditCategory::Instrument, + "vocal" => CreditCategory::Vocal, + "arranger" => CreditCategory::Arranger, + "producer" => CreditCategory::Producer, + "engineer" => CreditCategory::Engineer, + _ => return Err(()), + }) + } +} +impl Display for IdentifierType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + IdentifierType::MusicbrainzRecording => "musicbrainz_recording", + IdentifierType::MusicbrainzArtist => "musicbrainz_artist", + IdentifierType::MusicbrainzRelease => "musicbrainz_release", + IdentifierType::MusicbrainzReleaseGroup => "musicbrainz_release_group", + IdentifierType::Isrc => "isrc", + IdentifierType::Trakt => "trakt", + IdentifierType::Imdb => "imdb", + IdentifierType::Tmdb => "tmdb", + IdentifierType::Tvdb => "tvdb", + IdentifierType::Omdb => "omdb", + }) + } +} +impl FromStr for IdentifierType { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(match s { + "musicbrainz_recording" => IdentifierType::MusicbrainzRecording, + "musicbrainz_artist" => IdentifierType::MusicbrainzArtist, + "musicbrainz_release" => IdentifierType::MusicbrainzRelease, + "musicbrainz_release_group" => IdentifierType::MusicbrainzReleaseGroup, + "isrc" => IdentifierType::Isrc, + "trakt" => IdentifierType::Trakt, + "imdb" => IdentifierType::Imdb, + "tmdb" => IdentifierType::Tmdb, + "tvdb" => IdentifierType::Tvdb, + "omdb" => IdentifierType::Omdb, + _ => return Err(()), + }) + } +} diff --git a/common/src/impl.rs b/common/src/impl.rs index d4c863e..ef1a874 100644 --- a/common/src/impl.rs +++ b/common/src/impl.rs @@ -4,7 +4,8 @@ Copyright (C) 2025 metamuffin <metamuffin.org> */ use crate::{ - Node, NodeID, NodeIDOrSlug, ObjectIds, SourceTrack, SourceTrackKind, TmdbKind, TraktKind, + IdentifierType, Identifiers, Node, NodeID, NodeIDOrSlug, SourceTrack, SourceTrackKind, + TmdbKind, TraktKind, }; use serde::{Deserialize, Serialize}; use std::{fmt::Display, str::FromStr}; @@ -86,24 +87,21 @@ impl Display for TraktKind { }) } } -impl Display for ObjectIds { +impl Display for Identifiers { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(id) = self.trakt { + if let Some(id) = self.0.get(&IdentifierType::Trakt) { f.write_fmt(format_args!("trakt={}", id))?; } - if let Some(_id) = &self.slug { - f.write_str(",slug")?; - } - if let Some(id) = self.tmdb { + if let Some(id) = &self.0.get(&IdentifierType::Tmdb) { f.write_fmt(format_args!(",tmdb={}", id))?; } - if let Some(_id) = &self.imdb { + if let Some(_id) = &self.0.get(&IdentifierType::Imdb) { f.write_str(",imdb")?; } - if let Some(_id) = &self.tvdb { + if let Some(_id) = &self.0.get(&IdentifierType::Tvdb) { f.write_str(",tvdb")?; } - if let Some(_id) = &self.omdb { + if let Some(_id) = &self.0.get(&IdentifierType::Omdb) { f.write_str(",omdb")?; } Ok(()) diff --git a/common/src/lib.rs b/common/src/lib.rs index 0cc9ab5..d09153e 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -15,7 +15,6 @@ pub use jellystream_types as stream; pub use chrono; -use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, BTreeSet}, @@ -46,7 +45,7 @@ macro_rules! url_enum { }; } -#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NodeID(pub [u8; 32]); pub enum NodeIDOrSlug { @@ -54,15 +53,11 @@ pub enum NodeIDOrSlug { Slug(String), } -#[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] pub struct Node { - #[serde(default)] pub slug: String, - #[serde(default)] pub parents: BTreeSet<NodeID>, pub kind: NodeKind, - pub poster: Option<Asset>, - pub backdrop: Option<Asset>, pub title: Option<String>, pub subtitle: Option<String>, pub tagline: Option<String>, @@ -70,94 +65,78 @@ pub struct Node { pub release_date: Option<i64>, // in unix millis pub index: Option<usize>, pub media: Option<MediaInfo>, - #[serde(default)] - pub ratings: BTreeMap<Rating, f64>, pub federated: Option<String>, - #[serde(default)] pub tags: BTreeSet<String>, - #[serde(default)] - pub people: BTreeMap<PeopleGroup, Vec<Appearance>>, - #[serde(default)] - pub external_ids: BTreeMap<String, String>, - #[serde(default)] + pub ratings: BTreeMap<RatingType, f64>, + pub pictures: BTreeMap<PictureSlot, Asset>, + pub credits: BTreeMap<CreditCategory, Vec<Appearance>>, + pub identifiers: Identifiers, pub visibility: Visibility, - #[serde(default)] pub storage_size: u64, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] +pub struct Identifiers(pub BTreeMap<IdentifierType, String>); + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(rename_all = "snake_case")] +pub enum PictureSlot { + Poster, + Cover, + Backdrop, + Headshot, +} + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(rename_all = "snake_case")] +pub enum IdentifierType { + MusicbrainzRecording, + MusicbrainzArtist, + MusicbrainzRelease, + MusicbrainzReleaseGroup, + Isrc, + Trakt, + Imdb, + Tmdb, + Tvdb, + Omdb, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct Asset(pub String); -#[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct Appearance { - #[serde(default)] pub jobs: Vec<String>, - #[serde(default)] pub characters: Vec<String>, - pub person: Person, -} - -#[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] -pub struct Person { - pub name: String, - pub headshot: Option<Asset>, - pub ids: ObjectIds, + pub node: NodeID, } -#[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] -pub struct ObjectIds { - pub trakt: Option<u64>, - pub slug: Option<String>, - pub imdb: Option<String>, - pub tmdb: Option<u64>, - pub omdb: Option<u64>, - pub tvdb: Option<u64>, +#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(rename_all = "snake_case")] +pub enum CreditCategory { + Cast, + Writing, + Directing, + Art, + Sound, + Camera, + Lighting, + Crew, + Editing, + Production, + Vfx, + CostumeMakeup, + CreatedBy, + Performance, + Instrument, + Vocal, + Arranger, + Producer, + Engineer, } -url_enum!( - #[derive( - Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, - )] - #[serde(rename_all = "snake_case")] - enum PeopleGroup { - Cast = "cast", - Writing = "writing", - Directing = "directing", - Art = "art", - Sound = "sound", - Camera = "camera", - Lighting = "lighting", - Crew = "crew", - Editing = "editing", - Production = "production", - Vfx = "vfx", - CostumeMakeup = "costume_makeup", - CreatedBy = "created_by", - // https://musicbrainz.org/relationships/artist-recording - // modelling after this, but its too many categories - Performance = "performance", - Instrument = "instrument", - Vocal = "vocal", - Arranger = "arranger", - Producer = "producer", - Engineer = "engineer", - } -); - -#[derive( - Debug, - Clone, - Copy, - Deserialize, - Serialize, - PartialEq, - Eq, - PartialOrd, - Ord, - Encode, - Decode, - Default, -)] +#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Default)] #[serde(rename_all = "snake_case")] pub enum Visibility { Hidden, @@ -166,39 +145,24 @@ pub enum Visibility { Visible, } -url_enum!( - #[derive( - Debug, - Clone, - Copy, - Deserialize, - Serialize, - PartialEq, - Eq, - Default, - Encode, - Decode, - PartialOrd, - Ord, - )] - #[serde(rename_all = "snake_case")] - enum NodeKind { - #[default] - Unknown = "unknown", - Movie = "movie", - Video = "video", - Music = "music", - ShortFormVideo = "short_form_video", - Collection = "collection", - Channel = "channel", - Show = "show", - Series = "series", - Season = "season", - Episode = "episode", - } -); +#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Default, PartialOrd, Ord)] +#[serde(rename_all = "snake_case")] +pub enum NodeKind { + #[default] + Unknown, + Movie, + Video, + Music, + ShortFormVideo, + Collection, + Channel, + Show, + Series, + Season, + Episode, +} -#[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum TrackSource { Local(Asset), @@ -207,13 +171,13 @@ pub enum TrackSource { pub type TrackID = usize; -#[derive(Debug, Clone, Deserialize, Serialize, Hash, Encode, Decode, PartialEq, Eq)] +#[derive(Debug, Clone, Deserialize, Serialize, Hash, PartialEq, Eq)] pub struct LocalTrack { pub path: PathBuf, pub track: TrackID, } -#[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct MediaInfo { pub duration: f64, // in seconds pub tracks: Vec<SourceTrack>, @@ -221,14 +185,14 @@ pub struct MediaInfo { pub chapters: Vec<Chapter>, } -#[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] pub struct Chapter { pub time_start: Option<f64>, pub time_end: Option<f64>, pub labels: Vec<(String, String)>, } -#[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct SourceTrack { pub source: TrackSource, pub kind: SourceTrackKind, @@ -239,32 +203,25 @@ pub struct SourceTrack { pub federated: Vec<String>, } -url_enum!( - #[derive( - Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode, - )] - #[serde(rename_all = "snake_case")] - enum Rating { - Imdb = "imdb", - Tmdb = "tmdb", - RottenTomatoes = "rotten_tomatoes", - Metacritic = "metacritic", - YoutubeViews = "youtube_views", - YoutubeLikes = "youtube_likes", - YoutubeFollowers = "youtube_followers", - Trakt = "trakt", - } -); +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(rename_all = "snake_case")] +pub enum RatingType { + Imdb, + Tmdb, + RottenTomatoes, + Metacritic, + YoutubeViews, + YoutubeLikes, + YoutubeFollowers, + Trakt, +} -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum SourceTrackKind { Video { width: u64, height: u64, - display_width: Option<u64>, - display_height: Option<u64>, - display_unit: u64, fps: Option<f64>, }, Audio { @@ -275,7 +232,8 @@ pub enum SourceTrackKind { Subtitle, } -#[derive(Debug, Serialize, Deserialize, Clone, Copy, Hash, PartialEq, Encode, Decode)] +// TODO move this somewhere else +#[derive(Debug, Serialize, Deserialize, Clone, Copy, Hash, PartialEq)] #[serde(rename_all = "snake_case")] pub enum TraktKind { Movie, diff --git a/common/src/routes.rs b/common/src/routes.rs index 3e8682b..f78c7f0 100644 --- a/common/src/routes.rs +++ b/common/src/routes.rs @@ -3,7 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ -use crate::{api::NodeFilterSort, user::ApiWatchedState, NodeID, PeopleGroup}; +use crate::{api::NodeFilterSort, user::ApiWatchedState, NodeID, CreditCategory}; pub fn u_home() -> String { "/home".to_owned() @@ -31,7 +31,7 @@ pub fn u_node_slug_watched(node: &str, state: ApiWatchedState) -> String { } pub fn u_node_slug_person_asset( node: &str, - group: PeopleGroup, + group: CreditCategory, index: usize, width: usize, ) -> String { diff --git a/common/src/user.rs b/common/src/user.rs index c6da166..481732b 100644 --- a/common/src/user.rs +++ b/common/src/user.rs @@ -3,7 +3,6 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ -use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; use std::{ collections::{HashMap, HashSet}, @@ -13,7 +12,7 @@ use std::{ use crate::url_enum; #[rustfmt::skip] -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct User { pub name: String, pub display_name: String, @@ -25,14 +24,14 @@ pub struct User { pub permissions: PermissionSet, } -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct NodeUserData { pub watched: WatchedState, #[serde(default)] pub rating: i32, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum WatchedState { None, @@ -60,7 +59,7 @@ pub struct CreateSessionParams { } url_enum!( - #[derive(Debug, Clone, Copy, Serialize, Default, Deserialize, PartialEq, Encode, Decode)] + #[derive(Debug, Clone, Copy, Serialize, Default, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] enum Theme { #[default] @@ -72,7 +71,7 @@ url_enum!( ); url_enum!( - #[derive(Debug, Clone, Copy, Serialize, Default, Deserialize, PartialEq, Encode, Decode)] + #[derive(Debug, Clone, Copy, Serialize, Default, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] enum PlayerKind { #[default] @@ -82,10 +81,10 @@ url_enum!( } ); -#[derive(Debug, Clone, Serialize, Deserialize, Default, Encode, Decode)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct PermissionSet(pub HashMap<UserPermission, bool>); -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Encode, Decode)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum UserPermission { Admin, diff --git a/database/Cargo.toml b/database/Cargo.toml index 2cf9909..c5bfc9d 100644 --- a/database/Cargo.toml +++ b/database/Cargo.toml @@ -8,7 +8,7 @@ tantivy = "0.25.0" jellycommon = { path = "../common" } serde = { version = "1.0.228", features = ["derive"] } log = { workspace = true } -bincode = "2.0.1" +serde_json = "1.0.145" redb = "3.1.0" anyhow = "1.0.100" diff --git a/database/src/lib.rs b/database/src/lib.rs index 8e47298..fe43ad4 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -6,7 +6,6 @@ pub mod search; use anyhow::{Context, Result, anyhow, bail}; -use bincode::{Decode, Encode, config::standard}; use jellycommon::{ Node, NodeID, user::{NodeUserData, User}, @@ -14,6 +13,8 @@ use jellycommon::{ use log::info; use redb::{Durability, ReadableDatabase, ReadableTable, StorageError, TableDefinition}; use search::NodeTextSearchIndex; +#[cfg(not(feature = "db_json"))] +use serde::{Serialize, de::DeserializeOwned}; use std::{ fs::create_dir_all, hash::{DefaultHasher, Hasher}, @@ -185,21 +186,19 @@ impl Database { let mut t_tag_node = txn.open_table(T_TAG_NODE)?; let mut node = t_node.get(id.0)?.map(|v| v.value().0).unwrap_or_default(); - let mut dh_before = HashWriter(DefaultHasher::new()); - bincode::encode_into_writer(&node, &mut dh_before, standard()).unwrap(); + let dh_before = serde_json::to_vec(&node).unwrap(); update(&mut node)?; - let mut dh_after = HashWriter(DefaultHasher::new()); - bincode::encode_into_writer(&node, &mut dh_after, standard()).unwrap(); + let dh_after = serde_json::to_vec(&node).unwrap(); - if dh_before.0.finish() == dh_after.0.finish() { + if dh_before == dh_after { return Ok(()); } for parent in &node.parents { t_node_children.insert((parent.0, id.0), ())?; } - for (pl, eid) in &node.external_ids { - t_node_external_id.insert((pl.as_str(), eid.as_str()), id.0)?; + for (pl, eid) in &node.identifiers.0 { + t_node_external_id.insert((pl.to_string().as_str(), eid.as_str()), id.0)?; } for tag in &node.tags { t_tag_node.insert((tag.as_str(), id.0), ())?; @@ -468,59 +467,11 @@ impl Database { } } -pub struct HashWriter(DefaultHasher); -impl bincode::enc::write::Writer for HashWriter { - fn write(&mut self, bytes: &[u8]) -> std::result::Result<(), bincode::error::EncodeError> { - self.0.write(bytes); - Ok(()) - } -} - #[derive(Debug)] #[cfg(not(feature = "db_json"))] pub struct Ser<T>(pub T); #[cfg(not(feature = "db_json"))] -impl<T: Encode + Decode<()> + std::fmt::Debug> redb::Value for Ser<T> { - type SelfType<'a> - = Ser<T> - where - Self: 'a; - type AsBytes<'a> - = Vec<u8> - where - Self: 'a; - - fn fixed_width() -> Option<usize> { - None - } - - fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a> - where - Self: 'a, - { - Ser(bincode::decode_from_slice(data, bincode::config::legacy()) - .unwrap() - .0) - } - - fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a> - where - Self: 'a, - Self: 'b, - { - bincode::encode_to_vec(&value.0, bincode::config::legacy()).unwrap() - } - - fn type_name() -> redb::TypeName { - redb::TypeName::new("bincode") - } -} - -#[derive(Debug)] -#[cfg(feature = "db_json")] -pub struct Ser<T>(pub T); -#[cfg(feature = "db_json")] -impl<T: Serialize + for<'a> Deserialize<'a> + std::fmt::Debug> redb::Value for Ser<T> { +impl<T: DeserializeOwned + Serialize + std::fmt::Debug> redb::Value for Ser<T> { type SelfType<'a> = Ser<T> where diff --git a/import/asset_token/src/lib.rs b/import/asset_token/src/lib.rs index 0a120f0..ef1850e 100644 --- a/import/asset_token/src/lib.rs +++ b/import/asset_token/src/lib.rs @@ -6,7 +6,6 @@ use aes_gcm_siv::{aead::Aead, Aes256GcmSiv, KeyInit}; use anyhow::{anyhow, bail, Context}; use base64::Engine; -use bincode::{Decode, Encode}; use jellycache::CachePath; pub use jellycommon as common; use jellycommon::{Asset, LocalTrack}; @@ -46,10 +45,10 @@ static ASSET_KEY: LazyLock<Aes256GcmSiv> = LazyLock::new(|| { } }); -#[derive(Debug, Encode, Decode, Serialize, PartialEq, Eq)] +#[derive(Debug, Serialize, PartialEq, Eq)] pub enum AssetInner { Federated { host: String, asset: Vec<u8> }, - Cache(#[bincode(with_serde)] CachePath), + Cache(CachePath), Assets(PathBuf), Media(PathBuf), LocalTrack(LocalTrack), diff --git a/import/src/lib.rs b/import/src/lib.rs index 1fd8bc7..1a1d5ad 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -24,7 +24,7 @@ use infojson::YVideo; use jellycache::{cache_file, cache_memory}; use jellycommon::{ Appearance, Chapter, LocalTrack, MediaInfo, Node, NodeID, NodeKind, ObjectIds, PeopleGroup, - Person, Rating, SourceTrack, SourceTrackKind, TmdbKind, TrackSource, TraktKind, Visibility, + Person, RatingType, SourceTrack, SourceTrackKind, TmdbKind, TrackSource, TraktKind, Visibility, }; use jellyimport_fallback_generator::generate_fallback; use jellyremuxer::{ @@ -291,7 +291,7 @@ fn import_file( 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); + node.identifiers.extend(data.identifiers); Ok(()) })?; @@ -323,10 +323,10 @@ fn import_file( node.kind = NodeKind::Channel; node.title = Some(clean_uploader_name(&data.title).to_owned()); if let Some(cid) = data.channel_id { - node.external_ids.insert("youtube.channel".to_string(), cid); + node.identifiers.insert("youtube.channel".to_string(), cid); } if let Some(uid) = data.uploader_id { - node.external_ids + node.identifiers .insert("youtube.channelname".to_string(), uid); } if let Some(desc) = data.description { @@ -334,7 +334,7 @@ fn import_file( } if let Some(followers) = data.channel_follower_count { node.ratings - .insert(Rating::YoutubeFollowers, followers as f64); + .insert(RatingType::YoutubeFollowers, followers as f64); } Ok(()) })?; @@ -401,7 +401,8 @@ fn import_media_file( .transpose()?; let mut tags = m - .tags.first() + .tags + .first() .map(|tags| { tags.tags .iter() @@ -508,7 +509,7 @@ fn import_media_file( node.tagline = tags.remove("COMMENT").or(node.tagline.clone()); node.parents.insert(parent); - node.external_ids.extend(eids); + node.identifiers.extend(eids); if let Some(ct) = tags.get("CONTENT_TYPE") { node.kind = match ct.to_lowercase().trim() { @@ -533,9 +534,6 @@ fn import_media_file( SourceTrackKind::Video { width: video.pixel_width, height: video.pixel_height, - display_width: video.display_width, - display_height: video.display_height, - display_unit: video.display_unit, fps: video.frame_rate, } } else if let Some(audio) = &track.audio { @@ -594,20 +592,17 @@ fn import_media_file( } match infojson.extractor.as_str() { "youtube" => { - node.external_ids + node.identifiers .insert("youtube.video".to_string(), infojson.id); node.ratings.insert( - Rating::YoutubeViews, + RatingType::YoutubeViews, infojson.view_count.unwrap_or_default() as f64, ); if let Some(lc) = infojson.like_count { - node.ratings.insert(Rating::YoutubeLikes, lc as f64); + node.ratings.insert(RatingType::YoutubeLikes, lc as f64); } } - "Bandcamp" => drop( - node.external_ids - .insert("bandcamp".to_string(), infojson.id), - ), + "Bandcamp" => drop(node.identifiers.insert("bandcamp".to_string(), infojson.id)), _ => (), } } @@ -686,7 +681,7 @@ fn import_media_file( node.title = Some(episode.title.clone()); node.poster = poster.or(node.poster.clone()); node.description = episode.overview.clone().or(node.description.clone()); - node.ratings.insert(Rating::Trakt, episode.rating); + node.ratings.insert(RatingType::Trakt, episode.rating); Ok(()) })? } @@ -770,11 +765,11 @@ fn apply_musicbrainz_recording( db.update_node_init(node, |node| { node.title = Some(rec.title.clone()); - node.external_ids + node.identifiers .insert("musicbrainz.recording".to_string(), rec.id.to_string()); if let Some(a) = rec.artist_credit.first() { node.subtitle = Some(a.artist.name.clone()); - node.external_ids + node.identifiers .insert("musicbrainz.artist".to_string(), a.artist.id.to_string()); } @@ -850,24 +845,15 @@ fn apply_musicbrainz_recording( .ser(), }; - node.people.entry(group).or_default().push(Appearance { + node.credits.entry(group).or_default().push(Appearance { jobs, characters: vec![], - person: Person { - name: if rel.target_credit.is_empty() { - artist.name.clone() - } else { - rel.target_credit.clone() - }, - headshot: Some(headshot), - ids: ObjectIds::default(), - }, }); } } for isrc in &rec.isrcs { - node.external_ids + node.identifiers .insert("isrc".to_string(), isrc.to_string()); } Ok(()) @@ -944,7 +930,7 @@ fn apply_trakt_tmdb( db.update_node_init(node, |node| { node.title = Some(data.title.clone()); - node.people.extend(people_map); + node.credits.extend(people_map); node.kind = match trakt_kind { TraktKind::Movie => NodeKind::Movie, TraktKind::Show => NodeKind::Show, @@ -960,7 +946,7 @@ fn apply_trakt_tmdb( node.tagline = Some(tagline.clone()) } if let Some(rating) = &data.rating { - node.ratings.insert(Rating::Trakt, *rating); + node.ratings.insert(RatingType::Trakt, *rating); } if let Some(poster) = poster { node.poster = Some(poster); @@ -972,7 +958,7 @@ fn apply_trakt_tmdb( node.title = data.title.clone().or(node.title.clone()); node.tagline = data.tagline.clone().or(node.tagline.clone()); node.description = Some(data.overview.clone()); - node.ratings.insert(Rating::Tmdb, data.vote_average); + node.ratings.insert(RatingType::Tmdb, data.vote_average); if let Some(date) = data.release_date.clone() { if let Ok(date) = tmdb::parse_release_date(&date) { node.release_date = date; diff --git a/logic/src/assets.rs b/logic/src/assets.rs index c6d6a11..02d0c2e 100644 --- a/logic/src/assets.rs +++ b/logic/src/assets.rs @@ -58,7 +58,7 @@ pub fn get_node_person_asset( .get_node(id)? .ok_or(anyhow!("node does not exist"))?; let app = node - .people + .credits .get(&group) .ok_or(anyhow!("group has no members"))? .get(index) diff --git a/logic/src/filter_sort.rs b/logic/src/filter_sort.rs index 3ccbc0d..d3244af 100644 --- a/logic/src/filter_sort.rs +++ b/logic/src/filter_sort.rs @@ -4,7 +4,7 @@ Copyright (C) 2025 metamuffin <metamuffin.org> */ use jellycommon::{ - Node, NodeKind, Rating, + Node, NodeKind, RatingType, api::{FilterProperty, NodeFilterSort, SortOrder, SortProperty}, helpers::SortAnyway, user::NodeUserData, @@ -65,28 +65,28 @@ pub fn filter_and_sort_nodes( .cmp(&b.index.unwrap_or(usize::MAX)) }), SortProperty::RatingRottenTomatoes => nodes.sort_by_cached_key(|(n, _)| { - SortAnyway(*n.ratings.get(&Rating::RottenTomatoes).unwrap_or(&0.)) + SortAnyway(*n.ratings.get(&RatingType::RottenTomatoes).unwrap_or(&0.)) }), SortProperty::RatingMetacritic => nodes.sort_by_cached_key(|(n, _)| { - SortAnyway(*n.ratings.get(&Rating::Metacritic).unwrap_or(&0.)) + SortAnyway(*n.ratings.get(&RatingType::Metacritic).unwrap_or(&0.)) }), SortProperty::RatingImdb => nodes - .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&Rating::Imdb).unwrap_or(&0.))), + .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&RatingType::Imdb).unwrap_or(&0.))), SortProperty::RatingTmdb => nodes - .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&Rating::Tmdb).unwrap_or(&0.))), + .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&RatingType::Tmdb).unwrap_or(&0.))), SortProperty::RatingYoutubeViews => nodes.sort_by_cached_key(|(n, _)| { - SortAnyway(*n.ratings.get(&Rating::YoutubeViews).unwrap_or(&0.)) + SortAnyway(*n.ratings.get(&RatingType::YoutubeViews).unwrap_or(&0.)) }), SortProperty::RatingYoutubeLikes => nodes.sort_by_cached_key(|(n, _)| { - SortAnyway(*n.ratings.get(&Rating::YoutubeLikes).unwrap_or(&0.)) + SortAnyway(*n.ratings.get(&RatingType::YoutubeLikes).unwrap_or(&0.)) }), SortProperty::RatingYoutubeFollowers => nodes.sort_by_cached_key(|(n, _)| { - SortAnyway(*n.ratings.get(&Rating::YoutubeFollowers).unwrap_or(&0.)) + SortAnyway(*n.ratings.get(&RatingType::YoutubeFollowers).unwrap_or(&0.)) }), SortProperty::RatingLikesDivViews => nodes.sort_by_cached_key(|(n, _)| { SortAnyway( - *n.ratings.get(&Rating::YoutubeLikes).unwrap_or(&0.) - / (1. + *n.ratings.get(&Rating::YoutubeViews).unwrap_or(&0.)), + *n.ratings.get(&RatingType::YoutubeLikes).unwrap_or(&0.) + / (1. + *n.ratings.get(&RatingType::YoutubeViews).unwrap_or(&0.)), ) }), SortProperty::RatingUser => nodes.sort_by_cached_key(|(_, u)| u.rating), diff --git a/logic/src/home.rs b/logic/src/home.rs index ff85ba1..db8a397 100644 --- a/logic/src/home.rs +++ b/logic/src/home.rs @@ -7,7 +7,7 @@ use crate::{DATABASE, node::DatabaseNodeUserDataExt, session::Session}; use anyhow::{Context, Result}; use jellycommon::{ - NodeID, NodeKind, Rating, Visibility, + NodeID, NodeKind, RatingType, Visibility, api::ApiHomeResponse, chrono::{Datelike, Utc}, user::WatchedState, @@ -77,7 +77,7 @@ pub fn home(session: &Session) -> Result<ApiHomeResponse> { items.sort_by_key(|(n, _)| { n.ratings - .get(&Rating::Tmdb) + .get(&RatingType::Tmdb) .map(|x| (*x * -1000.) as i32) .unwrap_or(0) }); @@ -87,7 +87,7 @@ pub fn home(session: &Session) -> Result<ApiHomeResponse> { items .iter() .take(16) - .filter(|(n, _)| n.ratings.contains_key(&Rating::Tmdb)) + .filter(|(n, _)| n.ratings.contains_key(&RatingType::Tmdb)) .cloned() .collect(), )); diff --git a/server/src/compat/jellyfin/mod.rs b/server/src/compat/jellyfin/mod.rs index be9278e..3f04705 100644 --- a/server/src/compat/jellyfin/mod.rs +++ b/server/src/compat/jellyfin/mod.rs @@ -735,7 +735,7 @@ fn item_object(node: &Node, userdata: &NodeUserData) -> JellyfinItem { _ => JellyfinItemType::CollectionFolder, }, people: node - .people + .credits .iter() .flat_map(|(_pg, ps)| { ps.iter().map(|p| JellyfinPerson { diff --git a/ui/src/node_page.rs b/ui/src/node_page.rs index 39b66df..1e029ae 100644 --- a/ui/src/node_page.rs +++ b/ui/src/node_page.rs @@ -116,9 +116,9 @@ markup::define! { }} }} } - @if !node.people.is_empty() { + @if !node.credits.is_empty() { h2 { @trs(lang, "node.people") } - @for (group, people) in &node.people { + @for (group, people) in &node.credits { details[open=group==&PeopleGroup::Cast] { summary { h3 { @format!("{}", group) } } ul.children.hlist { @for (i, pe) in people.iter().enumerate() { @@ -149,11 +149,11 @@ markup::define! { }} } } - @if !node.external_ids.is_empty() { + @if !node.identifiers.is_empty() { details { summary { @trs(lang, "node.external_ids") } table { - @for (key, value) in &node.external_ids { tr { + @for (key, value) in &node.identifiers { tr { tr { td { @trs(lang, &format!("eid.{}", key)) } @if let Some(url) = external_id_url(key, value) { diff --git a/ui/src/props.rs b/ui/src/props.rs index fbeddca..64713ea 100644 --- a/ui/src/props.rs +++ b/ui/src/props.rs @@ -8,7 +8,7 @@ use crate::{ locale::{Language, tr, trs}, }; use jellycommon::{ - Node, Rating, Visibility, + Node, RatingType, Visibility, chrono::DateTime, user::{NodeUserData, WatchedState}, }; @@ -38,14 +38,14 @@ markup::define! { // } @for (kind, value) in &node.ratings { @match kind { - Rating::YoutubeLikes => {p.likes{ @format_count(*value as usize) " Likes" }} - Rating::YoutubeViews => {p{ @format_count(*value as usize) " Views" }} - Rating::YoutubeFollowers => {p{ @format_count(*value as usize) " Subscribers" }} - Rating::RottenTomatoes => {p.rating{ @value " Tomatoes" }} - Rating::Metacritic if *full => {p{ "Metacritic Score: " @value }} - Rating::Imdb => {p.rating{ "IMDb " @value }} - Rating::Tmdb => {p.rating{ "TMDB " @value }} - Rating::Trakt if *full => {p.rating{ "Trakt " @value }} + RatingType::YoutubeLikes => {p.likes{ @format_count(*value as usize) " Likes" }} + RatingType::YoutubeViews => {p{ @format_count(*value as usize) " Views" }} + RatingType::YoutubeFollowers => {p{ @format_count(*value as usize) " Subscribers" }} + RatingType::RottenTomatoes => {p.rating{ @value " Tomatoes" }} + RatingType::Metacritic if *full => {p{ "Metacritic Score: " @value }} + RatingType::Imdb => {p.rating{ "IMDb " @value }} + RatingType::Tmdb => {p.rating{ "TMDB " @value }} + RatingType::Trakt if *full => {p.rating{ "Trakt " @value }} _ => {} } } |