diff --git a/.cargo/config.toml b/.cargo/config.toml index 2460f4c..4cc9335 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,3 @@ default = "crates-io" [registries.elnafo-vcs] index = "sparse+https://vcs.elnafo.ru/api/packages/L-Nafaryus/cargo/" - -[target.x86_64-unknown-linux-gnu] -rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/.gitignore b/.gitignore index 012adb5..58bf802 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /target +/vendor result* /temp /.direnv .env +.tmp diff --git a/Cargo.lock b/Cargo.lock index 47bfd11..e0f587e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,55 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "askama" version = "0.12.1" @@ -96,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -113,15 +162,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -146,7 +195,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tower 0.5.1", + "tower", "tower-layer", "tower-service", "tracing", @@ -154,9 +203,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -251,6 +300,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "cpufeatures" version = "0.2.14" @@ -349,6 +444,7 @@ name = "elnafo-radio" version = "0.1.0" dependencies = [ "axum", + "clap", "elnafo-radio-frontend", "mime_guess", "mpd", @@ -382,9 +478,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -469,8 +565,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -498,6 +594,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -540,9 +642,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -581,9 +683,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-util", @@ -592,7 +694,6 @@ dependencies = [ "hyper", "pin-project-lite", "tokio", - "tower 0.4.13", "tower-service", ] @@ -606,7 +707,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.8", "same-file", "walkdir", "winapi-util", @@ -622,6 +723,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.11" @@ -636,9 +743,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -713,7 +820,7 @@ dependencies = [ "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -780,9 +887,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "overload" @@ -796,26 +906,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -828,6 +918,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "powerfmt" version = "0.2.0" @@ -854,14 +950,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -875,13 +971,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -892,9 +988,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rust-embed" @@ -1001,9 +1097,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -1062,14 +1158,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] -name = "syn" -version = "2.0.77" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1130,7 +1232,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1180,9 +1282,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -1191,21 +1293,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - [[package]] name = "tower" version = "0.5.1" @@ -1224,9 +1311,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41515cc9e193536d93fd0dbbea0c73819c08eca76e0b30909a325c3ec90985bb" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" dependencies = [ "async-compression", "bitflags", @@ -1340,9 +1427,15 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -1394,7 +1487,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1412,6 +1505,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1478,9 +1580,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 4c0d1f2..8f7f959 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,11 @@ -[package] -name = "elnafo-radio" -version = "0.1.0" -edition = "2021" -publish = ["elnafo-vcs"] -authors = ["L-Nafaryus "] -description = "Elnafo radio" -license = "MIT" -repository = "https://vcs.elnafo.ru/L-Nafaryus/elnafo-radio" - -[dependencies] -axum = { version = "0.7.6", features = ["http2", "macros"] } -elnafo-radio-frontend = { version = "0.1.0", path = "crates/frontend" } -mime_guess = "2.0.5" -mpd = "0.1.0" -serde = { version = "1.0.210", features = ["derive"] } -serde_json = "1.0.128" -time = "0.3.36" -tokio = { version = "1.40.0", default-features = false, features = ["macros", "rt-multi-thread"] } -toml = "0.8.19" -tower-http = { version = "0.6.0", features = ["trace", "cors", "compression-gzip", "decompression-gzip"] } -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } - [workspace] -members = ["crates/frontend"] +members = ["crates/frontend", "crates/backend"] resolver = "2" + +[workspace.package] +version = "0.1.0" +edition = "2021" + +[workspace.metadata.crane] +name = "elnafo-radio" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ffecc31 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2023 George Kusayko [L-Nafaryus] + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..95bab84 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# elnafo-radio + +

+ Elnafo Radio + Elnafo Radio +

+

+ nix-flake + bonfire-cachix +

+

+ Simple interface for MPD services +

