feat: support cover art + resizing
This commit is contained in:
parent
07197a6703
commit
dc5fdf4b90
11 changed files with 566 additions and 15 deletions
254
Cargo.lock
generated
254
Cargo.lock
generated
|
|
@ -163,6 +163,18 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayref"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-attributes"
|
name = "async-attributes"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
|
@ -391,6 +403,12 @@ version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
|
@ -406,6 +424,19 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake3"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"constant_time_eq",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
@ -458,6 +489,12 @@ version = "3.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -574,6 +611,12 @@ dependencies = [
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
@ -595,6 +638,12 @@ version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -678,6 +727,30 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
|
@ -697,6 +770,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -884,6 +963,22 @@ version = "2.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exr"
|
||||||
|
version = "1.71.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"flume",
|
||||||
|
"half",
|
||||||
|
"lebe",
|
||||||
|
"miniz_oxide",
|
||||||
|
"rayon-core",
|
||||||
|
"smallvec",
|
||||||
|
"zune-inflate",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eyre"
|
name = "eyre"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
|
|
@ -909,6 +1004,15 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "findshlibs"
|
name = "findshlibs"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
|
@ -1124,6 +1228,16 @@ dependencies = [
|
||||||
"polyval",
|
"polyval",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
|
@ -1167,6 +1281,15 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
|
||||||
|
dependencies = [
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
|
@ -1410,6 +1533,25 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.24.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"exr",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"qoi",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indenter"
|
name = "indenter"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
|
@ -1497,6 +1639,15 @@ version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.64"
|
||||||
|
|
@ -1524,6 +1675,12 @@ dependencies = [
|
||||||
"spin 0.5.2",
|
"spin 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lebe"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.149"
|
version = "0.2.149"
|
||||||
|
|
@ -1615,6 +1772,15 @@ version = "2.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "metaflac"
|
name = "metaflac"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
|
@ -1663,6 +1829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1787,6 +1954,17 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
|
@ -2060,6 +2238,19 @@ version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poem"
|
name = "poem"
|
||||||
version = "1.3.58"
|
version = "1.3.58"
|
||||||
|
|
@ -2262,6 +2453,15 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qoi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.30.0"
|
version = "0.30.0"
|
||||||
|
|
@ -2316,10 +2516,12 @@ name = "rave"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"audiotags",
|
"audiotags",
|
||||||
|
"blake3",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"entities",
|
"entities",
|
||||||
"futures",
|
"futures",
|
||||||
|
"image",
|
||||||
"md5",
|
"md5",
|
||||||
"migration",
|
"migration",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -2340,6 +2542,26 @@ dependencies = [
|
||||||
"url-escape",
|
"url-escape",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "readme-rustdocifier"
|
name = "readme-rustdocifier"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -2993,6 +3215,12 @@ dependencies = [
|
||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
|
@ -3387,6 +3615,17 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.29"
|
version = "0.3.29"
|
||||||
|
|
@ -3944,6 +4183,12 @@ version = "0.25.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "whoami"
|
name = "whoami"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
|
@ -4071,3 +4316,12 @@ name = "zeroize"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zune-inflate"
|
||||||
|
version = "0.2.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
|
||||||
2
Justfile
2
Justfile
|
|
@ -10,7 +10,7 @@ unmount:
|
||||||
bash ./mount-tool.sh unmount
|
bash ./mount-tool.sh unmount
|
||||||
|
|
||||||
run: mount
|
run: mount
|
||||||
RAVE_STORAGE_DIR=/tmp/media-for-rave cargo r
|
RAVE_STORAGE_DIR=/tmp/media-for-rave RAVE_CACHE_DIR=/tmp/cache-for-rave cargo r
|
||||||
|
|
||||||
refresh:
|
refresh:
|
||||||
sea migrate fresh
|
sea migrate fresh
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ use serde::{Deserialize, Serialize};
|
||||||
#[sea_orm(table_name = "cover_art")]
|
#[sea_orm(table_name = "cover_art")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
|
pub hash: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,13 @@ impl MigrationTrait for Migration {
|
||||||
.if_not_exists()
|
.if_not_exists()
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(CoverArt::Id)
|
ColumnDef::new(CoverArt::Id)
|
||||||
.integer()
|
.big_integer()
|
||||||
.not_null()
|
.not_null()
|
||||||
.auto_increment()
|
.auto_increment()
|
||||||
.primary_key()
|
.primary_key()
|
||||||
.unique_key(),
|
.unique_key(),
|
||||||
)
|
)
|
||||||
|
.col(ColumnDef::new(CoverArt::Hash).string().not_null())
|
||||||
.col(ColumnDef::new(CoverArt::Path).string().not_null())
|
.col(ColumnDef::new(CoverArt::Path).string().not_null())
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
|
|
@ -36,5 +37,6 @@ impl MigrationTrait for Migration {
|
||||||
pub enum CoverArt {
|
pub enum CoverArt {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
|
Hash,
|
||||||
Path,
|
Path,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,3 +54,5 @@ sentry = { version = "0.31.7", default-features = false, features = [
|
||||||
"tracing",
|
"tracing",
|
||||||
] }
|
] }
|
||||||
sentry-tracing = { version = "0.31.7", features = ["backtrace"] }
|
sentry-tracing = { version = "0.31.7", features = ["backtrace"] }
|
||||||
|
blake3 = "1.5.0"
|
||||||
|
image = "0.24.7"
|
||||||
|
|
|
||||||
162
rave/src/rest/get_cover_art.rs
Normal file
162
rave/src/rest/get_cover_art.rs
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
use std::{io::Cursor, path::PathBuf};
|
||||||
|
|
||||||
|
use entities::prelude::CoverArt;
|
||||||
|
use poem::{
|
||||||
|
http::StatusCode,
|
||||||
|
web::{Data, Query},
|
||||||
|
IntoResponse, Response,
|
||||||
|
};
|
||||||
|
use poem_ext::db::DbTxn;
|
||||||
|
use sea_orm::EntityTrait;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tracing::{error, instrument};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
authentication::Authentication,
|
||||||
|
subsonic::{Error, SubsonicResponse},
|
||||||
|
utils::{self},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[poem::handler]
|
||||||
|
#[instrument(skip(txn, auth))]
|
||||||
|
pub async fn get_cover_art(
|
||||||
|
Data(txn): Data<&DbTxn>,
|
||||||
|
auth: Authentication,
|
||||||
|
Query(params): Query<GetCoverArtParams>,
|
||||||
|
) -> Response {
|
||||||
|
let u = utils::verify_user(txn.clone(), auth).await;
|
||||||
|
|
||||||
|
match u {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => return e.into_response(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let cover_art_id = match params.id.strip_prefix("ca-").ok_or_else(|| {
|
||||||
|
Error::RequiredParameterMissing(Some("Album IDs must be formatted as `ca-{}`".to_string()))
|
||||||
|
}) {
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(e) => return SubsonicResponse::new_error(e).into_response(),
|
||||||
|
};
|
||||||
|
let cover_art_id = match cover_art_id.parse::<i64>() {
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
error = &e as &dyn std::error::Error,
|
||||||
|
"Error parsing cover art ID: {e}"
|
||||||
|
);
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let cover_art = CoverArt::find_by_id(cover_art_id).one(&**txn).await;
|
||||||
|
|
||||||
|
let Ok(Some(cover_art)) = cover_art else {
|
||||||
|
match cover_art {
|
||||||
|
Ok(Some(_)) => unreachable!("Ok(Some(_)) covered by `let .. else`"),
|
||||||
|
Ok(None) => {
|
||||||
|
return SubsonicResponse::new_error(Error::RequestedDataWasNotFound(None))
|
||||||
|
.into_response()
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
error = &e as &dyn std::error::Error,
|
||||||
|
"Error getting album: {e}"
|
||||||
|
);
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = cover_art.path;
|
||||||
|
let path: PathBuf = path.into();
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
return SubsonicResponse::new_error(Error::RequestedDataWasNotFound(None)).into_response();
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = match tokio::fs::read(&path).await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
error = &e as &dyn std::error::Error,
|
||||||
|
"Error reading cover art file: {e}"
|
||||||
|
);
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ext = path
|
||||||
|
.extension()
|
||||||
|
.expect("File had no extension")
|
||||||
|
.to_str()
|
||||||
|
.expect("PathBuf extension is not valid UTF-8");
|
||||||
|
|
||||||
|
if params.size.is_none() {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.content_type(format!("image/{ext}"))
|
||||||
|
.body(data);
|
||||||
|
}
|
||||||
|
let size = params.size.expect("params.size.is_none() was false");
|
||||||
|
|
||||||
|
match size {
|
||||||
|
0.. => {}
|
||||||
|
..=-1 => {
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let image = match image::load_from_memory(&data) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
error = &e as &dyn std::error::Error,
|
||||||
|
"Error loading image from memory: {e}"
|
||||||
|
);
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
let resize = image.resize(
|
||||||
|
size as u32,
|
||||||
|
size as u32,
|
||||||
|
image::imageops::FilterType::Lanczos3,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buf = Cursor::new(Vec::new());
|
||||||
|
|
||||||
|
let res = resize.write_to(
|
||||||
|
&mut buf,
|
||||||
|
match ext {
|
||||||
|
"jpg" => image::ImageOutputFormat::Jpeg(100),
|
||||||
|
"png" => image::ImageOutputFormat::Png,
|
||||||
|
"gif" => image::ImageOutputFormat::Gif,
|
||||||
|
_ => {
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let () = match res {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
error = &e as &dyn std::error::Error,
|
||||||
|
"Error writing resized image to buffer: {e}"
|
||||||
|
);
|
||||||
|
return SubsonicResponse::new_error(Error::Generic(None)).into_response();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.content_type(format!("image/{ext}"))
|
||||||
|
.body(buf.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct GetCoverArtParams {
|
||||||
|
id: String,
|
||||||
|
size: Option<i32>,
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,8 @@ mod start_scan;
|
||||||
mod get_scan_status;
|
mod get_scan_status;
|
||||||
// rest/search3
|
// rest/search3
|
||||||
mod search3;
|
mod search3;
|
||||||
|
// rest/getCoverArt
|
||||||
|
mod get_cover_art;
|
||||||
|
|
||||||
pub fn build() -> Box<dyn Endpoint<Output = poem::Response>> {
|
pub fn build() -> Box<dyn Endpoint<Output = poem::Response>> {
|
||||||
Route::new()
|
Route::new()
|
||||||
|
|
@ -31,5 +33,6 @@ pub fn build() -> Box<dyn Endpoint<Output = poem::Response>> {
|
||||||
.at("/startScan", start_scan::start_scan)
|
.at("/startScan", start_scan::start_scan)
|
||||||
.at("/getScanStatus", get_scan_status::get_scan_status)
|
.at("/getScanStatus", get_scan_status::get_scan_status)
|
||||||
.at("/search3", search3::search3)
|
.at("/search3", search3::search3)
|
||||||
|
.at("/getCoverArt", get_cover_art::get_cover_art)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
use audiotags::MimeType;
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use entities::{
|
use entities::{
|
||||||
genre, music_folder,
|
cover_art, genre, music_folder,
|
||||||
prelude::{Genre, MusicFolder},
|
prelude::{CoverArt, Genre, MusicFolder},
|
||||||
};
|
};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
@ -14,7 +15,7 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use tokio::sync::RwLock;
|
use tokio::{io::AsyncWriteExt, sync::RwLock};
|
||||||
use tracing::{debug, error, info, instrument};
|
use tracing::{debug, error, info, instrument};
|
||||||
|
|
||||||
mod walk;
|
mod walk;
|
||||||
|
|
@ -390,7 +391,60 @@ fn get_root_dir() -> PathBuf {
|
||||||
PathBuf::from(root_dir)
|
PathBuf::from(root_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn get_cache_dir() -> PathBuf {
|
fn get_cache_dir() -> PathBuf {
|
||||||
// let cache_dir = std::env::var("RAVE_CACHE_DIR").expect("RAVE_CACHE_DIR not set");
|
let cache_dir = std::env::var("RAVE_CACHE_DIR").expect("RAVE_CACHE_DIR not set");
|
||||||
// PathBuf::from(cache_dir)
|
PathBuf::from(cache_dir)
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
async fn find_or_create_cover_art(
|
||||||
|
tx: &DatabaseTransaction,
|
||||||
|
data: &[u8],
|
||||||
|
mime_type: MimeType,
|
||||||
|
) -> Result<cover_art::Model, Report> {
|
||||||
|
let hash = blake3::hash(data).to_string();
|
||||||
|
|
||||||
|
debug!("Finding cover art with hash {hash}");
|
||||||
|
|
||||||
|
let res = CoverArt::find()
|
||||||
|
.filter(cover_art::Column::Hash.eq(&hash))
|
||||||
|
.one(tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(cover_art) = res {
|
||||||
|
return Ok(cover_art);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Trying to create cover art");
|
||||||
|
|
||||||
|
let path = get_cache_dir();
|
||||||
|
let path = path
|
||||||
|
.join(hash.clone())
|
||||||
|
.with_extension(mime_type_to_ext(mime_type));
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut file = tokio::fs::File::create(&path).await?;
|
||||||
|
file.write_all(data).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = path.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
let am = cover_art::ActiveModel {
|
||||||
|
hash: Set(hash.clone()),
|
||||||
|
path: Set(path),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let model = CoverArt::insert(am).exec_with_returning(tx).await;
|
||||||
|
|
||||||
|
Ok(model?)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn mime_type_to_ext(mime: MimeType) -> &'static str {
|
||||||
|
match mime {
|
||||||
|
MimeType::Png => "png",
|
||||||
|
MimeType::Jpeg => "jpg",
|
||||||
|
MimeType::Tiff => "tif",
|
||||||
|
MimeType::Bmp => "bmp",
|
||||||
|
MimeType::Gif => "gif",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use audiotags::{AudioTagEdit, FlacTag, Tag};
|
use audiotags::{AudioTagEdit, FlacTag, MimeType, Tag};
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use entities::{
|
use entities::{
|
||||||
album, artist,
|
album, artist,
|
||||||
|
|
@ -14,7 +14,7 @@ use sea_orm::{
|
||||||
};
|
};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::{fs::File, sync::RwLock};
|
use tokio::{fs::File, sync::RwLock};
|
||||||
use tracing::{debug, error, instrument};
|
use tracing::{debug, error, instrument, warn};
|
||||||
|
|
||||||
use super::ScanState;
|
use super::ScanState;
|
||||||
|
|
||||||
|
|
@ -67,6 +67,24 @@ pub async fn handle(
|
||||||
|
|
||||||
Set(duration)
|
Set(duration)
|
||||||
};
|
};
|
||||||
|
let cover_art = tag.album_cover();
|
||||||
|
if let Some(cover_art) = cover_art {
|
||||||
|
let data = match cover_art.mime_type {
|
||||||
|
MimeType::Png | MimeType::Jpeg | MimeType::Gif => Some(cover_art.data),
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unknown cover art mime type: {mime_type:?}",
|
||||||
|
mime_type = cover_art.mime_type
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(data) = data {
|
||||||
|
let cover_art = super::find_or_create_cover_art(tx, data, cover_art.mime_type).await?;
|
||||||
|
am.cover_art_id = Set(Some(cover_art.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
am.created = Set(OffsetDateTime::now_utc());
|
am.created = Set(OffsetDateTime::now_utc());
|
||||||
am.size = Set(meta
|
am.size = Set(meta
|
||||||
.len()
|
.len()
|
||||||
|
|
@ -122,6 +140,24 @@ async fn find_album(
|
||||||
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly
|
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly
|
||||||
.unwrap_or_default());
|
.unwrap_or_default());
|
||||||
am.created = Set(OffsetDateTime::now_utc());
|
am.created = Set(OffsetDateTime::now_utc());
|
||||||
|
let cover_art = tag.album_cover();
|
||||||
|
if let Some(cover_art) = cover_art {
|
||||||
|
let data = match cover_art.mime_type {
|
||||||
|
MimeType::Png | MimeType::Jpeg | MimeType::Gif => Some(cover_art.data),
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unknown cover art mime type: {mime_type:?}",
|
||||||
|
mime_type = cover_art.mime_type
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(data) = data {
|
||||||
|
let cover_art = super::find_or_create_cover_art(tx, data, cover_art.mime_type).await?;
|
||||||
|
am.cover_art_id = Set(Some(cover_art.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let model = Album::insert(am).exec_with_returning(tx).await;
|
let model = Album::insert(am).exec_with_returning(tx).await;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use audiotags::{AudioTagEdit, Id3v2Tag, Tag};
|
use audiotags::{AudioTagEdit, Id3v2Tag, MimeType, Tag};
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use entities::{
|
use entities::{
|
||||||
album, artist,
|
album, artist,
|
||||||
|
|
@ -14,7 +14,7 @@ use sea_orm::{
|
||||||
};
|
};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::{fs::File, sync::RwLock};
|
use tokio::{fs::File, sync::RwLock};
|
||||||
use tracing::{debug, error, instrument};
|
use tracing::{debug, error, instrument, warn};
|
||||||
|
|
||||||
use super::ScanState;
|
use super::ScanState;
|
||||||
|
|
||||||
|
|
@ -67,6 +67,24 @@ pub async fn handle(
|
||||||
|
|
||||||
Set(duration)
|
Set(duration)
|
||||||
};
|
};
|
||||||
|
let cover_art = tag.album_cover();
|
||||||
|
if let Some(cover_art) = cover_art {
|
||||||
|
let data = match cover_art.mime_type {
|
||||||
|
MimeType::Png | MimeType::Jpeg | MimeType::Gif => Some(cover_art.data),
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unknown cover art mime type: {mime_type:?}",
|
||||||
|
mime_type = cover_art.mime_type
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(data) = data {
|
||||||
|
let cover_art = super::find_or_create_cover_art(tx, data, cover_art.mime_type).await?;
|
||||||
|
am.cover_art_id = Set(Some(cover_art.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
am.created = Set(OffsetDateTime::now_utc());
|
am.created = Set(OffsetDateTime::now_utc());
|
||||||
am.size = Set(meta
|
am.size = Set(meta
|
||||||
.len()
|
.len()
|
||||||
|
|
@ -122,6 +140,24 @@ async fn find_album(
|
||||||
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly
|
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly
|
||||||
.unwrap_or_default());
|
.unwrap_or_default());
|
||||||
am.created = Set(OffsetDateTime::now_utc());
|
am.created = Set(OffsetDateTime::now_utc());
|
||||||
|
let cover_art = tag.album_cover();
|
||||||
|
if let Some(cover_art) = cover_art {
|
||||||
|
let data = match cover_art.mime_type {
|
||||||
|
MimeType::Png | MimeType::Jpeg | MimeType::Gif => Some(cover_art.data),
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"Unknown cover art mime type: {mime_type:?}",
|
||||||
|
mime_type = cover_art.mime_type
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(data) = data {
|
||||||
|
let cover_art = super::find_or_create_cover_art(tx, data, cover_art.mime_type).await?;
|
||||||
|
am.cover_art_id = Set(Some(cover_art.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let model = Album::insert(am).exec_with_returning(tx).await;
|
let model = Album::insert(am).exec_with_returning(tx).await;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ pub struct Artist {
|
||||||
pub starred: Option<String>,
|
pub starred: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
impl From<artist::Model> for Artist {
|
impl From<artist::Model> for Artist {
|
||||||
fn from(artist: artist::Model) -> Self {
|
fn from(artist: artist::Model) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: format!("ar-{}", artist.id),
|
id: format!("ar-{}", artist.id),
|
||||||
name: artist.name,
|
name: artist.name,
|
||||||
cover_art: artist.cover_art_id.map(|v| format!("ca-{}", v)),
|
cover_art: artist.cover_art_id.map(|v| format!("ca-{v}")),
|
||||||
artist_image_url: artist.artist_image_url,
|
artist_image_url: artist.artist_image_url,
|
||||||
album_count: artist.album_count as u64,
|
album_count: artist.album_count as u64,
|
||||||
starred: artist
|
starred: artist
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue