You've already forked AstralRinth
forked from didirus/AstralRinth
Project Colors (#512)
* Inital tests * Finish project colors * Run fmt + clippy + prepare * Fix dp+rp fmting
This commit is contained in:
6
.idea/sqldialects.xml
generated
6
.idea/sqldialects.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="SqlDialectMappings">
|
|
||||||
<file url="PROJECT" dialect="PostgreSQL" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
270
Cargo.lock
generated
270
Cargo.lock
generated
@@ -432,7 +432,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.5.4",
|
||||||
"object",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
@@ -464,6 +464,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -515,6 +521,12 @@ version = "3.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@@ -634,6 +646,21 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-thief"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6460d760cf38ce67c9e0318f896538820acc54f2d0a3bfc5b2c557211066c98"
|
||||||
|
dependencies = [
|
||||||
|
"rgb",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "1.2.4"
|
version = "1.2.4"
|
||||||
@@ -725,6 +752,30 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@@ -744,6 +795,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"
|
||||||
@@ -999,6 +1056,21 @@ 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.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8eb5f255b5980bb0c8cf676b675d1a99be40f316881444f44e0462eaf5df5ded"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"flume",
|
||||||
|
"half",
|
||||||
|
"lebe",
|
||||||
|
"miniz_oxide 0.6.2",
|
||||||
|
"smallvec",
|
||||||
|
"threadpool",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@@ -1015,7 +1087,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.5.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flume"
|
||||||
|
version = "0.10.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"nanorand",
|
||||||
|
"pin-project",
|
||||||
|
"spin 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1186,8 +1271,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1215,6 +1312,15 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554"
|
||||||
|
dependencies = [
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@@ -1430,6 +1536,25 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.24.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"exr",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"scoped_threadpool",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
@@ -1525,6 +1650,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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.60"
|
version = "0.3.60"
|
||||||
@@ -1549,6 +1683,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"censor",
|
"censor",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"color-thief",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@@ -1556,6 +1691,7 @@ dependencies = [
|
|||||||
"futures-timer",
|
"futures-timer",
|
||||||
"hex",
|
"hex",
|
||||||
"hmac 0.11.0",
|
"hmac 0.11.0",
|
||||||
|
"image",
|
||||||
"itertools 0.10.5",
|
"itertools 0.10.5",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@@ -1598,6 +1734,12 @@ version = "1.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lebe"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lexical-core"
|
name = "lexical-core"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@@ -1764,6 +1906,15 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.16"
|
version = "0.3.16"
|
||||||
@@ -1804,6 +1955,15 @@ dependencies = [
|
|||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -1816,6 +1976,15 @@ dependencies = [
|
|||||||
"windows-sys 0.42.0",
|
"windows-sys 0.42.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanorand"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@@ -1876,6 +2045,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.15"
|
version = "0.2.15"
|
||||||
@@ -2119,6 +2299,18 @@ version = "0.3.26"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"crc32fast",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide 0.6.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "2.4.0"
|
version = "2.4.0"
|
||||||
@@ -2220,6 +2412,28 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@@ -2317,6 +2531,15 @@ dependencies = [
|
|||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rgb"
|
||||||
|
version = "0.8.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
@@ -2326,7 +2549,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -2455,6 +2678,12 @@ dependencies = [
|
|||||||
"windows-sys 0.36.1",
|
"windows-sys 0.36.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped_threadpool"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -2802,6 +3031,15 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlformat"
|
name = "sqlformat"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -2994,6 +3232,26 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "threadpool"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
||||||
|
dependencies = [
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@@ -3474,6 +3732,12 @@ dependencies = [
|
|||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wepoll-ffi"
|
name = "wepoll-ffi"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|||||||
@@ -69,3 +69,6 @@ rust_decimal = { version = "1.26", features = ["serde-with-float", "serde-with-s
|
|||||||
|
|
||||||
sentry = "0.29.1"
|
sentry = "0.29.1"
|
||||||
sentry-actix = "0.29.1"
|
sentry-actix = "0.29.1"
|
||||||
|
|
||||||
|
image = "0.24.5"
|
||||||
|
color-thief = "0.2.2"
|
||||||
|
|||||||
2
migrations/20221227010515_project-colors.sql
Normal file
2
migrations/20221227010515_project-colors.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
ALTER TABLE mods ADD COLUMN color integer NULL;
|
||||||
2088
sqlx-data.json
2088
sqlx-data.json
File diff suppressed because it is too large
Load Diff
@@ -100,6 +100,7 @@ pub struct ProjectBuilder {
|
|||||||
pub slug: Option<String>,
|
pub slug: Option<String>,
|
||||||
pub donation_urls: Vec<DonationUrl>,
|
pub donation_urls: Vec<DonationUrl>,
|
||||||
pub gallery_items: Vec<GalleryItem>,
|
pub gallery_items: Vec<GalleryItem>,
|
||||||
|
pub color: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectBuilder {
|
impl ProjectBuilder {
|
||||||
@@ -137,6 +138,7 @@ impl ProjectBuilder {
|
|||||||
flame_anvil_project: None,
|
flame_anvil_project: None,
|
||||||
flame_anvil_user: None,
|
flame_anvil_user: None,
|
||||||
webhook_sent: false,
|
webhook_sent: false,
|
||||||
|
color: self.color,
|
||||||
};
|
};
|
||||||
project_struct.insert(&mut *transaction).await?;
|
project_struct.insert(&mut *transaction).await?;
|
||||||
|
|
||||||
@@ -213,6 +215,7 @@ pub struct Project {
|
|||||||
pub flame_anvil_project: Option<i32>,
|
pub flame_anvil_project: Option<i32>,
|
||||||
pub flame_anvil_user: Option<UserId>,
|
pub flame_anvil_user: Option<UserId>,
|
||||||
pub webhook_sent: bool,
|
pub webhook_sent: bool,
|
||||||
|
pub color: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
@@ -227,14 +230,14 @@ impl Project {
|
|||||||
published, downloads, icon_url, issues_url,
|
published, downloads, icon_url, issues_url,
|
||||||
source_url, wiki_url, status, requested_status, discord_url,
|
source_url, wiki_url, status, requested_status, discord_url,
|
||||||
client_side, server_side, license_url, license,
|
client_side, server_side, license_url, license,
|
||||||
slug, project_type
|
slug, project_type, color
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1, $2, $3, $4, $5,
|
$1, $2, $3, $4, $5,
|
||||||
$6, $7, $8, $9,
|
$6, $7, $8, $9,
|
||||||
$10, $11, $12, $13, $14,
|
$10, $11, $12, $13, $14,
|
||||||
$15, $16, $17, $18,
|
$15, $16, $17, $18,
|
||||||
LOWER($19), $20
|
LOWER($19), $20, $21
|
||||||
)
|
)
|
||||||
",
|
",
|
||||||
self.id as ProjectId,
|
self.id as ProjectId,
|
||||||
@@ -256,7 +259,8 @@ impl Project {
|
|||||||
self.license_url.as_ref(),
|
self.license_url.as_ref(),
|
||||||
&self.license,
|
&self.license,
|
||||||
self.slug.as_ref(),
|
self.slug.as_ref(),
|
||||||
self.project_type as ProjectTypeId
|
self.project_type as ProjectTypeId,
|
||||||
|
self.color.map(|x| x as i32)
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -279,7 +283,7 @@ impl Project {
|
|||||||
issues_url, source_url, wiki_url, discord_url, license_url,
|
issues_url, source_url, wiki_url, discord_url, license_url,
|
||||||
team_id, client_side, server_side, license, slug,
|
team_id, client_side, server_side, license, slug,
|
||||||
moderation_message, moderation_message_body, flame_anvil_project,
|
moderation_message, moderation_message_body, flame_anvil_project,
|
||||||
flame_anvil_user, webhook_sent
|
flame_anvil_user, webhook_sent, color
|
||||||
FROM mods
|
FROM mods
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
",
|
",
|
||||||
@@ -321,6 +325,7 @@ impl Project {
|
|||||||
flame_anvil_project: row.flame_anvil_project,
|
flame_anvil_project: row.flame_anvil_project,
|
||||||
flame_anvil_user: row.flame_anvil_user.map(UserId),
|
flame_anvil_user: row.flame_anvil_user.map(UserId),
|
||||||
webhook_sent: row.webhook_sent,
|
webhook_sent: row.webhook_sent,
|
||||||
|
color: row.color.map(|x| x as u32),
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -346,7 +351,7 @@ impl Project {
|
|||||||
issues_url, source_url, wiki_url, discord_url, license_url,
|
issues_url, source_url, wiki_url, discord_url, license_url,
|
||||||
team_id, client_side, server_side, license, slug,
|
team_id, client_side, server_side, license, slug,
|
||||||
moderation_message, moderation_message_body, flame_anvil_project,
|
moderation_message, moderation_message_body, flame_anvil_project,
|
||||||
flame_anvil_user, webhook_sent
|
flame_anvil_user, webhook_sent, color
|
||||||
FROM mods
|
FROM mods
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
",
|
",
|
||||||
@@ -388,6 +393,7 @@ impl Project {
|
|||||||
flame_anvil_project: m.flame_anvil_project,
|
flame_anvil_project: m.flame_anvil_project,
|
||||||
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
||||||
webhook_sent: m.webhook_sent,
|
webhook_sent: m.webhook_sent,
|
||||||
|
color: m.color.map(|x| x as u32),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<Project>>()
|
.try_collect::<Vec<Project>>()
|
||||||
@@ -666,7 +672,7 @@ impl Project {
|
|||||||
m.updated updated, m.approved approved, m.status status, m.requested_status requested_status,
|
m.updated updated, m.approved approved, m.status status, m.requested_status requested_status,
|
||||||
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
||||||
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
||||||
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.flame_anvil_project flame_anvil_project, m.flame_anvil_user flame_anvil_user, m.webhook_sent webhook_sent,
|
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.flame_anvil_project flame_anvil_project, m.flame_anvil_user flame_anvil_user, m.webhook_sent webhook_sent, m.color,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
||||||
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
||||||
@@ -725,6 +731,7 @@ impl Project {
|
|||||||
flame_anvil_project: m.flame_anvil_project,
|
flame_anvil_project: m.flame_anvil_project,
|
||||||
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
||||||
webhook_sent: m.webhook_sent,
|
webhook_sent: m.webhook_sent,
|
||||||
|
color: m.color.map(|x| x as u32),
|
||||||
},
|
},
|
||||||
project_type: m.project_type_name,
|
project_type: m.project_type_name,
|
||||||
categories: m.categories.unwrap_or_default(),
|
categories: m.categories.unwrap_or_default(),
|
||||||
@@ -794,7 +801,7 @@ impl Project {
|
|||||||
m.updated updated, m.approved approved, m.status status, m.requested_status requested_status,
|
m.updated updated, m.approved approved, m.status status, m.requested_status requested_status,
|
||||||
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
||||||
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
||||||
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.flame_anvil_project flame_anvil_project, m.flame_anvil_user flame_anvil_user, m.webhook_sent,
|
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.flame_anvil_project flame_anvil_project, m.flame_anvil_user flame_anvil_user, m.webhook_sent, m.color,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
||||||
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
||||||
@@ -856,6 +863,7 @@ impl Project {
|
|||||||
flame_anvil_project: m.flame_anvil_project,
|
flame_anvil_project: m.flame_anvil_project,
|
||||||
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
||||||
webhook_sent: m.webhook_sent,
|
webhook_sent: m.webhook_sent,
|
||||||
|
color: m.color.map(|x| x as u32),
|
||||||
},
|
},
|
||||||
project_type: m.project_type_name,
|
project_type: m.project_type_name,
|
||||||
categories: m.categories.unwrap_or_default(),
|
categories: m.categories.unwrap_or_default(),
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ pub struct Project {
|
|||||||
pub flame_anvil_project: Option<i32>,
|
pub flame_anvil_project: Option<i32>,
|
||||||
/// The user_id of the team member whose token
|
/// The user_id of the team member whose token
|
||||||
pub flame_anvil_user: Option<UserId>,
|
pub flame_anvil_user: Option<UserId>,
|
||||||
|
|
||||||
|
/// The color of the project (picked from icon)
|
||||||
|
pub color: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<QueryProject> for Project {
|
impl From<QueryProject> for Project {
|
||||||
@@ -181,6 +184,7 @@ impl From<QueryProject> for Project {
|
|||||||
.collect(),
|
.collect(),
|
||||||
flame_anvil_project: m.flame_anvil_project,
|
flame_anvil_project: m.flame_anvil_project,
|
||||||
flame_anvil_user: m.flame_anvil_user.map(|x| x.into()),
|
flame_anvil_user: m.flame_anvil_user.map(|x| x.into()),
|
||||||
|
color: m.color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ pub use self::index::index_get;
|
|||||||
pub use self::not_found::not_found;
|
pub use self::not_found::not_found;
|
||||||
use crate::file_hosting::FileHostingError;
|
use crate::file_hosting::FileHostingError;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
|
use image::ImageError;
|
||||||
|
|
||||||
pub fn v2_config(cfg: &mut web::ServiceConfig) {
|
pub fn v2_config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(
|
cfg.service(
|
||||||
@@ -230,6 +231,8 @@ pub enum ApiError {
|
|||||||
DiscordError(String),
|
DiscordError(String),
|
||||||
#[error("Error while decoding Base62: {0}")]
|
#[error("Error while decoding Base62: {0}")]
|
||||||
Decoding(#[from] crate::models::ids::DecodingError),
|
Decoding(#[from] crate::models::ids::DecodingError),
|
||||||
|
#[error("Image Parsing Error: {0}")]
|
||||||
|
ImageError(#[from] ImageError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl actix_web::ResponseError for ApiError {
|
impl actix_web::ResponseError for ApiError {
|
||||||
@@ -280,6 +283,9 @@ impl actix_web::ResponseError for ApiError {
|
|||||||
actix_web::http::StatusCode::FAILED_DEPENDENCY
|
actix_web::http::StatusCode::FAILED_DEPENDENCY
|
||||||
}
|
}
|
||||||
ApiError::Decoding(..) => actix_web::http::StatusCode::BAD_REQUEST,
|
ApiError::Decoding(..) => actix_web::http::StatusCode::BAD_REQUEST,
|
||||||
|
ApiError::ImageError(..) => {
|
||||||
|
actix_web::http::StatusCode::BAD_REQUEST
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +310,7 @@ impl actix_web::ResponseError for ApiError {
|
|||||||
ApiError::Payments(..) => "payments_error",
|
ApiError::Payments(..) => "payments_error",
|
||||||
ApiError::DiscordError(..) => "discord_error",
|
ApiError::DiscordError(..) => "discord_error",
|
||||||
ApiError::Decoding(..) => "decoding_error",
|
ApiError::Decoding(..) => "decoding_error",
|
||||||
|
ApiError::ImageError(..) => "invalid_image",
|
||||||
},
|
},
|
||||||
description: &self.to_string(),
|
description: &self.to_string(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use actix_web::web::Data;
|
|||||||
use actix_web::{post, HttpRequest, HttpResponse};
|
use actix_web::{post, HttpRequest, HttpResponse};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
use image::ImageError;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
@@ -65,6 +66,8 @@ pub enum CreateError {
|
|||||||
Unauthorized(#[from] AuthenticationError),
|
Unauthorized(#[from] AuthenticationError),
|
||||||
#[error("Authentication Error: {0}")]
|
#[error("Authentication Error: {0}")]
|
||||||
CustomAuthenticationError(String),
|
CustomAuthenticationError(String),
|
||||||
|
#[error("Image Parsing Error: {0}")]
|
||||||
|
ImageError(#[from] ImageError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl actix_web::ResponseError for CreateError {
|
impl actix_web::ResponseError for CreateError {
|
||||||
@@ -95,6 +98,7 @@ impl actix_web::ResponseError for CreateError {
|
|||||||
CreateError::SlugCollision => StatusCode::BAD_REQUEST,
|
CreateError::SlugCollision => StatusCode::BAD_REQUEST,
|
||||||
CreateError::ValidationError(..) => StatusCode::BAD_REQUEST,
|
CreateError::ValidationError(..) => StatusCode::BAD_REQUEST,
|
||||||
CreateError::FileValidationError(..) => StatusCode::BAD_REQUEST,
|
CreateError::FileValidationError(..) => StatusCode::BAD_REQUEST,
|
||||||
|
CreateError::ImageError(..) => StatusCode::BAD_REQUEST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +124,7 @@ impl actix_web::ResponseError for CreateError {
|
|||||||
CreateError::SlugCollision => "invalid_input",
|
CreateError::SlugCollision => "invalid_input",
|
||||||
CreateError::ValidationError(..) => "invalid_input",
|
CreateError::ValidationError(..) => "invalid_input",
|
||||||
CreateError::FileValidationError(..) => "invalid_input",
|
CreateError::FileValidationError(..) => "invalid_input",
|
||||||
|
CreateError::ImageError(..) => "invalid_image",
|
||||||
},
|
},
|
||||||
description: &self.to_string(),
|
description: &self.to_string(),
|
||||||
})
|
})
|
||||||
@@ -468,7 +473,7 @@ pub async fn project_create_inner(
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut icon_url = None;
|
let mut icon_data = None;
|
||||||
|
|
||||||
while let Some(item) = payload.next().await {
|
while let Some(item) = payload.next().await {
|
||||||
let mut field: Field = item.map_err(CreateError::MultipartError)?;
|
let mut field: Field = item.map_err(CreateError::MultipartError)?;
|
||||||
@@ -482,13 +487,13 @@ pub async fn project_create_inner(
|
|||||||
super::version_creation::get_name_ext(&content_disposition)?;
|
super::version_creation::get_name_ext(&content_disposition)?;
|
||||||
|
|
||||||
if name == "icon" {
|
if name == "icon" {
|
||||||
if icon_url.is_some() {
|
if icon_data.is_some() {
|
||||||
return Err(CreateError::InvalidInput(String::from(
|
return Err(CreateError::InvalidInput(String::from(
|
||||||
"Projects can only have one icon",
|
"Projects can only have one icon",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// Upload the icon to the cdn
|
// Upload the icon to the cdn
|
||||||
icon_url = Some(
|
icon_data = Some(
|
||||||
process_icon_upload(
|
process_icon_upload(
|
||||||
uploaded_files,
|
uploaded_files,
|
||||||
project_id,
|
project_id,
|
||||||
@@ -731,7 +736,7 @@ pub async fn project_create_inner(
|
|||||||
title: project_create_data.title,
|
title: project_create_data.title,
|
||||||
description: project_create_data.description,
|
description: project_create_data.description,
|
||||||
body: project_create_data.body,
|
body: project_create_data.body,
|
||||||
icon_url,
|
icon_url: icon_data.clone().map(|x| x.0),
|
||||||
issues_url: project_create_data.issues_url,
|
issues_url: project_create_data.issues_url,
|
||||||
source_url: project_create_data.source_url,
|
source_url: project_create_data.source_url,
|
||||||
wiki_url: project_create_data.wiki_url,
|
wiki_url: project_create_data.wiki_url,
|
||||||
@@ -759,6 +764,7 @@ pub async fn project_create_inner(
|
|||||||
ordering: x.ordering,
|
ordering: x.ordering,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
color: icon_data.and_then(|x| x.1),
|
||||||
};
|
};
|
||||||
|
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
@@ -803,6 +809,7 @@ pub async fn project_create_inner(
|
|||||||
gallery: gallery_urls,
|
gallery: gallery_urls,
|
||||||
flame_anvil_project: None,
|
flame_anvil_project: None,
|
||||||
flame_anvil_user: None,
|
flame_anvil_user: None,
|
||||||
|
color: project_builder.color,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _project_id = project_builder.insert(&mut *transaction).await?;
|
let _project_id = project_builder.insert(&mut *transaction).await?;
|
||||||
@@ -911,9 +918,9 @@ async fn process_icon_upload(
|
|||||||
project_id: ProjectId,
|
project_id: ProjectId,
|
||||||
file_extension: &str,
|
file_extension: &str,
|
||||||
file_host: &dyn FileHost,
|
file_host: &dyn FileHost,
|
||||||
mut field: actix_multipart::Field,
|
mut field: Field,
|
||||||
cdn_url: &str,
|
cdn_url: &str,
|
||||||
) -> Result<String, CreateError> {
|
) -> Result<(String, Option<u32>), CreateError> {
|
||||||
if let Some(content_type) =
|
if let Some(content_type) =
|
||||||
crate::util::ext::get_image_content_type(file_extension)
|
crate::util::ext::get_image_content_type(file_extension)
|
||||||
{
|
{
|
||||||
@@ -924,6 +931,8 @@ async fn process_icon_upload(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let color = crate::util::img::get_color_from_img(&data)?;
|
||||||
|
|
||||||
let hash = sha1::Sha1::from(&data).hexdigest();
|
let hash = sha1::Sha1::from(&data).hexdigest();
|
||||||
let upload_data = file_host
|
let upload_data = file_host
|
||||||
.upload_file(
|
.upload_file(
|
||||||
@@ -938,7 +947,7 @@ async fn process_icon_upload(
|
|||||||
file_name: upload_data.file_name.clone(),
|
file_name: upload_data.file_name.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(format!("{}/{}", cdn_url, upload_data.file_name))
|
Ok((format!("{}/{}", cdn_url, upload_data.file_name), color))
|
||||||
} else {
|
} else {
|
||||||
Err(CreateError::InvalidIconFormat(file_extension.to_string()))
|
Err(CreateError::InvalidIconFormat(file_extension.to_string()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1288,6 +1288,9 @@ pub async fn project_icon_edit(
|
|||||||
"Icons must be smaller than 256KiB",
|
"Icons must be smaller than 256KiB",
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let color = crate::util::img::get_color_from_img(&bytes)?;
|
||||||
|
|
||||||
let hash = sha1::Sha1::from(&bytes).hexdigest();
|
let hash = sha1::Sha1::from(&bytes).hexdigest();
|
||||||
let project_id: ProjectId = project_item.id.into();
|
let project_id: ProjectId = project_item.id.into();
|
||||||
let upload_data = file_host
|
let upload_data = file_host
|
||||||
@@ -1303,10 +1306,11 @@ pub async fn project_icon_edit(
|
|||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE mods
|
UPDATE mods
|
||||||
SET icon_url = $1
|
SET icon_url = $1, color = $2
|
||||||
WHERE (id = $2)
|
WHERE (id = $3)
|
||||||
",
|
",
|
||||||
format!("{}/{}", cdn_url, upload_data.file_name),
|
format!("{}/{}", cdn_url, upload_data.file_name),
|
||||||
|
color.map(|x| x as i32),
|
||||||
project_item.id as database::models::ids::ProjectId,
|
project_item.id as database::models::ids::ProjectId,
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
@@ -1379,7 +1383,7 @@ pub async fn delete_project_icon(
|
|||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE mods
|
UPDATE mods
|
||||||
SET icon_url = NULL
|
SET icon_url = NULL, color = NULL
|
||||||
WHERE (id = $1)
|
WHERE (id = $1)
|
||||||
",
|
",
|
||||||
project_item.id as database::models::ids::ProjectId,
|
project_item.id as database::models::ids::ProjectId,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub async fn index_local(
|
|||||||
"
|
"
|
||||||
SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,
|
SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,
|
||||||
m.icon_url icon_url, m.published published, m.approved approved, m.updated updated,
|
m.icon_url icon_url, m.published published, m.approved approved, m.updated updated,
|
||||||
m.team_id team_id, m.license license, m.slug slug, m.status status_name,
|
m.team_id team_id, m.license license, m.slug slug, m.status status_name, m.color color,
|
||||||
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, u.username username,
|
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, u.username username,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
||||||
@@ -96,6 +96,7 @@ pub async fn index_local(
|
|||||||
gallery,
|
gallery,
|
||||||
display_categories,
|
display_categories,
|
||||||
open_source,
|
open_source,
|
||||||
|
color: m.color.map(|x| x as u32),
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pub struct UploadSearchProject {
|
|||||||
/// Unix timestamp of the last major modification
|
/// Unix timestamp of the last major modification
|
||||||
pub modified_timestamp: i64,
|
pub modified_timestamp: i64,
|
||||||
pub open_source: bool,
|
pub open_source: bool,
|
||||||
|
pub color: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@@ -132,6 +133,7 @@ pub struct ResultSearchProject {
|
|||||||
pub client_side: String,
|
pub client_side: String,
|
||||||
pub server_side: String,
|
pub server_side: String,
|
||||||
pub gallery: Vec<String>,
|
pub gallery: Vec<String>,
|
||||||
|
pub color: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Document for UploadSearchProject {
|
impl Document for UploadSearchProject {
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ pub fn get_image_content_type(extension: &str) -> Option<&'static str> {
|
|||||||
match extension {
|
match extension {
|
||||||
"bmp" => Some("image/bmp"),
|
"bmp" => Some("image/bmp"),
|
||||||
"gif" => Some("image/gif"),
|
"gif" => Some("image/gif"),
|
||||||
"jpeg" | "jpg" | "jpe" => Some("image/jpeg"),
|
"jpeg" | "jpg" => Some("image/jpeg"),
|
||||||
"png" => Some("image/png"),
|
"png" => Some("image/png"),
|
||||||
"svg" | "svgz" => Some("image/svg+xml"),
|
|
||||||
"webp" => Some("image/webp"),
|
"webp" => Some("image/webp"),
|
||||||
"rgb" => Some("image/x-rgb"),
|
|
||||||
"mp4" => Some("video/mp4"),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/util/img.rs
Normal file
19
src/util/img.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use color_thief::ColorFormat;
|
||||||
|
use image::imageops::FilterType;
|
||||||
|
use image::{EncodableLayout, ImageError};
|
||||||
|
|
||||||
|
pub fn get_color_from_img(data: &[u8]) -> Result<Option<u32>, ImageError> {
|
||||||
|
let image =
|
||||||
|
image::load_from_memory(data)?.resize(256, 256, FilterType::Nearest);
|
||||||
|
let color = color_thief::get_palette(
|
||||||
|
image.to_rgb8().as_bytes(),
|
||||||
|
ColorFormat::Rgb,
|
||||||
|
10,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.and_then(|x| x.get(0).copied())
|
||||||
|
.map(|x| (x.r as u32) << 16 | (x.g as u32) << 8 | (x.b as u32));
|
||||||
|
|
||||||
|
Ok(color)
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ pub mod auth;
|
|||||||
pub mod env;
|
pub mod env;
|
||||||
pub mod ext;
|
pub mod ext;
|
||||||
pub mod guards;
|
pub mod guards;
|
||||||
|
pub mod img;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
pub mod validate;
|
pub mod validate;
|
||||||
pub mod webhook;
|
pub mod webhook;
|
||||||
|
|||||||
@@ -157,7 +157,13 @@ pub async fn send_discord_webhook(
|
|||||||
_ => 1049805243866681424,
|
_ => 1049805243866681424,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut x = loader.clone();
|
let mut x = if loader == "datapack" {
|
||||||
|
"Data Pack"
|
||||||
|
} else {
|
||||||
|
loader
|
||||||
|
}
|
||||||
|
.to_string();
|
||||||
|
|
||||||
formatted_loaders.push_str(&format!(
|
formatted_loaders.push_str(&format!(
|
||||||
"<:{loader}:{emoji_id}> {}{x}\n",
|
"<:{loader}:{emoji_id}> {}{x}\n",
|
||||||
x.remove(0).to_uppercase()
|
x.remove(0).to_uppercase()
|
||||||
@@ -190,6 +196,13 @@ pub async fn send_discord_webhook(
|
|||||||
project_type = "datapack".to_string();
|
project_type = "datapack".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut display_project_type = match &*project_type {
|
||||||
|
"datapack" => "data pack",
|
||||||
|
"resourcepack" => "resource pack",
|
||||||
|
_ => &*project_type,
|
||||||
|
}
|
||||||
|
.to_string();
|
||||||
|
|
||||||
let embed = DiscordEmbed {
|
let embed = DiscordEmbed {
|
||||||
author: Some(DiscordEmbedAuthor {
|
author: Some(DiscordEmbedAuthor {
|
||||||
name: project.username.clone(),
|
name: project.username.clone(),
|
||||||
@@ -224,8 +237,8 @@ pub async fn send_discord_webhook(
|
|||||||
.map(|x| DiscordEmbedImage { url: Some(x) }),
|
.map(|x| DiscordEmbedImage { url: Some(x) }),
|
||||||
footer: Some(DiscordEmbedFooter {
|
footer: Some(DiscordEmbedFooter {
|
||||||
text: format!(
|
text: format!(
|
||||||
"{}{project_type} on Modrinth",
|
"{}{display_project_type} on Modrinth",
|
||||||
project_type.remove(0).to_uppercase()
|
display_project_type.remove(0).to_uppercase()
|
||||||
),
|
),
|
||||||
icon_url: Some(
|
icon_url: Some(
|
||||||
"https://cdn-raw.modrinth.com/modrinth-new.png".to_string(),
|
"https://cdn-raw.modrinth.com/modrinth-new.png".to_string(),
|
||||||
|
|||||||
Reference in New Issue
Block a user