From 73c5e4af9b4af142b7d36f6f29c19b06d163f62a Mon Sep 17 00:00:00 2001 From: David Skrundz Date: Mon, 19 May 2025 15:05:24 -0600 Subject: [PATCH] Extend model to support update command --- Cargo.lock | 231 ++++++++++++++-------------- Cargo.toml | 4 +- crates/cli/Cargo.toml | 2 +- crates/cli/src/cli/mod.rs | 31 ++-- crates/cli/src/main.rs | 85 ++++++---- crates/cli/src/run/flix.rs | 68 ++++++++ crates/cli/src/run/mod.rs | 1 + crates/cli/src/run/tmdb.rs | 26 ++-- crates/flix/Cargo.toml | 2 +- crates/flix/src/model/collection.rs | 4 +- crates/flix/src/model/episode.rs | 21 ++- crates/flix/src/model/season.rs | 19 ++- crates/flix/src/model/show.rs | 4 +- crates/flix/src/model/verse.rs | 4 +- crates/tmdb/Cargo.toml | 2 +- crates/tmdb/src/model/collection.rs | 5 +- crates/tmdb/src/model/episode.rs | 5 +- crates/tmdb/src/model/id.rs | 7 + crates/tmdb/src/model/season.rs | 5 +- crates/tmdb/src/model/show.rs | 5 +- 20 files changed, 337 insertions(+), 194 deletions(-) create mode 100644 crates/cli/src/run/flix.rs diff --git a/Cargo.lock b/Cargo.lock index 8d23d64..e1fa9a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,9 +81,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -102,9 +102,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bumpalo" @@ -120,9 +120,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.21" +version = "1.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" dependencies = [ "shlex", ] @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" dependencies = [ "clap_builder", "clap_derive", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" dependencies = [ "anstream", "anstyle", @@ -214,7 +214,7 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "flix" -version = "0.0.4" +version = "0.0.5" dependencies = [ "chrono", "flix-tmdb", @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "flix-cli" -version = "0.0.4" +version = "0.0.5" dependencies = [ "anyhow", "clap", @@ -238,7 +238,7 @@ dependencies = [ [[package]] name = "flix-tmdb" -version = "0.0.4" +version = "0.0.5" dependencies = [ "chrono", "reqwest", @@ -311,9 +311,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", @@ -424,7 +424,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -449,21 +449,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -472,31 +473,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -504,67 +485,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "idna" version = "1.0.3" @@ -578,9 +546,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -632,9 +600,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "log" @@ -642,6 +610,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "memchr" version = "2.7.4" @@ -716,6 +690,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -736,9 +719,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", "cfg_aliases", @@ -756,12 +739,13 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbafbbdbb0f638fe3f35f3c56739f77a8a1d070cb25603226c83339b391472b" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "getrandom 0.3.2", + "getrandom 0.3.3", + "lru-slab", "rand", "ring", "rustc-hash", @@ -829,7 +813,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -871,7 +855,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.26.11", "windows-registry", ] @@ -903,9 +887,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", "ring", @@ -926,18 +910,19 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time", + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -1111,9 +1096,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -1136,9 +1121,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -1296,12 +1281,6 @@ dependencies = [ "url", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -1431,9 +1410,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.10" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37493cadf42a2a939ed404698ded7fb378bf301b5011f973361779a3a74f8c93" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] @@ -1457,9 +1445,9 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d" dependencies = [ "windows-link", ] @@ -1621,9 +1609,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -1637,23 +1625,17 @@ dependencies = [ "bitflags", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -1663,9 +1645,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -1721,10 +1703,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -1733,9 +1726,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 67809ea..0be2d3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,8 @@ overflow-checks = true strip = "debuginfo" [workspace.dependencies] -flix = { path = "crates/flix", version = "=0.0.4", default-features = false } -flix-tmdb = { path = "crates/tmdb", version = "=0.0.4", default-features = false } +flix = { path = "crates/flix", version = "=0.0.5", default-features = false } +flix-tmdb = { path = "crates/tmdb", version = "=0.0.5", default-features = false } anyhow = { version = "^1", default-features = false } chrono = { version = "^0.4", default-features = false } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index e15efe0..2bc34bd 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flix-cli" -version = "0.0.4" +version = "0.0.5" categories = ["command-line-utilities"] description = "CLI for interacting with flix media" diff --git a/crates/cli/src/cli/mod.rs b/crates/cli/src/cli/mod.rs index 8782a5f..d30f470 100644 --- a/crates/cli/src/cli/mod.rs +++ b/crates/cli/src/cli/mod.rs @@ -7,9 +7,9 @@ pub mod tmdb; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct Cli { - /// Use a custom config file [default: ~/.flix] - #[arg(short, long, value_name = "FILE")] - config: Option, + /// Use a custom config file + #[arg(short, long, value_name = "FILE", default_value = "~/.flix")] + config: PathBuf, #[command(subcommand)] command: Command, @@ -17,12 +17,9 @@ pub struct Cli { impl Cli { pub fn config_path(&self) -> PathBuf { - match self.config.as_ref() { - Some(path) => match path.strip_prefix("~/") { - Ok(path) => expect_home_dir().join(path), - Err(_) => path.to_owned(), - }, - None => expect_home_dir().join(".flix"), + match self.config.strip_prefix("~/") { + Ok(path) => expect_home_dir().join(path), + Err(_) => self.config.to_owned(), } } @@ -45,12 +42,18 @@ pub enum Command { force: bool, /// Change the destination - #[arg(short, long, value_name = "FILE")] - output: Option, + #[arg(short, long, value_name = "FILE", default_value = "flix.toml")] + output: PathBuf, #[command(subcommand)] command: BackendCommand, }, + /// Update a flix manifest + Update { + /// Change the destination + #[arg(short, long, value_name = "FILE", default_value = "flix.toml")] + output: PathBuf, + }, } #[derive(Subcommand)] @@ -62,6 +65,12 @@ pub enum BackendCommand { }, } +impl From for BackendCommand { + fn from(value: tmdb::Command) -> Self { + Self::Tmdb { command: value } + } +} + fn expect_home_dir() -> PathBuf { #[allow(clippy::expect_used)] home::home_dir().expect("you do not have a home directory") diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index ec2fe60..0125375 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -5,15 +5,16 @@ use flix_tmdb::Client; use anyhow::{Context, Result}; use clap::Parser; use tokio::fs; +use tokio::io::AsyncWriteExt; mod cli; use cli::{BackendCommand, Cli, Command}; mod config; use config::Config; -use tokio::io::AsyncWriteExt; mod run; +use run::flix::FlixObject; #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { @@ -27,41 +28,63 @@ async fn main() -> Result<()> { let client = Client::new(config.tmdb().bearer_token().to_owned()); match cli.command() { - Command::Print { command } => match command { - BackendCommand::Tmdb { command } => { - let object = run::tmdb::TmdbObject::fetch(&client, command).await?; - println!("{}", object.serialize().context("failed to serialize")?) - } - }, + Command::Print { command } => exec_print(client, command).await?, Command::Write { force, output, command, - } => match command { - BackendCommand::Tmdb { command } => { - let object = run::tmdb::TmdbObject::fetch(&client, command).await?; - let output = output - .as_ref() - .map(|p| p.as_path()) - .unwrap_or(Path::new("flix.toml")); - - let mut file = if *force { - fs::File::create(output).await - } else { - fs::File::create_new(output).await - } - .with_context(|| format!("could not create file at path {}", output.display()))?; - file.write_all( - object - .serialize() - .context("failed to serialize tmdb object")? - .as_bytes(), - ) - .await - .with_context(|| format!("could not write to file at path {}", output.display()))?; - } - }, + } => exec_write(client, *force, output, command).await?, + Command::Update { output } => exec_update(client, output).await?, } Ok(()) } + +async fn exec_print(client: Client, command: &BackendCommand) -> Result<()> { + match command { + BackendCommand::Tmdb { command } => { + let object = run::tmdb::TmdbObject::fetch(&client, command).await?; + println!("{}", object.serialize().context("failed to serialize")?) + } + } + Ok(()) +} + +async fn exec_write( + client: Client, + force: bool, + output: &Path, + command: &BackendCommand, +) -> Result<()> { + match command { + BackendCommand::Tmdb { command } => { + let object = run::tmdb::TmdbObject::fetch(&client, command).await?; + + let mut file = if force { + fs::File::create(output).await + } else { + fs::File::create_new(output).await + } + .with_context(|| format!("could not create file at path {}", output.display()))?; + file.write_all( + object + .serialize() + .context("failed to serialize tmdb object")? + .as_bytes(), + ) + .await + .with_context(|| format!("could not write to file at path {}", output.display()))?; + } + } + Ok(()) +} + +async fn exec_update(client: Client, output: &Path) -> Result<()> { + let content = fs::read_to_string(output) + .await + .with_context(|| format!("failed to read file at path: {}", output.display()))?; + let object: FlixObject = toml::from_str(&content).context("failed to deserialize flix file")?; + + let command = object.backend_command()?; + exec_write(client, true, output, &command).await +} diff --git a/crates/cli/src/run/flix.rs b/crates/cli/src/run/flix.rs new file mode 100644 index 0000000..efe8c77 --- /dev/null +++ b/crates/cli/src/run/flix.rs @@ -0,0 +1,68 @@ +use flix::model::{Collection, Episode, Movie, Season, Show, Verse}; + +use anyhow::{Result, bail}; + +use crate::cli::BackendCommand; +use crate::cli::tmdb; + +#[derive(Debug, serde::Deserialize)] +#[serde(untagged)] +pub enum FlixObject { + Collection(Collection), + Movie(Movie), + Show(Show), + Season(Season), + Episode(Episode), + // DEAD CODE: The TMDB backend does not support Verses + #[allow(dead_code)] + Verse(Verse), +} + +impl FlixObject { + pub fn backend_command(&self) -> Result { + Ok(match self { + FlixObject::Collection(collection) => { + let Some(ref tmdb) = collection.tmdb else { + bail!("missing tmdb data") + }; + tmdb::Command::Collection { id: tmdb.id.into() }.into() + } + FlixObject::Movie(movie) => { + let Some(ref tmdb) = movie.tmdb else { + bail!("missing tmdb data") + }; + tmdb::Command::Movie { id: tmdb.id.into() }.into() + } + FlixObject::Show(show) => { + let Some(ref tmdb) = show.tmdb else { + bail!("missing tmdb data") + }; + tmdb::Command::Show { id: tmdb.id.into() }.into() + } + FlixObject::Season(season) => { + let Some(ref tmdb) = season.tmdb else { + bail!("missing tmdb data") + }; + tmdb::Command::Season { + id: tmdb.show_id.into(), + season: season.season.number, + } + .into() + } + FlixObject::Episode(episode) => { + let Some(ref tmdb) = episode.tmdb else { + bail!("missing tmdb data") + }; + tmdb::Command::Episode { + id: tmdb.show_id.into(), + season: episode.episode.season, + episode: episode.episode.number, + } + .into() + } + FlixObject::Verse(_) => { + bail!("verses are not handled") + } + }) + } +} diff --git a/crates/cli/src/run/mod.rs b/crates/cli/src/run/mod.rs index 93cfeb6..9acb9e7 100644 --- a/crates/cli/src/run/mod.rs +++ b/crates/cli/src/run/mod.rs @@ -1 +1,2 @@ +pub mod flix; pub mod tmdb; diff --git a/crates/cli/src/run/tmdb.rs b/crates/cli/src/run/tmdb.rs index a03c510..ec915a3 100644 --- a/crates/cli/src/run/tmdb.rs +++ b/crates/cli/src/run/tmdb.rs @@ -1,11 +1,11 @@ use flix::model::{ Collection, Episode, GenericCollection, GenericEpisode, GenericMovie, GenericSeason, - GenericShow, Movie, Season, Show, TmdbCollection, TmdbMovie, TmdbShow, + GenericShow, Movie, Season, Show, TmdbCollection, TmdbEpisode, TmdbMovie, TmdbSeason, TmdbShow, }; use flix_tmdb::Client; use flix_tmdb::model::{ Collection as TCollection, Episode as TEpisode, Movie as TMovie, Season as TSeason, - Show as TShow, + Show as TShow, ShowId, }; use anyhow::{Context, Result}; @@ -16,8 +16,8 @@ pub enum TmdbObject { Collection(TCollection), Movie(TMovie), Show(TShow), - Season(TSeason), - Episode(TEpisode), + Season(TSeason, ShowId), + Episode(TEpisode, u32, ShowId), } impl TmdbObject { @@ -25,7 +25,7 @@ impl TmdbObject { Ok(match self { TmdbObject::Collection(tmdb) => toml::to_string(&Collection { collection: GenericCollection { - name: tmdb.name, + title: tmdb.title, overview: tmdb.overview, }, tmdb: Some(TmdbCollection { id: tmdb.id }), @@ -44,7 +44,7 @@ impl TmdbObject { })?, TmdbObject::Show(tmdb) => toml::to_string(&Show { show: GenericShow { - name: tmdb.name, + title: tmdb.title, overview: tmdb.overview, genres: tmdb.genres.iter().cloned().map(|g| g.name).collect(), air_date: tmdb.first_air_date, @@ -54,21 +54,24 @@ impl TmdbObject { genres: tmdb.genres.iter().map(|g| g.id).collect(), }), })?, - TmdbObject::Season(tmdb) => toml::to_string(&Season { + TmdbObject::Season(tmdb, show_id) => toml::to_string(&Season { season: GenericSeason { number: tmdb.season_number, - name: tmdb.name, + title: tmdb.title, overview: tmdb.overview, air_date: tmdb.air_date, }, + tmdb: Some(TmdbSeason { show_id }), })?, - TmdbObject::Episode(tmdb) => toml::to_string(&Episode { + TmdbObject::Episode(tmdb, season_number, show_id) => toml::to_string(&Episode { episode: GenericEpisode { number: tmdb.episode_number, - name: tmdb.name, + season: season_number, + title: tmdb.title, overview: tmdb.overview, air_date: tmdb.air_date, }, + tmdb: Some(TmdbEpisode { show_id }), })?, }) } @@ -104,6 +107,7 @@ impl TmdbObject { .get_details(id, season, None) .await .with_context(|| format!("could not get show details for '{id}' S{season}"))?, + id.into(), ), Command::Episode { id, @@ -117,6 +121,8 @@ impl TmdbObject { .with_context(|| { format!("could not get show details for '{id}' S{season}E{episode}") })?, + season, + id.into(), ), }) } diff --git a/crates/flix/Cargo.toml b/crates/flix/Cargo.toml index f551ff0..a0509f6 100644 --- a/crates/flix/Cargo.toml +++ b/crates/flix/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flix" -version = "0.0.4" +version = "0.0.5" categories = [] description = "Types for storing persistent data about media" diff --git a/crates/flix/src/model/collection.rs b/crates/flix/src/model/collection.rs index a3cc388..f8923b1 100644 --- a/crates/flix/src/model/collection.rs +++ b/crates/flix/src/model/collection.rs @@ -15,8 +15,8 @@ pub struct Collection { /// The generic collection data #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct GenericCollection { - /// The collection's name - pub name: String, + /// The collection's title + pub title: String, /// The collection's overview pub overview: String, } diff --git a/crates/flix/src/model/episode.rs b/crates/flix/src/model/episode.rs index e147beb..ce5e58e 100644 --- a/crates/flix/src/model/episode.rs +++ b/crates/flix/src/model/episode.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "tmdb")] +use flix_tmdb::model::ShowId; + use chrono::NaiveDate; /// An Episode container @@ -5,6 +8,10 @@ use chrono::NaiveDate; pub struct Episode { /// The generic episode data pub episode: GenericEpisode, + + /// The TMDB episode data + #[cfg(feature = "tmdb")] + pub tmdb: Option, } /// The generic episode data @@ -12,10 +19,20 @@ pub struct Episode { pub struct GenericEpisode { /// The episode's number pub number: u32, - /// The episode's name - pub name: String, + /// The episode's season's number + pub season: u32, + /// The episode's title + pub title: String, /// The episode's overview pub overview: String, /// The episode's air date pub air_date: NaiveDate, } + +/// The TMDB show data +#[cfg(feature = "tmdb")] +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct TmdbEpisode { + /// The episodes's show's TMDB ID + pub show_id: ShowId, +} diff --git a/crates/flix/src/model/season.rs b/crates/flix/src/model/season.rs index 7349ccf..56c614d 100644 --- a/crates/flix/src/model/season.rs +++ b/crates/flix/src/model/season.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "tmdb")] +use flix_tmdb::model::ShowId; + use chrono::NaiveDate; /// A Season container @@ -5,6 +8,10 @@ use chrono::NaiveDate; pub struct Season { /// The generic season data pub season: GenericSeason, + + /// The TMDB season data + #[cfg(feature = "tmdb")] + pub tmdb: Option, } /// The generic season data @@ -12,10 +19,18 @@ pub struct Season { pub struct GenericSeason { /// The season's number pub number: u32, - /// The season's name - pub name: String, + /// The season's title + pub title: String, /// The season's overview pub overview: String, /// The season's air date pub air_date: NaiveDate, } + +/// The TMDB show data +#[cfg(feature = "tmdb")] +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct TmdbSeason { + /// The season's show's TMDB ID + pub show_id: ShowId, +} diff --git a/crates/flix/src/model/show.rs b/crates/flix/src/model/show.rs index 711fd38..56e909e 100644 --- a/crates/flix/src/model/show.rs +++ b/crates/flix/src/model/show.rs @@ -17,8 +17,8 @@ pub struct Show { /// The generic show data #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct GenericShow { - /// The show's name - pub name: String, + /// The show's title + pub title: String, /// The show's overview pub overview: String, /// The show's genres diff --git a/crates/flix/src/model/verse.rs b/crates/flix/src/model/verse.rs index b1cd4b3..950b6e4 100644 --- a/crates/flix/src/model/verse.rs +++ b/crates/flix/src/model/verse.rs @@ -15,8 +15,8 @@ pub struct Verse { /// The generic verse data #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct GenericVerse { - /// The verse's name - pub name: String, + /// The verse's title + pub title: String, /// The verse's overview pub overview: String, } diff --git a/crates/tmdb/Cargo.toml b/crates/tmdb/Cargo.toml index 0f7e519..ec8f423 100644 --- a/crates/tmdb/Cargo.toml +++ b/crates/tmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flix-tmdb" -version = "0.0.4" +version = "0.0.5" categories = [] description = "Clients and models for fetching data from TMDB" diff --git a/crates/tmdb/src/model/collection.rs b/crates/tmdb/src/model/collection.rs index 2ca4476..ee37114 100644 --- a/crates/tmdb/src/model/collection.rs +++ b/crates/tmdb/src/model/collection.rs @@ -5,8 +5,9 @@ use super::{CollectionId, MovieId}; pub struct Collection { /// The collection's TMDB ID pub id: CollectionId, - /// The collection's name - pub name: String, + /// The collection's title + #[serde(rename = "name")] + pub title: String, /// The collection's overview pub overview: String, /// The list of movies that are part of this collection diff --git a/crates/tmdb/src/model/episode.rs b/crates/tmdb/src/model/episode.rs index a15ab5f..e14807e 100644 --- a/crates/tmdb/src/model/episode.rs +++ b/crates/tmdb/src/model/episode.rs @@ -5,8 +5,9 @@ use chrono::NaiveDate; pub struct Episode { /// The episode's number pub episode_number: u32, - /// The episode's name - pub name: String, + /// The episode's title + #[serde(rename = "name")] + pub title: String, /// The episode's overview pub overview: String, /// The episode's air date diff --git a/crates/tmdb/src/model/id.rs b/crates/tmdb/src/model/id.rs index 29a8ee0..961d176 100644 --- a/crates/tmdb/src/model/id.rs +++ b/crates/tmdb/src/model/id.rs @@ -1,4 +1,5 @@ use core::fmt; +use core::hash::{Hash, Hasher}; use core::marker::PhantomData; /// The TMDB ID type of a movie genre @@ -81,3 +82,9 @@ impl PartialEq for TmdbId { } impl Eq for TmdbId {} + +impl Hash for TmdbId { + fn hash(&self, state: &mut H) { + self.inner.hash(state); + } +} diff --git a/crates/tmdb/src/model/season.rs b/crates/tmdb/src/model/season.rs index a5f6ee7..c48a209 100644 --- a/crates/tmdb/src/model/season.rs +++ b/crates/tmdb/src/model/season.rs @@ -7,8 +7,9 @@ use super::Episode; pub struct Season { /// The season's number pub season_number: u32, - /// The season's name - pub name: String, + /// The season's title + #[serde(rename = "name")] + pub title: String, /// The season's overview pub overview: String, /// The season's air date diff --git a/crates/tmdb/src/model/show.rs b/crates/tmdb/src/model/show.rs index 57ebd3d..ddb712e 100644 --- a/crates/tmdb/src/model/show.rs +++ b/crates/tmdb/src/model/show.rs @@ -7,8 +7,9 @@ use super::{ShowGenre, ShowId}; pub struct Show { /// The show's TMDB ID pub id: ShowId, - /// The show's name - pub name: String, + /// The show's title + #[serde(rename = "name")] + pub title: String, /// The show's overview pub overview: String, /// The list of genres this show belongs to