(add):premiere version fonctionelle
This commit is contained in:
parent
d7154bbc55
commit
67a19e5095
470
Cargo.lock
generated
470
Cargo.lock
generated
@ -8,7 +8,7 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.4",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@ -19,6 +19,21 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-cors"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daa239b93927be1ff123eebada5a3ff23e89f0124ccb8609234e5103d5a5ae6d"
|
||||
dependencies = [
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"derive_more",
|
||||
"futures-util",
|
||||
"log",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.11.1"
|
||||
@ -29,8 +44,8 @@ dependencies = [
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"base64",
|
||||
"bitflags",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.9.4",
|
||||
"brotli",
|
||||
"bytes",
|
||||
"bytestring",
|
||||
@ -230,6 +245,25 @@ version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
|
||||
[[package]]
|
||||
name = "apijellyfin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-cors",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"dotenvy",
|
||||
"futures-util",
|
||||
"glob",
|
||||
"reqwest",
|
||||
"sanitize-filename",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
@ -248,15 +282,27 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.4"
|
||||
@ -343,6 +389,22 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
@ -480,6 +542,15 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
@ -533,6 +604,17 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
@ -551,6 +633,12 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.27"
|
||||
@ -587,6 +675,17 @@ dependencies = [
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.10.1"
|
||||
@ -599,6 +698,44 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"rustls",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.0.0"
|
||||
@ -728,11 +865,17 @@ version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.4",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
@ -745,7 +888,7 @@ version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -884,7 +1027,7 @@ dependencies = [
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -985,7 +1128,7 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -994,7 +1137,7 @@ version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1032,12 +1175,98 @@ version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"rustls-webpki",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
@ -1050,12 +1279,31 @@ version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "sanitize-filename"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
@ -1158,21 +1406,6 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "src"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"dotenvy",
|
||||
"futures-util",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
@ -1190,6 +1423,12 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.13.2"
|
||||
@ -1201,6 +1440,27 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.43"
|
||||
@ -1272,6 +1532,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.16"
|
||||
@ -1285,6 +1555,12 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.41"
|
||||
@ -1317,6 +1593,12 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
@ -1335,6 +1617,12 @@ version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.7"
|
||||
@ -1359,7 +1647,7 @@ version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -1370,6 +1658,15 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
@ -1421,6 +1718,19 @@ dependencies = [
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.101"
|
||||
@ -1453,13 +1763,38 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1468,7 +1803,22 @@ version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1477,28 +1827,46 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@ -1511,30 +1879,64 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.45.1"
|
||||
|
||||
25
Cargo.toml
25
Cargo.toml
@ -1,22 +1,35 @@
|
||||
[package]
|
||||
name = "src"
|
||||
name = "apijellyfin"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
edition = "2021" # 2024 n’est pas encore stable pour Cargo
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
actix-cors = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
anyhow = "1.0"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
dotenvy = "0.15"
|
||||
futures-util = "0.3.31"
|
||||
url = "2.5.7"
|
||||
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] }
|
||||
sanitize-filename = "0.6.0"
|
||||
glob = "0.3.3"
|
||||
|
||||
[[bin]]
|
||||
name = "src"
|
||||
path = "./src/main.rs"
|
||||
name = "apijellyfin"
|
||||
path = "src/main.rs"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 0 # pas d’optimisation lourde en dev
|
||||
debug = true
|
||||
incremental = true # compile uniquement ce qui change
|
||||
codegen-units = 16 # compile en parallèle (plus rapide sur CPU multi-core)
|
||||
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = "thin" # link-time optimization rapide
|
||||
codegen-units = 1 # meilleur binaire, plus lent à compiler
|
||||
strip = "debuginfo" # supprime les symboles pour réduire la taille
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use actix_web::{post, web, HttpResponse, Responder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::services::youtube::download_from_youtube;
|
||||
use crate::services::converter::convert_file;
|
||||
use crate::utils::validate::validate_request;
|
||||
use crate::services::{youtube::download_from_youtube, converter::convert_file, jellyfin::upload_to_jellyfin};
|
||||
use crate::utils::{validate::validate_request, env::env_or_default};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DownloadRequest {
|
||||
@ -12,48 +11,54 @@ pub struct DownloadRequest {
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ApiResponse {
|
||||
status: &'static str,
|
||||
status: String,
|
||||
message: String,
|
||||
file: Option<String>,
|
||||
}
|
||||
|
||||
/// Helper pour générer une réponse JSON cohérente
|
||||
fn json_response(status: &'static str, message: impl Into<String>, file: Option<String>) -> HttpResponse {
|
||||
HttpResponse::Ok().json(ApiResponse {
|
||||
status,
|
||||
message: message.into(),
|
||||
file,
|
||||
fn error_response(message: String) -> HttpResponse {
|
||||
HttpResponse::InternalServerError().json(ApiResponse {
|
||||
status: "error".into(),
|
||||
message,
|
||||
file: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[post("/download")]
|
||||
pub async fn download(req: web::Json<DownloadRequest>) -> impl Responder {
|
||||
// ✅ Validation de la requête
|
||||
if let Err(msg) = validate_request(&req.url, &req.format) {
|
||||
return HttpResponse::BadRequest().json(ApiResponse {
|
||||
status: "error",
|
||||
status: "error".into(),
|
||||
message: msg,
|
||||
file: None,
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ Téléchargement depuis YouTube
|
||||
match download_from_youtube(&req.url, &req.format).await {
|
||||
Ok(file_path) => {
|
||||
// ✅ Conversion audio
|
||||
match convert_file(&file_path, &req.format).await {
|
||||
Ok(final_file) => json_response("ok", "Téléchargement et conversion réussis", Some(final_file)),
|
||||
Err(e) => HttpResponse::InternalServerError().json(ApiResponse {
|
||||
status: "error",
|
||||
message: format!("Erreur conversion: {}", e),
|
||||
file: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
Err(e) => HttpResponse::InternalServerError().json(ApiResponse {
|
||||
status: "error",
|
||||
message: format!("Erreur téléchargement: {}", e),
|
||||
file: None,
|
||||
let file_path = match download_from_youtube(&req.url, &req.format).await {
|
||||
Ok(path) => path,
|
||||
Err(e) => return error_response(format!("Erreur téléchargement: {}", e)),
|
||||
};
|
||||
|
||||
let final_file = match convert_file(&file_path, &req.format).await {
|
||||
Ok(path) => path,
|
||||
Err(e) => return error_response(format!("Erreur conversion: {}", e)),
|
||||
};
|
||||
|
||||
let (host, user, dest, ssh_key, url, key) = (
|
||||
env_or_default("JELLYFIN_HOST", "192.168.1.200"),
|
||||
env_or_default("JELLYFIN_USER", "jellyfin"),
|
||||
env_or_default("JELLYFIN_DEST", "/home/playlist"),
|
||||
env_or_default("JELLYFIN_SSH_KEY", "/root/.ssh/jellyfin_api"),
|
||||
env_or_default("JELLYFIN_URL", "http://192.168.1.200:8096"),
|
||||
env_or_default("JELLYFIN_API_KEY", "changeme"),
|
||||
);
|
||||
|
||||
match upload_to_jellyfin(&final_file, &host, &user, &dest, &ssh_key, &url, &key).await {
|
||||
Ok(_) => HttpResponse::Ok().json(ApiResponse {
|
||||
status: "ok".into(),
|
||||
message: "Fichier ajouté et indexé dans Jellyfin ✅".into(),
|
||||
file: Some(final_file),
|
||||
}),
|
||||
Err(e) => error_response(format!("Upload Jellyfin échoué: {}", e)),
|
||||
}
|
||||
}
|
||||
22
src/main.rs
22
src/main.rs
@ -1,4 +1,3 @@
|
||||
// Déclaration des modules internes
|
||||
mod routes;
|
||||
mod handlers;
|
||||
mod services;
|
||||
@ -7,27 +6,32 @@ mod utils;
|
||||
|
||||
use actix_web::{App, HttpServer, middleware::Logger};
|
||||
use middleware::auth::ApiKeyMiddleware;
|
||||
use actix_cors::Cors;
|
||||
use std::env;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
// Charger les variables d'environnement depuis .env (facultatif)
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
// Définir l'adresse du serveur (par défaut 0.0.0.0:8080)
|
||||
let host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
|
||||
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
|
||||
let bind_addr = format!("{}:{}", host, port);
|
||||
let bind_addr = format!(
|
||||
"{}:{}",
|
||||
env::var("HOST").unwrap_or_else(|_| "0.0.0.0".into()),
|
||||
env::var("PORT").unwrap_or_else(|_| "8080".into())
|
||||
);
|
||||
|
||||
println!("🚀 API Jellyfin démarrée sur http://{}", bind_addr);
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
// Logger Actix (affiche les requêtes entrantes)
|
||||
.wrap(Logger::default())
|
||||
// Middleware Auth par clé API
|
||||
.wrap(ApiKeyMiddleware {})
|
||||
// Routes de l'application
|
||||
.wrap(
|
||||
Cors::default()
|
||||
.allowed_origin("http://192.168.1.206:5173")
|
||||
.allowed_methods(vec!["GET", "POST", "OPTIONS"])
|
||||
.allowed_headers(vec!["Content-Type", "Authorization"])
|
||||
.supports_credentials(),
|
||||
)
|
||||
.configure(routes::config)
|
||||
})
|
||||
.bind(bind_addr)?
|
||||
|
||||
@ -4,8 +4,7 @@ use actix_web::{
|
||||
Error, HttpResponse,
|
||||
};
|
||||
use futures_util::future::{ok, Ready, LocalBoxFuture};
|
||||
use std::rc::Rc;
|
||||
use std::env;
|
||||
use std::{env, rc::Rc};
|
||||
use serde_json::json;
|
||||
|
||||
pub struct ApiKeyMiddleware;
|
||||
@ -24,14 +23,17 @@ where
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(ApiKeyMiddlewareInner {
|
||||
service: Rc::new(service),
|
||||
api_key: env::var("API_KEY").expect("⚠️ API_KEY must be set in .env"),
|
||||
bearer_key: format!(
|
||||
"Bearer {}",
|
||||
env::var("API_KEY").expect("⚠️ API_KEY must be set in .env")
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ApiKeyMiddlewareInner<S> {
|
||||
service: Rc<S>,
|
||||
api_key: String,
|
||||
bearer_key: String,
|
||||
}
|
||||
|
||||
impl<S, B> Service<ServiceRequest> for ApiKeyMiddlewareInner<S>
|
||||
@ -52,24 +54,28 @@ where
|
||||
|
||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
let service = self.service.clone();
|
||||
let expected = format!("Bearer {}", self.api_key);
|
||||
let expected = self.bearer_key.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
match req.headers().get("Authorization") {
|
||||
Some(value) if value == expected.as_str() => {
|
||||
match req.headers().get("Authorization").and_then(|h| h.to_str().ok()) {
|
||||
Some(value) if value == expected => {
|
||||
service.call(req).await.map(|res| res.map_into_boxed_body())
|
||||
}
|
||||
_ => {
|
||||
let (req, _) = req.into_parts();
|
||||
let res = HttpResponse::Unauthorized()
|
||||
.json(json!({
|
||||
"status": "error",
|
||||
"message": "Unauthorized"
|
||||
}))
|
||||
.map_into_boxed_body();
|
||||
Ok(ServiceResponse::new(req, res))
|
||||
}
|
||||
Some(_) => unauthorized::<B>(req, "Invalid API key"),
|
||||
None => unauthorized::<B>(req, "Missing Authorization header"),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Réponse 401 factorisée
|
||||
fn unauthorized<B>(req: ServiceRequest, msg: &str) -> Result<ServiceResponse<BoxBody>, Error>
|
||||
where
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
let (req, _) = req.into_parts();
|
||||
let res = HttpResponse::Unauthorized()
|
||||
.json(json!({ "status": "error", "message": msg }))
|
||||
.map_into_boxed_body();
|
||||
Ok(ServiceResponse::new(req, res))
|
||||
}
|
||||
@ -1,29 +1,33 @@
|
||||
use std::process::Command;
|
||||
use std::path::Path;
|
||||
use anyhow::{Result, Context};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub async fn convert_file(input: &str, format: &str) -> Result<String> {
|
||||
let output_file = format!("/tmp/{}_conv.{}", Uuid::new_v4(), format);
|
||||
let input_path = Path::new(input);
|
||||
|
||||
// Exécution de ffmpeg avec redirection des sorties
|
||||
let output = Command::new("ffmpeg")
|
||||
.arg("-y") // overwrite sans confirmation
|
||||
.arg("-i").arg(input) // input file
|
||||
.arg(&output_file) // output file
|
||||
.output()
|
||||
.with_context(|| "Impossible d'exécuter ffmpeg")?;
|
||||
|
||||
// Vérification du code retour
|
||||
if output.status.success() {
|
||||
// Vérification que le fichier existe vraiment
|
||||
if Path::new(&output_file).exists() {
|
||||
Ok(output_file)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("ffmpeg n’a pas généré de fichier de sortie"))
|
||||
}
|
||||
} else {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
Err(anyhow::anyhow!("Échec ffmpeg: {}", stderr))
|
||||
// Vérifie si l’extension est déjà correcte
|
||||
if input_path.extension().and_then(|ext| ext.to_str()) == Some(format) {
|
||||
return Ok(input.to_string()); // rien à faire
|
||||
}
|
||||
}
|
||||
|
||||
// Sinon, on génère un nouveau fichier
|
||||
let stem = input_path
|
||||
.file_stem()
|
||||
.ok_or_else(|| anyhow::anyhow!("Nom de fichier invalide"))?
|
||||
.to_string_lossy();
|
||||
|
||||
let output_file = format!("/tmp/{}.{}", stem, format);
|
||||
|
||||
let status = Command::new("ffmpeg")
|
||||
.arg("-y") // overwrite
|
||||
.arg("-i").arg(input)
|
||||
.arg(&output_file)
|
||||
.status()
|
||||
.context("Erreur lors de l’exécution de ffmpeg")?;
|
||||
|
||||
if status.success() {
|
||||
Ok(output_file)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("ffmpeg conversion failed"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,44 @@
|
||||
pub async fn upload_to_jellyfin(file_path: &str) -> Result<(), anyhow::Error> {
|
||||
|
||||
use anyhow::{Result, Context};
|
||||
use std::process::Command;
|
||||
use reqwest;
|
||||
|
||||
|
||||
println!("Fichier {} envoyé à Jellyfin", file_path);
|
||||
Ok(())
|
||||
/// Upload un fichier vers Jellyfin via rsync+SSH et rafraîchit la médiathèque
|
||||
pub async fn upload_to_jellyfin(
|
||||
file_path: &str,
|
||||
jellyfin_host: &str,
|
||||
jellyfin_user: &str,
|
||||
jellyfin_dest: &str,
|
||||
ssh_key_path: &str,
|
||||
jellyfin_url: &str,
|
||||
jellyfin_api_key: &str,
|
||||
) -> Result<()> {
|
||||
// Transfert du fichier avec rsync
|
||||
let output = Command::new("rsync")
|
||||
.args([
|
||||
"-avz",
|
||||
"-e", &format!("ssh -i {}", ssh_key_path),
|
||||
file_path,
|
||||
&format!("{}@{}:{}", jellyfin_user, jellyfin_host, jellyfin_dest),
|
||||
])
|
||||
.output()
|
||||
.context("Impossible d’exécuter rsync")?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
anyhow::bail!("rsync failed (code: {:?}): {}", output.status.code(), stderr);
|
||||
}
|
||||
|
||||
// Rafraîchit la médiathèque Jellyfin
|
||||
let resp = reqwest::Client::new()
|
||||
.post(format!("{}/Library/Refresh", jellyfin_url))
|
||||
.header("X-Emby-Token", jellyfin_api_key)
|
||||
.send()
|
||||
.await
|
||||
.context("Erreur lors de l’appel à l’API Jellyfin")?;
|
||||
|
||||
if resp.status().is_success() {
|
||||
Ok(())
|
||||
} else {
|
||||
anyhow::bail!("Échec refresh Jellyfin (status: {})", resp.status())
|
||||
}
|
||||
}
|
||||
@ -1,34 +1,37 @@
|
||||
use std::process::Command;
|
||||
use std::path::Path;
|
||||
use anyhow::{Result, Context};
|
||||
use uuid::Uuid;
|
||||
use std::str;
|
||||
|
||||
pub async fn download_from_youtube(url: &str, format: &str) -> Result<String> {
|
||||
// On laisse yt-dlp gérer l'extension, mais on contrôle le préfixe
|
||||
let output_template = format!("/tmp/{}_out.%(ext)s", Uuid::new_v4());
|
||||
let output_template = format!("/tmp/%(title)s-%(uploader)s.{}", format);
|
||||
|
||||
// Exécution yt-dlp
|
||||
// yt-dlp : extrait le fichier ET affiche le chemin final
|
||||
let output = Command::new("yt-dlp")
|
||||
.arg("-x") // extraire uniquement l’audio
|
||||
.arg("--audio-format").arg(format)
|
||||
.arg("--no-playlist")
|
||||
.arg("-o").arg(&output_template)
|
||||
.arg(url)
|
||||
.args([
|
||||
"-x",
|
||||
"--audio-format", format,
|
||||
"--no-playlist",
|
||||
"-o", &output_template,
|
||||
"--print", "after_move:filepath",
|
||||
url,
|
||||
])
|
||||
.output()
|
||||
.with_context(|| "Impossible d'exécuter yt-dlp")?;
|
||||
|
||||
// Vérification du code retour
|
||||
if output.status.success() {
|
||||
// yt-dlp remplace %(ext)s par la vraie extension
|
||||
let expected_file = output_template.replace("%(ext)s", format);
|
||||
|
||||
if Path::new(&expected_file).exists() {
|
||||
Ok(expected_file)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("yt-dlp a terminé sans générer de fichier"))
|
||||
}
|
||||
} else {
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
Err(anyhow::anyhow!("Échec yt-dlp: {}", stderr))
|
||||
return Err(anyhow::anyhow!("Échec yt-dlp: {}", stderr));
|
||||
}
|
||||
}
|
||||
|
||||
// Récupérer le vrai chemin depuis stdout
|
||||
let filepath = str::from_utf8(&output.stdout)
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
if filepath.is_empty() {
|
||||
return Err(anyhow::anyhow!("yt-dlp a terminé mais n’a pas retourné de fichier"));
|
||||
}
|
||||
|
||||
Ok(filepath)
|
||||
}
|
||||
|
||||
6
src/utils/env.rs
Normal file
6
src/utils/env.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use std::env;
|
||||
|
||||
/// Récupère une variable d'environnement avec un fallback par défaut
|
||||
pub fn env_or_default(key: &str, default: &str) -> String {
|
||||
env::var(key).unwrap_or_else(|_| default.to_string())
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
pub fn generate_temp_filename(extension: &str) -> String {
|
||||
format!("/tmp/file_{}.{}", uuid::Uuid::new_v4(), extension)
|
||||
}
|
||||
@ -1,2 +1,2 @@
|
||||
pub mod validate;
|
||||
pub mod filename;
|
||||
pub mod env;
|
||||
@ -1,25 +1,19 @@
|
||||
use url::Url;
|
||||
|
||||
pub fn validate_request(url: &str, format: &str) -> Result<(), String> {
|
||||
// Vérification de l'URL
|
||||
let parsed = Url::parse(url).map_err(|_| "URL invalide.".to_string())?;
|
||||
|
||||
// Liste blanche des domaines
|
||||
let allowed_domains = ["youtube.com", "www.youtube.com", "youtu.be"];
|
||||
let domain = parsed.domain().unwrap_or_default();
|
||||
let allowed_formats = ["mp3", "flac", "wav"];
|
||||
|
||||
if !allowed_domains.contains(&domain) {
|
||||
let domain = parsed.domain().unwrap_or_default();
|
||||
if !allowed_domains.iter().any(|d| d == &domain) {
|
||||
return Err(format!("Domaine non autorisé: {}", domain));
|
||||
}
|
||||
|
||||
// Vérification du format
|
||||
let allowed_formats = ["mp3", "flac", "wav"];
|
||||
if !allowed_formats.contains(&format) {
|
||||
return Err(format!(
|
||||
"Format non supporté: {}. Formats valides: {:?}",
|
||||
format, allowed_formats
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user