feat: Update the api crate

This commit is contained in:
uttarayan21
2025-11-25 18:48:13 +05:30
parent 77fe7b6bb4
commit ca1fd2e977
9 changed files with 229 additions and 260 deletions

152
Cargo.lock generated
View File

@@ -1009,9 +1009,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.46"
version = "1.2.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36"
checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -1125,9 +1125,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.52"
version = "4.5.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8"
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1135,9 +1135,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.52"
version = "4.5.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1"
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
dependencies = [
"anstream",
"anstyle",
@@ -1147,9 +1147,9 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.5.60"
version = "4.5.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971"
checksum = "39615915e2ece2550c0149addac32fb5bd312c657f43845bb9088cb9c8a7c992"
dependencies = [
"clap",
]
@@ -2457,15 +2457,15 @@ dependencies = [
[[package]]
name = "gio-sys"
version = "0.20.10"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521e93a7e56fc89e84aea9a52cfc9436816a4b363b030260b699950ff1336c83"
checksum = "171ed2f6dd927abbe108cfd9eebff2052c335013f5879d55bab0dc1dee19b706"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -2487,9 +2487,9 @@ checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
[[package]]
name = "glib"
version = "0.20.12"
version = "0.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffc4b6e352d4716d84d7dde562dd9aee2a7d48beb872dd9ece7f2d1515b2d683"
checksum = "5b9dbecb1c33e483a98be4acfea2ab369e1c28f517c6eadb674537409c25c4b2"
dependencies = [
"bitflags 2.10.0",
"futures-channel",
@@ -2508,9 +2508,9 @@ dependencies = [
[[package]]
name = "glib-macros"
version = "0.20.12"
version = "0.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8084af62f09475a3f529b1629c10c429d7600ee1398ae12dd3bf175d74e7145"
checksum = "880e524e0085f3546cfb38532b2c202c0d64741d9977a6e4aa24704bfc9f19fb"
dependencies = [
"heck 0.5.0",
"proc-macro-crate",
@@ -2521,9 +2521,9 @@ dependencies = [
[[package]]
name = "glib-sys"
version = "0.20.10"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ab79e1ed126803a8fb827e3de0e2ff95191912b8db65cee467edb56fc4cc215"
checksum = "d09d3d0fddf7239521674e57b0465dfbd844632fec54f059f7f56112e3f927e1"
dependencies = [
"libc",
"system-deps",
@@ -2583,9 +2583,9 @@ dependencies = [
[[package]]
name = "gobject-sys"
version = "0.20.10"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec9aca94bb73989e3cfdbf8f2e0f1f6da04db4d291c431f444838925c4c63eda"
checksum = "538e41d8776173ec107e7b0f2aceced60abc368d7e1d81c1f0e2ecd35f59080d"
dependencies = [
"glib-sys",
"libc",
@@ -2916,9 +2916,9 @@ checksum = "12101ecc8225ea6d675bc70263074eab6169079621c2186fe0c66590b2df9681"
[[package]]
name = "gstreamer"
version = "0.23.7"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8757a87f3706560037a01a9f06a59fcc7bdb0864744dcf73546606e60c4316e1"
checksum = "69ac2f12970a2f85a681d2ceaa40c32fe86cc202ead315e0dfa2223a1217cd24"
dependencies = [
"cfg-if",
"futures-channel",
@@ -2927,13 +2927,13 @@ dependencies = [
"glib",
"gstreamer-sys",
"itertools 0.14.0",
"kstring",
"libc",
"muldiv",
"num-integer",
"num-rational",
"once_cell",
"option-operations",
"paste",
"pastey",
"pin-project-lite",
"smallvec",
"thiserror 2.0.17",
@@ -2941,9 +2941,9 @@ dependencies = [
[[package]]
name = "gstreamer-app"
version = "0.23.5"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9a883eb21aebcf1289158225c05f7aea5da6ecf71fa7f0ff1ce4d25baf004e"
checksum = "0af5d403738faf03494dfd502d223444b4b44feb997ba28ab3f118ee6d40a0b2"
dependencies = [
"futures-core",
"futures-sink",
@@ -2956,9 +2956,9 @@ dependencies = [
[[package]]
name = "gstreamer-app-sys"
version = "0.23.5"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f7ef838306fe51852d503a14dc79ac42de005a59008a05098de3ecdaf05455"
checksum = "aaf1a3af017f9493c34ccc8439cbce5c48f6ddff6ec0514c23996b374ff25f9a"
dependencies = [
"glib-sys",
"gstreamer-base-sys",
@@ -2969,9 +2969,9 @@ dependencies = [
[[package]]
name = "gstreamer-base"
version = "0.23.6"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f19a74fd04ffdcb847dd322640f2cf520897129d00a7bcb92fd62a63f3e27404"
checksum = "71ff9b0bbc8041f0c6c8a53b206a6542f86c7d9fa8a7dff3f27d9c374d9f39b4"
dependencies = [
"atomic_refcell",
"cfg-if",
@@ -2983,9 +2983,9 @@ dependencies = [
[[package]]
name = "gstreamer-base-sys"
version = "0.23.6"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f2fb0037b6d3c5b51f60dea11e667910f33be222308ca5a101450018a09840"
checksum = "fed78852b92db1459b8f4288f86e6530274073c20be2f94ba642cddaca08b00e"
dependencies = [
"glib-sys",
"gobject-sys",
@@ -2996,10 +2996,11 @@ dependencies = [
[[package]]
name = "gstreamer-sys"
version = "0.23.6"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feea73b4d92dbf9c24a203c9cd0bcc740d584f6b5960d5faf359febf288919b2"
checksum = "a24ae2930e683665832a19ef02466094b09d1f2da5673f001515ed5486aa9377"
dependencies = [
"cfg-if",
"glib-sys",
"gobject-sys",
"libc",
@@ -3071,9 +3072,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.16.0"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"foldhash 0.2.0",
]
@@ -3276,7 +3277,7 @@ dependencies = [
[[package]]
name = "iced"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_core",
"iced_debug",
@@ -3293,7 +3294,7 @@ dependencies = [
[[package]]
name = "iced_beacon"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bincode",
"futures",
@@ -3308,7 +3309,7 @@ dependencies = [
[[package]]
name = "iced_core"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bitflags 2.10.0",
"bytes",
@@ -3326,7 +3327,7 @@ dependencies = [
[[package]]
name = "iced_debug"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_beacon",
"iced_core",
@@ -3337,7 +3338,7 @@ dependencies = [
[[package]]
name = "iced_devtools"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_debug",
"iced_program",
@@ -3348,7 +3349,7 @@ dependencies = [
[[package]]
name = "iced_futures"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"futures",
"iced_core",
@@ -3362,7 +3363,7 @@ dependencies = [
[[package]]
name = "iced_graphics"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bitflags 2.10.0",
"bytemuck",
@@ -3383,7 +3384,7 @@ dependencies = [
[[package]]
name = "iced_program"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_graphics",
"iced_runtime",
@@ -3392,7 +3393,7 @@ dependencies = [
[[package]]
name = "iced_renderer"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_graphics",
"iced_tiny_skia",
@@ -3404,7 +3405,7 @@ dependencies = [
[[package]]
name = "iced_runtime"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bytes",
"iced_core",
@@ -3417,7 +3418,7 @@ dependencies = [
[[package]]
name = "iced_tiny_skia"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bytemuck",
"cosmic-text 0.15.0",
@@ -3441,14 +3442,14 @@ dependencies = [
"iced",
"iced_wgpu",
"log",
"thiserror 1.0.69",
"thiserror 2.0.17",
"url",
]
[[package]]
name = "iced_wgpu"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"bitflags 2.10.0",
"bytemuck",
@@ -3468,7 +3469,7 @@ dependencies = [
[[package]]
name = "iced_widget"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_renderer",
"log",
@@ -3481,7 +3482,7 @@ dependencies = [
[[package]]
name = "iced_winit"
version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced#645643bfd63ed4c01aa281f97992e3c276e71498"
source = "git+https://github.com/iced-rs/iced#8bfd099c5929d927a3fdde666d4c645d0bd83cb7"
dependencies = [
"iced_debug",
"iced_program",
@@ -3646,12 +3647,12 @@ checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8"
[[package]]
name = "indexmap"
version = "2.12.0"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
dependencies = [
"equivalent",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
"serde",
"serde_core",
]
@@ -3930,6 +3931,15 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kstring"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"
dependencies = [
"static_assertions",
]
[[package]]
name = "kurbo"
version = "0.10.4"
@@ -4402,7 +4412,7 @@ dependencies = [
"cfg_aliases",
"codespan-reporting",
"half",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
"hexf-parse",
"indexmap",
"libm",
@@ -5174,11 +5184,11 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "option-operations"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0"
checksum = "b31ce827892359f23d3cd1cc4c75a6c241772bbd2db17a92dcf27cbefdf52689"
dependencies = [
"paste",
"pastey",
]
[[package]]
@@ -7789,9 +7799,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "value-bag"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
dependencies = [
"value-bag-serde1",
"value-bag-sval2",
@@ -7799,20 +7809,20 @@ dependencies = [
[[package]]
name = "value-bag-serde1"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35540706617d373b118d550d41f5dfe0b78a0c195dc13c6815e92e2638432306"
checksum = "16530907bfe2999a1773ca5900a65101e092c70f642f25cc23ca0c43573262c5"
dependencies = [
"erased-serde",
"serde",
"serde_core",
"serde_fmt",
]
[[package]]
name = "value-bag-sval2"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fe7e140a2658cc16f7ee7a86e413e803fc8f9b5127adc8755c19f9fefa63a52"
checksum = "d00ae130edd690eaa877e4f40605d534790d1cf1d651e7685bd6a144521b251f"
dependencies = [
"sval",
"sval_buffer",
@@ -8183,7 +8193,7 @@ dependencies = [
"cfg-if",
"cfg_aliases",
"document-features",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
"js-sys",
"log",
"naga 27.0.3",
@@ -8214,7 +8224,7 @@ dependencies = [
"bytemuck",
"cfg_aliases",
"document-features",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
"indexmap",
"log",
"naga 27.0.3",
@@ -8281,7 +8291,7 @@ dependencies = [
"gpu-alloc",
"gpu-allocator",
"gpu-descriptor",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
"js-sys",
"khronos-egl",
"libc",
@@ -9373,18 +9383,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
[[package]]
name = "zerocopy"
version = "0.8.27"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -4,7 +4,7 @@ pub async fn main() {
let config = std::fs::read_to_string("config.toml").expect("Config.toml");
let config: JellyfinConfig = toml::from_str(&config).expect("Failed to parse config.toml");
let mut jellyfin = JellyfinClient::new(config);
let mut jellyfin = JellyfinClient::new_with_config(config);
jellyfin
.authenticate_with_cached_token(".session")
.await

View File

@@ -566,7 +566,7 @@ pub struct BaseItemDto {
#[serde(rename = "SeriesThumbImageTag")]
pub series_thumb_image_tag: Option<String>,
/** Gets or sets the blurhashes for the image tags.
Maps image type to dictionary mapping image tag to blurhash value.*/
Maps image type to dictionary mapping image tag to blurhash value.*/
#[serde(rename = "ImageBlurHashes")]
pub image_blur_hashes: BaseItemDtoImageBlurHashes,
/// Gets or sets the series studio.
@@ -590,10 +590,7 @@ Maps image type to dictionary mapping image tag to blurhash value.*/
/// Gets or sets the trickplay manifest.
#[serde(rename = "Trickplay")]
pub trickplay: Option<
std::collections::HashMap<
String,
Option<std::collections::HashMap<String, TrickplayInfo>>,
>,
std::collections::HashMap<String, Option<std::collections::HashMap<String, TrickplayInfo>>>,
>,
/// Gets or sets the type of the location.
#[serde(rename = "LocationType")]
@@ -1525,9 +1522,7 @@ pub struct EncodingOptions {
pub hardware_decoding_codecs: Option<Vec<String>>,
/// Gets or sets the file extensions on-demand metadata based keyframe extraction is enabled for.
#[serde(rename = "AllowOnDemandMetadataBasedKeyframeExtractionForExtensions")]
pub allow_on_demand_metadata_based_keyframe_extraction_for_extensions: Option<
Vec<String>,
>,
pub allow_on_demand_metadata_based_keyframe_extraction_for_extensions: Option<Vec<String>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct EndPointInfo {
@@ -1546,9 +1541,9 @@ pub struct ExternalIdInfo {
#[serde(rename = "Key")]
pub key: String,
/** Gets or sets the specific media type for this id. This is used to distinguish between the different
external id types for providers with multiple ids.
A null value indicates there is no specific media type associated with the external id, or this is the
default id for the external provider so there is no need to specify a type.*/
external id types for providers with multiple ids.
A null value indicates there is no specific media type associated with the external id, or this is the
default id for the external provider so there is no need to specify a type.*/
#[serde(rename = "Type")]
pub _type: Option<ExternalIdMediaType>,
/// Gets or sets the URL format string.
@@ -2444,7 +2439,7 @@ pub struct MediaSourceInfo {
#[serde(rename = "Name")]
pub name: Option<String>,
/** Gets or sets a value indicating whether the media is remote.
Differentiate internet url vs local network.*/
Differentiate internet url vs local network.*/
#[serde(rename = "IsRemote")]
pub is_remote: bool,
#[serde(rename = "ETag")]
@@ -2506,7 +2501,7 @@ Differentiate internet url vs local network.*/
#[serde(rename = "TranscodingUrl")]
pub transcoding_url: Option<String>,
/** Media streaming protocol.
Lowercase for backwards compatibility.*/
Lowercase for backwards compatibility.*/
#[serde(rename = "TranscodingSubProtocol")]
pub transcoding_sub_protocol: MediaStreamProtocol,
#[serde(rename = "TranscodingContainer")]
@@ -2657,8 +2652,8 @@ pub struct MediaStream {
#[serde(rename = "RealFrameRate")]
pub real_frame_rate: Option<f32>,
/** Gets the framerate used as reference.
Prefer AverageFrameRate, if that is null or an unrealistic value
then fallback to RealFrameRate.*/
Prefer AverageFrameRate, if that is null or an unrealistic value
then fallback to RealFrameRate.*/
#[serde(rename = "ReferenceFrameRate")]
pub reference_frame_rate: Option<f32>,
/// Gets or sets the profile.
@@ -2720,7 +2715,7 @@ pub struct MediaUpdateInfoPathDto {
#[serde(rename = "Path")]
pub path: Option<String>,
/** Gets or sets media update type.
Created, Modified, Deleted.*/
Created, Modified, Deleted.*/
#[serde(rename = "UpdateType")]
pub update_type: Option<String>,
}
@@ -2969,7 +2964,7 @@ pub struct NetworkConfiguration {
#[serde(rename = "EnablePublishedServerUriByRequest")]
pub enable_published_server_uri_by_request: bool,
/** Gets or sets the PublishedServerUriBySubnet
Gets or sets PublishedServerUri to advertise for specific subnets.*/
Gets or sets PublishedServerUri to advertise for specific subnets.*/
#[serde(rename = "PublishedServerUriBySubnet")]
pub published_server_uri_by_subnet: Vec<String>,
/// Gets or sets the filter for remote IP connectivity. Used in conjunction with <seealso cref="P:MediaBrowser.Common.Net.NetworkConfiguration.IsRemoteIPFilterBlacklist" />.
@@ -3033,11 +3028,11 @@ pub struct OpenLiveStreamDto {
#[serde(rename = "AlwaysBurnInSubtitleWhenTranscoding")]
pub always_burn_in_subtitle_when_transcoding: Option<bool>,
/** A MediaBrowser.Model.Dlna.DeviceProfile represents a set of metadata which determines which content a certain device is able to play.
<br />
Specifically, it defines the supported <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.ContainerProfiles">containers</see> and
<see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.CodecProfiles">codecs</see> (video and/or audio, including codec profiles and levels)
the device is able to direct play (without transcoding or remuxing),
as well as which <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.TranscodingProfiles">containers/codecs to transcode to</see> in case it isn't.*/
<br />
Specifically, it defines the supported <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.ContainerProfiles">containers</see> and
<see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.CodecProfiles">codecs</see> (video and/or audio, including codec profiles and levels)
the device is able to direct play (without transcoding or remuxing),
as well as which <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.TranscodingProfiles">containers/codecs to transcode to</see> in case it isn't.*/
#[serde(rename = "DeviceProfile")]
pub device_profile: Option<DeviceProfile>,
/// Gets or sets the device play protocols.
@@ -3073,7 +3068,7 @@ pub struct PackageInfo {
#[serde(rename = "category")]
pub category: String,
/** Gets or sets the guid of the assembly associated with this plugin.
This is used to identify the proper item for automatic updates.*/
This is used to identify the proper item for automatic updates.*/
#[serde(rename = "guid")]
pub guid: uuid::Uuid,
/// Gets or sets the versions.
@@ -3192,11 +3187,11 @@ pub struct PlaybackInfoDto {
#[serde(rename = "LiveStreamId")]
pub live_stream_id: Option<String>,
/** A MediaBrowser.Model.Dlna.DeviceProfile represents a set of metadata which determines which content a certain device is able to play.
<br />
Specifically, it defines the supported <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.ContainerProfiles">containers</see> and
<see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.CodecProfiles">codecs</see> (video and/or audio, including codec profiles and levels)
the device is able to direct play (without transcoding or remuxing),
as well as which <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.TranscodingProfiles">containers/codecs to transcode to</see> in case it isn't.*/
<br />
Specifically, it defines the supported <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.ContainerProfiles">containers</see> and
<see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.CodecProfiles">codecs</see> (video and/or audio, including codec profiles and levels)
the device is able to direct play (without transcoding or remuxing),
as well as which <see cref="P:MediaBrowser.Model.Dlna.DeviceProfile.TranscodingProfiles">containers/codecs to transcode to</see> in case it isn't.*/
#[serde(rename = "DeviceProfile")]
pub device_profile: Option<DeviceProfile>,
/// Gets or sets a value indicating whether to enable direct play.
@@ -4393,7 +4388,7 @@ pub struct ServerConfiguration {
#[serde(rename = "PreviousVersion")]
pub previous_version: Option<String>,
/** Gets or sets the stringified PreviousVersion to be stored/loaded,
because System.Version itself isn't xml-serializable.*/
because System.Version itself isn't xml-serializable.*/
#[serde(rename = "PreviousVersionStr")]
pub previous_version_str: Option<String>,
/// Gets or sets a value indicating whether to enable prometheus metrics exporting.
@@ -4446,12 +4441,12 @@ because System.Version itself isn't xml-serializable.*/
#[serde(rename = "MaxAudiobookResume")]
pub max_audiobook_resume: i32,
/** Gets or sets the threshold in minutes after a inactive session gets closed automatically.
If set to 0 the check for inactive sessions gets disabled.*/
If set to 0 the check for inactive sessions gets disabled.*/
#[serde(rename = "InactiveSessionThreshold")]
pub inactive_session_threshold: i32,
/** Gets or sets the delay in seconds that we will wait after a file system change to try and discover what has been added/removed
Some delay is necessary with some items because their creation is not atomic. It involves the creation of several
different directories and files.*/
Some delay is necessary with some items because their creation is not atomic. It involves the creation of several
different directories and files.*/
#[serde(rename = "LibraryMonitorDelay")]
pub library_monitor_delay: i32,
/// Gets or sets the duration in seconds that we will wait after a library updated event before executing the library changed notification.
@@ -5420,7 +5415,7 @@ pub struct TrickplayOptions {
#[serde(rename = "EnableHwEncoding")]
pub enable_hw_encoding: bool,
/** Gets or sets a value indicating whether to only extract key frames.
Significantly faster, but is not compatible with all decoders and/or video files.*/
Significantly faster, but is not compatible with all decoders and/or video files.*/
#[serde(rename = "EnableKeyFrameOnlyExtraction")]
pub enable_key_frame_only_extraction: bool,
/// Gets or sets the behavior used by trickplay provider on library scan/update.
@@ -5712,7 +5707,7 @@ pub struct UserDto {
#[serde(rename = "ServerId")]
pub server_id: Option<String>,
/** Gets or sets the name of the server.
This is not used by the server and is for client-side usage only.*/
This is not used by the server and is for client-side usage only.*/
#[serde(rename = "ServerName")]
pub server_name: Option<String>,
/// Gets or sets the id.

View File

@@ -3,7 +3,7 @@ pub mod jellyfin;
use std::sync::Arc;
use ::tap::*;
use reqwest::Method;
use reqwest::{Method, header::InvalidHeaderValue};
use serde::{Deserialize, Serialize};
#[derive(thiserror::Error, Debug)]
@@ -15,6 +15,8 @@ pub enum JellyfinApiError {
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Unknown Jellyfin API error")]
InvalidHeader(#[from] InvalidHeaderValue),
#[error("Unknown Jellyfin API error")]
Unknown,
}
@@ -28,7 +30,49 @@ pub struct JellyfinClient {
}
impl JellyfinClient {
pub fn new(config: JellyfinConfig) -> Self {
pub async fn authenticate(
username: impl AsRef<str>,
password: impl AsRef<str>,
config: JellyfinConfig,
) -> Result<Self> {
let url = format!("{}/Users/AuthenticateByName", config.server_url);
let client = reqwest::Client::new();
let token = client
.post(url)
.json(&jellyfin::AuthenticateUserByName {
username: Some(username.as_ref().to_string()),
pw: Some(password.as_ref().to_string()),
})
.send()
.await?
.error_for_status()?
.json::<jellyfin::AuthenticationResult>()
.await?
.access_token
.ok_or_else(|| std::io::Error::other("No field access_token in auth response"))?;
Self::pre_authenticated(token, config)
}
pub fn pre_authenticated(token: impl AsRef<str>, config: JellyfinConfig) -> Result<Self> {
let auth_header = core::iter::once((
reqwest::header::HeaderName::from_static("X-Emby-Authorization"),
reqwest::header::HeaderValue::from_str(&format!(
"MediaBrowser Client=\"{}\", Device=\"{}\", DeviceId=\"{}\", Version=\"{}\"",
config.client_name, config.device_name, config.device_id, config.version
))?,
))
.collect();
let client = reqwest::Client::builder()
.default_headers(auth_header)
.build()?;
Ok(Self {
client,
access_token: Some(token.as_ref().to_string().into()),
config: Arc::new(config),
})
}
pub fn new_with_config(config: JellyfinConfig) -> Self {
JellyfinClient {
client: reqwest::Client::new(),
access_token: None,
@@ -119,45 +163,6 @@ impl JellyfinClient {
Ok(out)
}
pub async fn authenticate(&mut self) -> Result<jellyfin::AuthenticationResult> {
let auth_result: jellyfin::AuthenticationResult = self
.post(
"Users/AuthenticateByName",
&jellyfin::AuthenticateUserByName {
username: Some(self.config.username.clone()),
pw: Some(self.config.password.clone()),
},
)
.await?;
self.access_token = auth_result.access_token.clone().map(Into::into);
Ok(auth_result)
}
pub async fn authenticate_with_cached_token(
&mut self,
path: impl AsRef<std::path::Path>,
) -> Result<String> {
let path = path.as_ref();
if let Ok(token) = self
.load_token(path)
.await
.inspect_err(|err| tracing::warn!("Failed to load cached token: {}", err))
{
tracing::info!("Authenticating with cached token from {:?}", path);
self.access_token = Some(token.clone().into());
Ok(token)
} else {
tracing::info!("No cached token found at {:?}, authenticating...", path);
let token = self
.authenticate()
.await?
.access_token
.ok_or_else(|| JellyfinApiError::Unknown)?;
self.save_token(path).await?;
Ok(token)
}
}
pub async fn raw_items(&self) -> Result<jellyfin::BaseItemDtoQueryResult> {
let text = &self
.request_builder(Method::GET, "Items")
@@ -256,47 +261,11 @@ impl JellyfinClient {
}
}
// pub trait Item {
// fn id(&self) -> &str;
// fn name(&self) -> &str;
// fn type_(&self) -> jellyfin::BaseItemKind;
// fn media_type(&self) -> &str;
// }
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct JellyfinConfig {
pub username: String,
pub password: String,
pub server_url: iref::IriBuf,
pub device_id: String,
}
impl JellyfinConfig {
pub fn new(
username: String,
password: String,
server_url: impl AsRef<str>,
device_id: String,
) -> Self {
JellyfinConfig {
username,
password,
server_url: iref::IriBuf::new(server_url.as_ref().into())
.expect("Failed to parse server URL"),
device_id,
}
}
}
#[test]
fn test_client_authenticate() {
let config = JellyfinConfig {
username: "servius".to_string(),
password: "nfz6yqr_NZD1nxk!faj".to_string(),
server_url: iref::IriBuf::new("https://jellyfin.tsuba.darksailor.dev".into()).unwrap(),
device_id: "testdeviceid".to_string(),
};
let mut client = JellyfinClient::new(config);
let auth_result = tokio_test::block_on(client.authenticate());
assert!(auth_result.is_ok());
pub device_name: String,
pub client_name: String,
pub version: String,
}

View File

@@ -20,12 +20,12 @@ iced = { git = "https://github.com/iced-rs/iced", features = [
"wgpu",
] }
iced_wgpu = { git = "https://github.com/iced-rs/iced" }
gstreamer = "0.23"
gstreamer-app = "0.23" # appsink
gstreamer-base = "0.23" # basesrc
glib = "0.20" # gobject traits and error type
gstreamer = { version = "0.24", features = ["v1_26"] }
gstreamer-app = { version = "0.24", features = ["v1_26"] } # appsink
gstreamer-base = { version = "0.24", features = ["v1_26"] } # basesrc
glib = "0.21" # gobject traits and error type
log = "0.4"
thiserror = "1"
thiserror = "2"
url = "2" # media uri
[package.metadata.nix]
@@ -46,6 +46,8 @@ runtimeLibs = [
"gst_all_1.gst-plugins-ugly",
"gst_all_1.gst-plugins-good",
"gst_all_1.gst-plugins-base",
"glib",
"glib-networking",
]
buildInputs = [
"libxkbcommon",
@@ -55,6 +57,8 @@ buildInputs = [
"gst_all_1.gst-plugins-ugly",
"gst_all_1.gst-plugins-good",
"gst_all_1.gst-plugins-base",
"glib",
"glib-networking",
]
[package.metadata.docs.rs]

View File

@@ -307,7 +307,7 @@ impl Video {
.unwrap_or(0),
);
let sync_av = pipeline.has_property("av-offset", None);
let sync_av = pipeline.has_property("av-offset");
// NV12 = 12bpp
let frame = Arc::new(Mutex::new(Frame::empty()));

View File

@@ -56,7 +56,7 @@
src = let
filterBySuffix = path: exts: lib.any (ext: lib.hasSuffix ext path) exts;
sourceFilters = path: type: (craneLib.filterCargoSources path type) || filterBySuffix path [".c" ".h" ".hpp" ".cpp" ".cc"];
sourceFilters = path: type: (craneLib.filterCargoSources path type) || filterBySuffix path [".c" ".h" ".hpp" ".cpp" ".cc" "wgsl"];
in
lib.cleanSourceWith {
filter = sourceFilters;
@@ -74,19 +74,24 @@
buildInputs = with pkgs;
[
gst_all_1.gst-editing-services
gst_all_1.gst-libav
gst_all_1.gst-plugins-bad
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-rs
gst_all_1.gst-plugins-bad
gst_all_1.gst-plugins-ugly
gst_all_1.gst-rtsp-server
gst_all_1.gst-plugins-rs
gst_all_1.gstreamer
glib
glib-networking
libsysprof-capture
pcre2
libunwind
elfutils
zstd
openssl
vulkan-loader
glib
]
++ (lib.optionals pkgs.stdenv.isLinux [
gst_all_1.gstreamermm
@@ -159,8 +164,8 @@
default = pkg;
};
devShells = {
default =
devShells = rec {
rust-shell =
pkgs.mkShell.override {
stdenv =
if pkgs.stdenv.isLinux
@@ -168,6 +173,8 @@
else pkgs.clangStdenv;
} (commonArgs
// {
GST_PLUGIN_PATH = "/run/current-system/sw/lib/gstreamer-1.0/";
GIO_EXTRA_MODULES = "${pkgs.glib-networking}/lib/gio/modules";
packages = with pkgs;
[
toolchainWithRustAnalyzer
@@ -188,6 +195,7 @@
mold
]);
});
default = rust-shell;
};
}
)

View File

@@ -2,24 +2,9 @@ mod errors;
use api::JellyfinConfig;
use errors::*;
fn jellyfin_config_try() -> Result<JellyfinConfig> {
let file = std::fs::read("config.toml").change_context(Error)?;
let config: JellyfinConfig = toml::from_slice(&file)
.change_context(Error)
.attach("Failed to parse Jellyfin Config")?;
Ok(config)
}
fn jellyfin_config() -> JellyfinConfig {
jellyfin_config_try().unwrap_or_else(|err| {
eprintln!("Error loading Jellyfin configuration: {:?}", err);
std::process::exit(1);
})
}
fn main() -> Result<()> {
tracing_subscriber::fmt::init();
ui_iced::ui(jellyfin_config).change_context(Error)?;
ui_iced::ui().change_context(Error)?;
Ok(())
}

View File

@@ -201,7 +201,7 @@ fn update(state: &mut State, message: Message) -> Task<Message> {
Task::perform(
async move {
let mut client = api::JellyfinClient::new(config);
let mut client = api::JellyfinClient::new_with_config(config);
client.authenticate().await
},
|result| match result {
@@ -662,9 +662,8 @@ fn card(item: &Item) -> Element<'_, Message> {
// fn video(url: &str
fn init(config: impl Fn() -> api::JellyfinConfig + 'static) -> impl Fn() -> (State, Task<Message>) {
move || {
let mut jellyfin = api::JellyfinClient::new(config());
fn init() -> (State, Task<Message>) {
let mut jellyfin = api::JellyfinClient::new_with_config();
(
State::new(jellyfin.clone()),
Task::perform(
@@ -676,9 +675,8 @@ fn init(config: impl Fn() -> api::JellyfinConfig + 'static) -> impl Fn() -> (Sta
)
.chain(Task::done(Message::Refresh)),
)
}
}
pub fn ui(config: impl Fn() -> api::JellyfinConfig + 'static) -> iced::Result {
iced::application(init(config), update, view).run()
pub fn ui() -> iced::Result {
iced::application(init, update, view).run()
}