+ +## License + +**elnafo-radio** is licensed under the terms of the [MIT License](https://vcs.elnafo.ru/L-Nafaryus/elnafo-radio/raw/branch/master/LICENSE). diff --git a/crates/backend/Cargo.toml b/crates/backend/Cargo.toml new file mode 100644 index 0000000..e1c5462 --- /dev/null +++ b/crates/backend/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "elnafo-radio" +version = "0.1.0" +edition = "2021" +publish = ["elnafo-vcs"] +authors = ["L-Nafaryus "] +description = "Simple interface for MPD services" +license = "MIT" +repository = "https://vcs.elnafo.ru/L-Nafaryus/elnafo-radio" + +[dependencies] +axum = { version = "0.7.6", features = ["http2", "macros"] } +clap = { version = "4.5.18", features = ["derive"] } +elnafo-radio-frontend = { version = "0.1.0", path = "../frontend" } +mime_guess = "2.0.5" +mpd = "0.1.0" +serde = { version = "1.0.210", features = ["derive"] } +serde_json = "1.0.128" +time = "0.3.36" +tokio = { version = "1.40.0", default-features = false, features = ["macros", "rt-multi-thread"] } +toml = "0.8.19" +tower-http = { version = "0.6.0", features = ["trace", "cors", "compression-gzip", "decompression-gzip"] } +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } + diff --git a/src/api.rs b/crates/backend/src/api.rs similarity index 96% rename from src/api.rs rename to crates/backend/src/api.rs index 8697b01..a814818 100644 --- a/src/api.rs +++ b/crates/backend/src/api.rs @@ -1,16 +1,11 @@ use axum::{ - extract::DefaultBodyLimit, extract::State, - http::{ - header::{self, *}, - Method, StatusCode, Uri, - }, - response::{IntoResponse, Response}, + http::{header::*, Method, StatusCode}, + response::IntoResponse, routing::{get, post}, Json, Router, }; use mpd::Client; -use serde::ser::{Serialize, SerializeStruct, Serializer}; use serde_json::json; use std::sync::Arc; use tower_http::cors::CorsLayer; diff --git a/src/config.rs b/crates/backend/src/config.rs similarity index 97% rename from src/config.rs rename to crates/backend/src/config.rs index 12f7196..785467e 100644 --- a/src/config.rs +++ b/crates/backend/src/config.rs @@ -108,7 +108,7 @@ impl std::fmt::Display for ConfigError { Self::Parse => write!(f, "Failed to parse Config from string"), Self::StringParse => write!(f, "Failed to parse environment variable"), Self::Serialize => write!(f, "Failed to serialize Config to TOML"), - Self::IO => write!(f, "Faild to write file"), + Self::IO => write!(f, "Failed to write a configuration file"), } } } diff --git a/src/main.rs b/crates/backend/src/main.rs similarity index 72% rename from src/main.rs rename to crates/backend/src/main.rs index 5f42831..cb94174 100644 --- a/src/main.rs +++ b/crates/backend/src/main.rs @@ -1,20 +1,23 @@ +//#![doc = include_str!("../../../README.md")] + pub mod api; pub mod config; use axum::{ extract::State, http::{ - header::{self, *}, - Method, StatusCode, Uri, + header::{self}, + StatusCode, Uri, }, response::{IntoResponse, Response}, routing::get, Router, }; +use clap::Parser; use std::net::SocketAddr; use std::sync::Arc; use tower_http::trace::{self, TraceLayer}; -use tracing::Level; +use tracing::{info, warn, Level}; use crate::config::Config; @@ -22,6 +25,14 @@ pub struct Context { pub config: Config, } +#[derive(Parser)] +#[command(version, about, long_about = None)] +pub struct Cli { + /// Path to the configuration file + #[arg(short, long)] + pub config: Option, +} + #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt() @@ -29,13 +40,25 @@ async fn main() -> Result<(), Box> { .compact() .init(); - let config = match Config::open(Config::data_dir()?.join("config.toml").as_path()) { + let args = Cli::parse(); + + let config_path = if let Some(path) = args.config { + match std::path::absolute(&path) { + Ok(resolved) => resolved, + Err(_) => path, + } + } else { + Config::data_dir()?.join("config.toml") + }; + + let config = match Config::open(config_path.as_path()) { Ok(config) => { - println!("Config loaded: {:?}", config); + info!("Config loaded {:?}", config_path); config } Err(err) => { - eprintln!("{}", err); + warn!("{}", err); + info!("Using default configuration"); Config::new() } }; @@ -60,7 +83,7 @@ async fn main() -> Result<(), Box> { let listener = tokio::net::TcpListener::bind(&address).await?; - println!("Listening on http://{}", address); + info!("Listening on http://{}", address); axum::serve(listener, app.into_make_service()).await?; @@ -85,18 +108,14 @@ async fn frontend_handler(State(state): State>, _: Uri) -> impl Int elnafo_radio_frontend::BaseTemplate { view: String::from("app"), title: state.config.base.title.clone(), - meta: if let Some(meta) = &state.config.base.meta { - Some( - meta.iter() - .map(|kv| Meta { - name: kv.0.clone(), - content: kv.1.clone(), - }) - .collect(), - ) - } else { - None - }, + meta: state.config.base.meta.as_ref().map(|meta| { + meta.iter() + .map(|kv| Meta { + name: kv.0.clone(), + content: kv.1.clone(), + }) + .collect() + }), } } diff --git a/crates/frontend/Cargo.toml b/crates/frontend/Cargo.toml index 8834059..14bc3b9 100644 --- a/crates/frontend/Cargo.toml +++ b/crates/frontend/Cargo.toml @@ -2,7 +2,11 @@ name = "elnafo-radio-frontend" version = "0.1.0" edition = "2021" +publish = ["elnafo-vcs"] authors = ["L-Nafaryus "] +description = "Simple interface for MPD services (frontend)" +license = "MIT" +repository = "https://vcs.elnafo.ru/L-Nafaryus/elnafo-radio" [build-dependencies] ignore = "0.4.22" diff --git a/crates/frontend/package-lock.json b/crates/frontend/package-lock.json index df67a2e..6e5f5c7 100644 --- a/crates/frontend/package-lock.json +++ b/crates/frontend/package-lock.json @@ -1,18 +1,17 @@ { - "name": "materia-frontend", - "version": "0.0.5", + "name": "elnafo-radio-vue", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "materia-frontend", - "version": "0.0.5", + "name": "elnafo-radio-vue", + "version": "0.1.0", "dependencies": { "@catppuccin/tailwindcss": "^0.1.6", "@hey-api/client-axios": "^0.2.3", "autoprefixer": "^10.4.18", "axios": "^1.6.8", - "filesize": "^10.1.6", "pinia": "^2.1.7", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", @@ -27,7 +26,6 @@ "@vitejs/plugin-vue-jsx": "^3.1.0", "@vue/tsconfig": "^0.5.0", "npm-run-all2": "^6.1.1", - "openapi-typescript-codegen": "^0.29.0", "typescript": "~5.3.0", "vite": "^5.0.10", "vue-tsc": "^2.0.29" @@ -2151,14 +2149,6 @@ "reusify": "^1.0.4" } }, - "node_modules/filesize": { - "version": "10.1.6", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", - "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", - "engines": { - "node": ">= 10.4.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -2229,20 +2219,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -2375,12 +2351,6 @@ "node": ">=4" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -2602,18 +2572,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -3001,31 +2959,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi-typescript-codegen": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.29.0.tgz", - "integrity": "sha512-/wC42PkD0LGjDTEULa/XiWQbv4E9NwLjwLjsaJ/62yOsoYhwvmBR31kPttn1DzQ2OlGe5stACcF/EIkZk43M6w==", - "dev": true, - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^11.5.4", - "camelcase": "^6.3.0", - "commander": "^12.0.0", - "fs-extra": "^11.2.0", - "handlebars": "^4.7.8" - }, - "bin": { - "openapi": "bin/index.js" - } - }, - "node_modules/openapi-typescript-codegen/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "engines": { - "node": ">=18" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -3843,15 +3776,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/crates/frontend/package.json b/crates/frontend/package.json index e78d4da..cf0ab1c 100644 --- a/crates/frontend/package.json +++ b/crates/frontend/package.json @@ -1,6 +1,6 @@ { - "name": "materia-frontend", - "version": "0.0.5", + "name": "elnafo-radio-vue", + "version": "0.1.0", "private": true, "type": "module", "scripts": { @@ -9,7 +9,6 @@ "preview": "vite preview", "build": "vite build", "type-check": "vue-tsc --build --force", - "generate-client": "openapi --input ./openapi.json --output ./src/client_old/ --client axios --name Client", "openapi-ts": "openapi-ts --input ./openapi.json --output ./src/client/ --client @hey-api/client-axios" }, "dependencies": { @@ -17,7 +16,6 @@ "@hey-api/client-axios": "^0.2.3", "autoprefixer": "^10.4.18", "axios": "^1.6.8", - "filesize": "^10.1.6", "pinia": "^2.1.7", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", @@ -32,7 +30,6 @@ "@vitejs/plugin-vue-jsx": "^3.1.0", "@vue/tsconfig": "^0.5.0", "npm-run-all2": "^6.1.1", - "openapi-typescript-codegen": "^0.29.0", "typescript": "~5.3.0", "vite": "^5.0.10", "vue-tsc": "^2.0.29" diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..73f08fd --- /dev/null +++ b/deny.toml @@ -0,0 +1,9 @@ +[licenses] +allow = [ + "Apache-2.0", + "MIT", + "Unicode-DFS-2016", + "BSD-3-Clause", + "Unlicense" +] +unused-allowed-license = "warn" diff --git a/flake.lock b/flake.lock index a8df878..7d9795e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "advisory-db": { + "flake": false, + "locked": { + "lastModified": 1727353582, + "narHash": "sha256-2csMEEOZhvowVKZNBHk1kMJqk72ZMrPj9LQYCzP6EKs=", + "owner": "rustsec", + "repo": "advisory-db", + "rev": "cb905e6e405834bdff1eb1e20c9b10edb5403889", + "type": "github" + }, + "original": { + "owner": "rustsec", + "repo": "advisory-db", + "type": "github" + } + }, "crane": { "locked": { "lastModified": 1725409566, @@ -58,6 +74,21 @@ "type": "github" } }, + "nix-std": { + "locked": { + "lastModified": 1710870712, + "narHash": "sha256-e+7MJF2gsgTBuOWv4mCimSP0D9+naeFSw9a7N3yEmv4=", + "owner": "chessai", + "repo": "nix-std", + "rev": "31bbc925750cc9d8f828fe55cee1a2bd985e0c00", + "type": "github" + }, + "original": { + "owner": "chessai", + "repo": "nix-std", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1726755586, @@ -115,9 +146,11 @@ }, "root": { "inputs": { + "advisory-db": "advisory-db", "crane": "crane", "dream2nix": "dream2nix", "fenix": "fenix", + "nix-std": "nix-std", "nixpkgs": "nixpkgs" } }, diff --git a/flake.nix b/flake.nix index 96a559e..e61455e 100644 --- a/flake.nix +++ b/flake.nix @@ -1,14 +1,12 @@ { - description = "Elnafo"; + description = "Simple interface for MPD services"; nixConfig = { extra-substituters = [ "https://cache.elnafo.ru" - "https://bonfire.cachix.org" ]; extra-trusted-public-keys = [ "cache.elnafo.ru:j3VD+Hn+is2Qk3lPXDSdPwHJQSatizk7V82iJ2RP1yo=" - "bonfire.cachix.org-1:mzAGBy/Crdf8NhKail5ciK7ZrGRbPJJobW6TwFb7WYM=" ]; }; @@ -26,9 +24,23 @@ url = "github:nix-community/dream2nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + advisory-db = { + url = "github:rustsec/advisory-db"; + flake = false; + }; + nix-std.url = "github:chessai/nix-std"; }; outputs = {self, ...} @ inputs: let + maintainers = { + L-Nafaryus = { + email = "l.nafaryus@elnafo.ru"; + github = "L-Nafaryus"; + githubId = 37117584; + name = "L-Nafaryus"; + }; + }; + pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux; lib = pkgs.lib; fenixPkgs = inputs.fenix.packages.x86_64-linux; @@ -54,17 +66,44 @@ .config .public // {inherit meta;}; + + src = craneLib.cleanCargoSource ./.; + cargoVendorDeps = craneLib.vendorCargoDeps { + inherit src; + }; + commonArgs = { + inherit src; + strictDeps = true; + }; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + crateArgs = { + inherit cargoArtifacts; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./Cargo.toml + ./Cargo.lock + ./crates/backend + ./crates/frontend + ]; + }; + strictDeps = true; + configurePhase = '' + cp -rv ${self.packages.x86_64-linux.elnafo-radio-vue}/dist ./crates/frontend/ + ln -sv ${cargoVendorDeps}/config.toml ./.cargo-home/config.toml + ''; + }; in { packages.x86_64-linux = rec { - elnafo-radio-frontend = dreamBuildPackage { + elnafo-radio-vue = dreamBuildPackage { module = { lib, config, dream2nix, ... }: { - name = "elnafo-radio-frontend"; - version = "0.0.5"; + name = "elnafo-radio-vue"; + version = "0.1.0"; imports = [ dream2nix.modules.dream2nix.WIP-nodejs-builder-v3 @@ -87,38 +126,63 @@ }; }; meta = with lib; { - description = "Materia frontend (nodejs)"; + description = "Simple interface for MPD services (frontend)"; license = licenses.mit; + maintainers = with maintainers; [L-Nafaryus]; broken = false; }; }; - elnafo-radio = let - common = { - pname = "elnafo-radio"; - version = "0.1.0"; - src = pkgs.lib.cleanSourceWith { - src = ./.; - filter = path: type: (craneLib.filterCargoSources path type); - }; - - strictDeps = true; - - #nativeBuildInputs = [pkgs.pkg-config]; - - #buildInputs = [pkgs.openssl]; + elnafo-radio = craneLib.buildPackage { + pname = "elnafo-radio"; + version = "0.1.0"; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./Cargo.toml + ./Cargo.lock + ./crates/backend + ./crates/frontend + ]; }; + strictDeps = true; + cargoExtraArgs = "-p elnafo-radio"; + configurePhase = '' + cp -rv ${self.packages.x86_64-linux.elnafo-radio-vue}/dist ./crates/frontend/ + ln -sv ${cargoVendorDeps}/config.toml ./.cargo-home/config.toml + ''; + inherit cargoArtifacts; - cargoArtifacts = craneLib.buildDepsOnly common; - in - craneLib.buildPackage (common // {inherit cargoArtifacts;}); + meta = with lib; { + description = "Simple interface for MPD services"; + license = licenses.mit; + maintainers = with maintainers; [L-Nafaryus]; + platforms = platforms.x86_64; + mainProgram = "elnafo-radio"; + }; + }; default = elnafo-radio; }; checks.x86_64-linux = { + inherit (self.packages.x86_64-linux) elnafo-radio-vue elnafo-radio; + elnafo-radio-fmt = craneLib.cargoFmt { - src = craneLib.cleanCargoSource (craneLib.path ./.); + inherit src; + }; + + elnafo-radio-doc = craneLib.cargoDoc crateArgs; + + elnafo-radio-clippy = craneLib.cargoClippy crateArgs; + + elnafo-radio-audit = craneLib.cargoAudit { + inherit src; + inherit (inputs) advisory-db; + }; + + my-workspace-deny = craneLib.cargoDeny { + inherit src; }; }; @@ -127,20 +191,191 @@ buildInputs = [ fenixPkgs.complete.toolchain pkgs.ripgrep - pkgs.postgresql - pkgs.diesel-cli pkgs.cargo-watch pkgs.mold-wrapped pkgs.nodejs pkgs.cargo-release ]; }; + }; - elnafo-radio = craneLib.devShell { - checks = self.checks.x86_64-linux; + nixosModules = rec { + elnafo-radio = { + config, + lib, + pkgs, + ... + }: + with lib; let + cfg = config.services.elnafo-radio; + in { + options.services.elnafo-radio = { + enable = mkEnableOption "Enables the elnafo-radio service"; - packages = []; - }; + package = mkOption { + type = types.package; + default = self.packages.x86_64-linux.elnafo-radio; + description = "The package to use."; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/elnafo-radio"; + description = lib.mdDoc "Directory to store data files"; + }; + + base = mkOption { + type = types.submodule { + options = { + title = mkOption { + type = types.str; + default = "Elnafo Radio"; + description = "Title of the page"; + }; + meta = mkOption { + type = types.nullOr (types.listOf (types.listOf types.str)); + default = null; + description = "List of meta tag pairs"; + }; + }; + }; + default = {title = "Elnafo Radio";}; + description = "Base configuration"; + }; + + server = mkOption { + type = types.submodule { + options = { + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Server address"; + }; + port = mkOption { + type = types.port; + default = 54605; + description = "Server port"; + }; + }; + }; + default = { + address = "127.0.0.1"; + port = 54605; + }; + description = "Server configuration"; + }; + + stations = mkOption { + type = types.nullOr (types.listOf (types.submodule { + options = { + id = mkOption { + type = types.str; + description = "Station id"; + }; + name = mkOption { + type = types.str; + description = "Station name"; + }; + address = mkOption { + type = types.str; + description = "MPD service address"; + }; + port = mkOption { + type = types.port; + description = "MPD service port"; + }; + url = mkOption { + type = types.nullOr types.str; + default = null; + description = "Station stream url"; + }; + status = mkOption { + type = types.nullOr types.str; + default = null; + description = "Station status"; + }; + genre = mkOption { + type = types.nullOr types.str; + default = null; + description = "Station genre"; + }; + location = mkOption { + type = types.nullOr types.port; + default = null; + description = "Station location"; + }; + }; + })); + default = null; + description = "Server configuration"; + }; + }; + + config = mkIf cfg.enable { + users.users.elnafo-radio = { + description = "Elnafo radio service user"; + home = cfg.dataDir; + createHome = true; + isSystemUser = true; + group = "elnafo-radio"; + }; + users.groups.elnafo-radio = {}; + + systemd.services.elnafo-radio = { + description = "Elnafo radio service"; + wantedBy = ["multi-user.target"]; + after = ["network.target"]; + + serviceConfig = { + Restart = "always"; + ExecStart = "${lib.getExe cfg.package}"; + User = "elnafo-radio"; + WorkingDirectory = cfg.dataDir; + }; + + preStart = let + toTOML = inputs.nix-std.lib.serde.toTOML; + configFile = pkgs.writeText "config.toml" '' + ${toTOML {inherit (cfg) base server stations;}} + ''; + in '' + ln -sf ${configFile} ./config.toml + ''; + }; + }; + }; + + default = elnafo-radio; + }; + + nixosConfigurations.elnafo-radio = inputs.nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + self.nixosModules.elnafo-radio + ({pkgs, ...}: { + boot.isContainer = true; + + networking.hostName = "elnafo-radio"; + networking.useDHCP = false; + + services.elnafo-radio = { + enable = true; + base.meta = [ + ["author" "L-Nafaryus"] + ]; + stations = [ + { + id = "test"; + name = "Test"; + address = "127.0.0.1"; + port = 8080; + } + ]; + }; + + system.stateVersion = "24.05"; + }) + ]; }; }; }