some small refactoring
This commit is contained in:
parent
dd7c66a13b
commit
e591b11065
20 changed files with 957 additions and 40 deletions
246
Cargo.lock
generated
246
Cargo.lock
generated
|
@ -190,6 +190,25 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -352,6 +371,18 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.27"
|
version = "1.0.27"
|
||||||
|
@ -368,6 +399,15 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.28"
|
||||||
|
@ -443,8 +483,10 @@ dependencies = [
|
||||||
"flate2",
|
"flate2",
|
||||||
"maplit",
|
"maplit",
|
||||||
"password-auth",
|
"password-auth",
|
||||||
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"rocket",
|
"rocket",
|
||||||
|
"rocket_dyn_templates",
|
||||||
"serde",
|
"serde",
|
||||||
"sha",
|
"sha",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -511,6 +553,20 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "handlebars"
|
||||||
|
version = "4.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
@ -614,6 +670,26 @@ version = "0.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
@ -640,6 +716,26 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||||
|
dependencies = [
|
||||||
|
"kqueue-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue-sys"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -757,6 +853,33 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "normpath"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify"
|
||||||
|
version = "5.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"filetime",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
@ -864,6 +987,51 @@ version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"thiserror",
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_derive"
|
||||||
|
version = "2.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_generator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_generator"
|
||||||
|
version = "2.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_meta",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_meta"
|
||||||
|
version = "2.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"pest",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
|
@ -1079,6 +1247,19 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rocket_dyn_templates"
|
||||||
|
version = "0.1.0-rc.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "276cac97fcddca93d741a4a530f58969f45a5bdb587f8c6b04c75cf849ca7f4c"
|
||||||
|
dependencies = [
|
||||||
|
"glob",
|
||||||
|
"handlebars",
|
||||||
|
"normpath",
|
||||||
|
"notify",
|
||||||
|
"rocket",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rocket_http"
|
name = "rocket_http"
|
||||||
version = "0.5.0-rc.3"
|
version = "0.5.0-rc.3"
|
||||||
|
@ -1131,6 +1312,15 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -1192,6 +1382,17 @@ dependencies = [
|
||||||
"bswap",
|
"bswap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -1289,6 +1490,26 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.7"
|
version = "1.1.7"
|
||||||
|
@ -1504,6 +1725,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uncased"
|
name = "uncased"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
|
@ -1544,6 +1771,16 @@ version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1629,6 +1866,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -10,8 +10,10 @@ dotenvy = "0.15.7"
|
||||||
flate2 = "1.0.27"
|
flate2 = "1.0.27"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
password-auth = "0.3.0"
|
password-auth = "0.3.0"
|
||||||
|
rand = "0.8.5"
|
||||||
regex = "1.9.4"
|
regex = "1.9.4"
|
||||||
rocket = "=0.5.0-rc.3"
|
rocket = "=0.5.0-rc.3"
|
||||||
|
rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] }
|
||||||
serde = { version = "1.0.188", features = ["derive"] }
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
sha = "1.0.3"
|
sha = "1.0.3"
|
||||||
toml = "0.7.6"
|
toml = "0.7.6"
|
||||||
|
|
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 478 B |
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
45
public/style.css
Normal file
45
public/style.css
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
|
||||||
|
font-family: system-ui;
|
||||||
|
|
||||||
|
background-color: #1e1e2e;
|
||||||
|
color: #cdd6f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
display: inline;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #89b4fa;
|
||||||
|
}
|
14
readme.md
14
readme.md
|
@ -35,9 +35,11 @@ _these features are implemented_
|
||||||
## todo
|
## todo
|
||||||
|
|
||||||
- swap to chrono instead of `(TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.MS'))` (thats REALLY ugly!!)
|
- swap to chrono instead of `(TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.MS'))` (thats REALLY ugly!!)
|
||||||
- patch `upload_level` and `download_level` to use friends only unlisted we get social shit (friends only stuff)
|
- 2.2 friends only unlisted
|
||||||
- in our level parsing, check for dual portals rather than just starting dual
|
- add more old endpoints + better support for older versions
|
||||||
- instead of panicking for a lot of things return -1
|
- add dailies, events, weekly
|
||||||
- <small>green name users...</small>
|
- add defaults to more parameters
|
||||||
- add more old endpoints
|
- better way for checking if song is custom (currently `id > 50`)
|
||||||
- better support for older versions
|
- sqlite would make sense for this
|
||||||
|
- unscuff difficulties
|
||||||
|
- moderation utilities
|
|
@ -130,7 +130,7 @@ pub struct NewLevel {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub original: i32,
|
pub original: Option<i32>,
|
||||||
pub game_version: i32,
|
pub game_version: i32,
|
||||||
pub binary_version: i32,
|
pub binary_version: i32,
|
||||||
pub password: Option<String>,
|
pub password: Option<String>,
|
||||||
|
|
|
@ -31,7 +31,6 @@ pub fn update_account_settings(input: Form<FormUpdateAccountSettings>) -> status
|
||||||
// account verification
|
// account verification
|
||||||
let (_user_id_val, account_id_val): (i32, i32);
|
let (_user_id_val, account_id_val): (i32, i32);
|
||||||
|
|
||||||
// password argument is used for the level, so
|
|
||||||
match helpers::accounts::auth(input.accountID.clone(), input.password.clone(), input.gjp.clone(), input.gjp2.clone()) {
|
match helpers::accounts::auth(input.accountID.clone(), input.password.clone(), input.gjp.clone(), input.gjp2.clone()) {
|
||||||
Ok((user_id, account_id)) => {
|
Ok((user_id, account_id)) => {
|
||||||
_user_id_val = user_id;
|
_user_id_val = user_id;
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
pub mod get_levels;
|
||||||
pub mod upload_level;
|
pub mod upload_level;
|
439
src/endpoints/levels/get_levels.rs
Normal file
439
src/endpoints/levels/get_levels.rs
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
use rocket::form::Form;
|
||||||
|
use rocket::http::Status;
|
||||||
|
use rocket::response::status;
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
use base64::{Engine as _, engine::general_purpose};
|
||||||
|
|
||||||
|
use crate::helpers;
|
||||||
|
use crate::db;
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
pub struct FormGetLevels {
|
||||||
|
page: i64,
|
||||||
|
str: String,
|
||||||
|
|
||||||
|
accountID: Option<i32>,
|
||||||
|
gjp: Option<String>,
|
||||||
|
gjp2: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
|
|
||||||
|
// we have to escape here
|
||||||
|
r#type: Option<i32>,
|
||||||
|
featured: Option<i32>,
|
||||||
|
original: Option<i32>,
|
||||||
|
coins: Option<i32>,
|
||||||
|
epic: Option<i32>,
|
||||||
|
uncompleted: Option<i32>,
|
||||||
|
onlyCompleted: Option<i32>,
|
||||||
|
completedLevels: Option<String>,
|
||||||
|
song: Option<i32>,
|
||||||
|
customSong: Option<i32>,
|
||||||
|
twoPlayer: Option<i32>,
|
||||||
|
star: Option<i32>,
|
||||||
|
noStar: Option<i32>,
|
||||||
|
gauntlet: Option<i32>,
|
||||||
|
len: Option<i32>,
|
||||||
|
diff: Option<String>,
|
||||||
|
demonFilter: Option<i32>,
|
||||||
|
local: Option<i32>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/getGJLevels20.php", data = "<input>")]
|
||||||
|
pub fn get_levels(input: Form<FormGetLevels>) -> status::Custom<&'static str> {
|
||||||
|
let connection = &mut db::establish_connection_pg();
|
||||||
|
|
||||||
|
use crate::schema::{levels, users};
|
||||||
|
|
||||||
|
use crate::models::{Level, User};
|
||||||
|
|
||||||
|
let mut can_see_unlisted = false;
|
||||||
|
|
||||||
|
let mut query = levels::table.into_boxed();
|
||||||
|
let mut count_query = levels::table.into_boxed();
|
||||||
|
|
||||||
|
if input.str != "" && input.r#type != Some(5) && input.r#type != Some(10) && input.r#type != Some(19) {
|
||||||
|
match input.str.parse::<i32>() {
|
||||||
|
Ok(matched_id) => {
|
||||||
|
can_see_unlisted = true;
|
||||||
|
query = query.filter(levels::id.eq(matched_id));
|
||||||
|
count_query = count_query.filter(levels::id.eq(matched_id))
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
query = query.filter(levels::name.ilike(input.str.to_owned() + "%"));
|
||||||
|
count_query = count_query.filter(levels::name.ilike(input.str.to_owned() + "%"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(1) = input.featured {
|
||||||
|
query = query.filter(levels::featured.eq(1));
|
||||||
|
count_query = count_query.filter(levels::featured.eq(1))
|
||||||
|
}
|
||||||
|
if let Some(1) = input.original {
|
||||||
|
query = query.filter(levels::original.is_null());
|
||||||
|
count_query = count_query.filter(levels::original.is_null())
|
||||||
|
}
|
||||||
|
if let Some(1) = input.coins {
|
||||||
|
query = query.filter(levels::rated_coins.eq(1).and(levels::coins.ne(0)));
|
||||||
|
count_query = count_query.filter(levels::rated_coins.eq(1).and(levels::coins.ne(0)))
|
||||||
|
}
|
||||||
|
if let Some(1) = input.epic {
|
||||||
|
query = query.filter(levels::epic.eq(1));
|
||||||
|
count_query = count_query.filter(levels::epic.eq(1))
|
||||||
|
}
|
||||||
|
if let Some(1) = input.uncompleted {
|
||||||
|
match input.completedLevels.clone() {
|
||||||
|
Some(completed_levels) => {
|
||||||
|
let clean_levels: Vec<i32> = completed_levels[1..completed_levels.len() - 1].split(',')
|
||||||
|
.map(|s| s.parse::<i32>().expect("failed to parse i32"))
|
||||||
|
.collect();
|
||||||
|
query = query.filter(levels::id.ne_all(clean_levels.clone()));
|
||||||
|
count_query = count_query.filter(levels::id.ne_all(clean_levels))
|
||||||
|
},
|
||||||
|
None => return status::Custom(Status::Ok, "-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(1) = input.onlyCompleted {
|
||||||
|
match input.completedLevels.clone() {
|
||||||
|
Some(completed_levels) => {
|
||||||
|
let clean_levels: Vec<i32> = completed_levels[1..completed_levels.len() - 1].split(',')
|
||||||
|
.map(|s| s.parse::<i32>().expect("failed to parse i32"))
|
||||||
|
.collect();
|
||||||
|
query = query.filter(levels::id.eq_any(clean_levels.clone()));
|
||||||
|
count_query = count_query.filter(levels::id.eq_any(clean_levels))
|
||||||
|
},
|
||||||
|
None => return status::Custom(Status::Ok, "-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(song_id) = input.song {
|
||||||
|
if let Some(custom_song) = input.customSong {
|
||||||
|
query = query.filter(levels::song_id.eq(custom_song));
|
||||||
|
count_query = count_query.filter(levels::song_id.eq(custom_song))
|
||||||
|
} else {
|
||||||
|
query = query.filter(levels::song_id.eq(song_id));
|
||||||
|
count_query = count_query.filter(levels::song_id.eq(song_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(1) = input.twoPlayer {
|
||||||
|
query = query.filter(levels::two_player.eq(1));
|
||||||
|
count_query = count_query.filter(levels::two_player.eq(1))
|
||||||
|
}
|
||||||
|
if let Some(1) = input.star {
|
||||||
|
query = query.filter(levels::stars.is_not_null());
|
||||||
|
count_query = count_query.filter(levels::stars.is_not_null())
|
||||||
|
}
|
||||||
|
if let Some(1) = input.noStar {
|
||||||
|
query = query.filter(levels::stars.is_null());
|
||||||
|
count_query = count_query.filter(levels::stars.is_null())
|
||||||
|
}
|
||||||
|
if let Some(_gauntlet_id) = input.gauntlet {
|
||||||
|
unimplemented!("no gauntlet support")
|
||||||
|
}
|
||||||
|
if let Some(len) = input.len {
|
||||||
|
query = query.filter(levels::length.eq(len));
|
||||||
|
count_query = count_query.filter(levels::length.eq(len))
|
||||||
|
}
|
||||||
|
if let Some(diff) = input.diff.clone() {
|
||||||
|
if diff != "-" {
|
||||||
|
match diff.as_str() {
|
||||||
|
"-1" => {
|
||||||
|
query = query.filter(levels::difficulty.is_null().and(levels::community_difficulty.is_null()));
|
||||||
|
count_query = count_query.filter(levels::difficulty.is_null().and(levels::community_difficulty.is_null()))
|
||||||
|
},
|
||||||
|
"-2" => match input.demonFilter {
|
||||||
|
Some(demon_filter) => {
|
||||||
|
match demon_filter {
|
||||||
|
1 => {
|
||||||
|
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Easy.to_demon_difficulty()));
|
||||||
|
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Easy.to_demon_difficulty()))
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Medium.to_demon_difficulty()));
|
||||||
|
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Medium.to_demon_difficulty()))
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Hard.to_demon_difficulty()));
|
||||||
|
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Hard.to_demon_difficulty()))
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Insane.to_demon_difficulty()));
|
||||||
|
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Insane.to_demon_difficulty()))
|
||||||
|
},
|
||||||
|
5 => {
|
||||||
|
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Extreme.to_demon_difficulty()));
|
||||||
|
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Extreme.to_demon_difficulty()))
|
||||||
|
},
|
||||||
|
_ => panic!("invalid demon filter!")
|
||||||
|
}
|
||||||
|
query = query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()))));
|
||||||
|
count_query = count_query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()))))
|
||||||
|
},
|
||||||
|
None => panic!("demon filter option with no demon filter argument")
|
||||||
|
},
|
||||||
|
"-3" => {
|
||||||
|
query = query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()))));
|
||||||
|
count_query = count_query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()))))
|
||||||
|
},
|
||||||
|
// easy, normal, hard, harder, insane
|
||||||
|
_ => {
|
||||||
|
let diffs: Vec<i32> = diff.split(',')
|
||||||
|
.map(|v| v.parse::<i32>().expect("couldnt parse i32"))
|
||||||
|
.collect();
|
||||||
|
query = query.filter(levels::difficulty.eq_any(diffs.clone()).or(levels::difficulty.is_null().and(levels::community_difficulty.eq_any(diffs.clone()))));
|
||||||
|
count_query = count_query.filter(levels::difficulty.eq_any(diffs.clone()).or(levels::difficulty.is_null().and(levels::community_difficulty.eq_any(diffs))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(search_type) = input.r#type {
|
||||||
|
match search_type {
|
||||||
|
// downloads
|
||||||
|
1 => {
|
||||||
|
query = query.order(levels::downloads.desc());
|
||||||
|
// count query order doesnt matter
|
||||||
|
},
|
||||||
|
// likes
|
||||||
|
2 => {
|
||||||
|
query = query.order(levels::likes.desc());
|
||||||
|
// count query order doesnt matter
|
||||||
|
},
|
||||||
|
// trending
|
||||||
|
3 => {
|
||||||
|
unimplemented!("no trending sort :(");
|
||||||
|
},
|
||||||
|
// recent
|
||||||
|
4 => {
|
||||||
|
unimplemented!("no recent sort :(")
|
||||||
|
// count query order doesnt matter
|
||||||
|
}
|
||||||
|
// creator levels
|
||||||
|
5 => {
|
||||||
|
if let Some(1) = input.local {
|
||||||
|
if let Some(input_account_id) = input.accountID {
|
||||||
|
let (user_id_val, _account_id_val): (i32, i32);
|
||||||
|
|
||||||
|
match helpers::accounts::auth(input_account_id, input.password.clone(), input.gjp.clone(), input.gjp2.clone()) {
|
||||||
|
Ok((user_id_val_auth, account_id_val_auth)) => {
|
||||||
|
user_id_val = user_id_val_auth;
|
||||||
|
_account_id_val = account_id_val_auth;
|
||||||
|
},
|
||||||
|
Err(_) => return status::Custom(Status::Ok, "-1")
|
||||||
|
};
|
||||||
|
|
||||||
|
if user_id_val == input.str.parse::<i32>().expect("couldnt convert query input to i32") {
|
||||||
|
can_see_unlisted = true;
|
||||||
|
} else {
|
||||||
|
return status::Custom(Status::Ok, "-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// featured
|
||||||
|
// 17 is gdworld
|
||||||
|
6 | 17 => {
|
||||||
|
query = query.filter(levels::featured.eq(1));
|
||||||
|
count_query = count_query.filter(levels::featured.eq(1))
|
||||||
|
},
|
||||||
|
// epic / HoF
|
||||||
|
16 => {
|
||||||
|
query = query.filter(levels::epic.eq(1));
|
||||||
|
count_query = count_query.filter(levels::epic.eq(1))
|
||||||
|
},
|
||||||
|
// magic
|
||||||
|
7 => {
|
||||||
|
query = query.filter(levels::objects.gt(4000));
|
||||||
|
count_query = count_query.filter(levels::objects.gt(4000))
|
||||||
|
},
|
||||||
|
// map packs 🙄😶
|
||||||
|
10 | 19 => {
|
||||||
|
unimplemented!("no map packs yet buddy")
|
||||||
|
},
|
||||||
|
// rated
|
||||||
|
11 => {
|
||||||
|
query = query.filter(levels::stars.is_not_null());
|
||||||
|
count_query = count_query.filter(levels::stars.is_not_null())
|
||||||
|
},
|
||||||
|
// followed
|
||||||
|
12 => {
|
||||||
|
unimplemented!("no followed yet (i actually *could* implement this, but you cant follow yet so its useless)")
|
||||||
|
},
|
||||||
|
// friends
|
||||||
|
13 => {
|
||||||
|
unimplemented!("no friends")
|
||||||
|
},
|
||||||
|
// daily
|
||||||
|
21 => {
|
||||||
|
unimplemented!("no daily")
|
||||||
|
},
|
||||||
|
// weekly
|
||||||
|
22 => {
|
||||||
|
unimplemented!("no weekly")
|
||||||
|
},
|
||||||
|
// event (honestly idk what this is i think it got leaked from 2.2 or something)
|
||||||
|
23 => {
|
||||||
|
unimplemented!("no event")
|
||||||
|
},
|
||||||
|
// default sort
|
||||||
|
// 15 is gdworld
|
||||||
|
0 | 15 | _ => {
|
||||||
|
query = query.order(levels::likes.desc());
|
||||||
|
// count query order doesnt matter
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !can_see_unlisted {
|
||||||
|
query = query.filter(levels::unlisted.eq(0));
|
||||||
|
count_query = count_query.filter(levels::unlisted.eq(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut results: Vec<String> = [].to_vec();
|
||||||
|
let mut users: Vec<String> = [].to_vec();
|
||||||
|
let mut songs: Vec<String> = [].to_vec();
|
||||||
|
|
||||||
|
let mut hash_data: Vec<(i32, i32, bool)> = [].to_vec();
|
||||||
|
|
||||||
|
for result in {
|
||||||
|
query
|
||||||
|
.order(levels::created_at.desc())
|
||||||
|
.offset(input.page * 10)
|
||||||
|
.limit(10)
|
||||||
|
.get_results::<Level, >(connection)
|
||||||
|
.expect("fatal error loading levels")
|
||||||
|
} {
|
||||||
|
let user: User = users::table.find(result.user_id).get_result::<User, >(connection).expect("couldnt get user from lvl");
|
||||||
|
let level: Level = result;
|
||||||
|
|
||||||
|
let set_difficulty = match level.difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
Some(helpers::difficulty::LevelDifficulty::new(diff))
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
let community_difficulty = match level.community_difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
Some(helpers::difficulty::LevelDifficulty::new(diff))
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
let difficulty = match set_difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
Some(diff)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
match community_difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
Some(diff)
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let demon_difficulty = match level.demon_difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
Some(helpers::difficulty::DemonDifficulty::new(diff))
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
|
||||||
|
results.push(helpers::format::format(hashmap! {
|
||||||
|
1 => level.id.to_string(),
|
||||||
|
2 => level.name,
|
||||||
|
3 => general_purpose::URL_SAFE.encode(level.description),
|
||||||
|
5 => level.version.to_string(),
|
||||||
|
6 => user.id.to_string(),
|
||||||
|
// this argument is weird. its the "difficulty divisor"
|
||||||
|
// used to be vote count but yeah
|
||||||
|
8 => 10.to_string(),
|
||||||
|
9 => (match difficulty {
|
||||||
|
Some(diff) => diff.to_star_difficulty(),
|
||||||
|
None => 0
|
||||||
|
} * 10).to_string(),
|
||||||
|
10 => level.downloads.to_string(),
|
||||||
|
12 => (if level.song_id < 50 { level.song_id } else { 0 }).to_string(),
|
||||||
|
13 => level.game_version.to_string(),
|
||||||
|
14 => level.likes.to_string(),
|
||||||
|
16 => (-level.likes).to_string(),
|
||||||
|
15 => level.length.to_string(),
|
||||||
|
17 => match difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
if diff == helpers::difficulty::LevelDifficulty::Demon {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => 0
|
||||||
|
}.to_string(),
|
||||||
|
18 => (if let Some(stars) = level.stars { stars } else { 0 }).to_string(),
|
||||||
|
19 => level.featured.to_string(),
|
||||||
|
25 => match difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
if diff == helpers::difficulty::LevelDifficulty::Auto {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => 0
|
||||||
|
}.to_string(),
|
||||||
|
30 => (if let Some(original) = level.original { original } else { 0 }).to_string(),
|
||||||
|
31 => level.two_player.to_string(),
|
||||||
|
35 => (if level.song_id >= 50 { level.song_id } else { 0 }).to_string(),
|
||||||
|
37 => level.coins.to_string(),
|
||||||
|
38 => level.rated_coins.to_string(),
|
||||||
|
39 => (if let Some(requested_stars) = level.requested_stars { requested_stars } else { 0 }).to_string(),
|
||||||
|
40 => level.has_ldm.to_string(),
|
||||||
|
42 => level.epic.to_string(),
|
||||||
|
43 => match demon_difficulty {
|
||||||
|
Some(diff) => {
|
||||||
|
diff
|
||||||
|
},
|
||||||
|
None => helpers::difficulty::DemonDifficulty::Hard
|
||||||
|
}.to_demon_difficulty().to_string(),
|
||||||
|
45 => level.objects.to_string(),
|
||||||
|
46 => level.editor_time.to_string(),
|
||||||
|
47 => level.editor_time_copies.to_string()
|
||||||
|
}));
|
||||||
|
|
||||||
|
users.push(format!("{}:{}:{}", user.id, user.username, {
|
||||||
|
if user.registered == 1 {
|
||||||
|
user.account_id.expect("wtf? registered user with no account id.").to_string()
|
||||||
|
} else {
|
||||||
|
user.udid.expect("wtf? unregistered user with no udid.")
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
hash_data.push((
|
||||||
|
level.id,
|
||||||
|
{ if let Some(stars) = level.stars {
|
||||||
|
stars
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}},
|
||||||
|
{ if let 1 = level.rated_coins {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
println!("{}", "no rated coin");
|
||||||
|
false
|
||||||
|
}}
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let level_count = count_query
|
||||||
|
.count()
|
||||||
|
.get_result::<i64, >(connection)
|
||||||
|
.expect("failed to get count of levels");
|
||||||
|
|
||||||
|
let search_meta = format!("{}:{}:{}", level_count, input.page * 10, 10);
|
||||||
|
|
||||||
|
let response = vec![results.join("|"), users.join("|"), songs.join("|"), search_meta, helpers::encryption::gen_multi(hash_data)].join("#");
|
||||||
|
println!("{}", response);
|
||||||
|
|
||||||
|
return status::Custom(Status::Ok, Box::leak(response.into_boxed_str()))
|
||||||
|
}
|
||||||
|
|
||||||
|
//1:93455181:2:Siinamota:5:1:6:158483568:8:10:9:40:10:2171:12:0:13:21:14:40:17::43:5:25::18:0:19:0:42:0:45:3318:3:QnkgSm9yZ2UwMDFZVCAgcGFyYSBlc2N1Y2hhciBsYSBDYW5jaW9uIE5lY2VzaXRhcyBSZW1wbGF6YXIgZXN0YSA6XSBwYXMgMDAwMDAw:15:1:30:0:31:0:37:1:38:0:39:5:46:1:47:2:35:633211#158483568:Jorge001yt:16248905#1~|~633211~|~2~|~Random Song 04~|~3~|~42023~|~4~|~Zhenmuron~|~5~|~0.31~|~6~|~~|~10~|~http%3A%2F%2Faudio.ngfiles.com%2F633000%2F633211_Random-Song-04.mp3~|~7~|~~|~8~|~1#9999:0:10#d19e918b852b706b20e7fbc31bbb07d92efda123
|
|
@ -141,7 +141,7 @@ pub fn upload_level(input: Form<FormUploadLevel>) -> status::Custom<&'static str
|
||||||
length.eq(level_length_val),
|
length.eq(level_length_val),
|
||||||
objects.eq(objects_val as i32),
|
objects.eq(objects_val as i32),
|
||||||
coins.eq(coins_val as i32),
|
coins.eq(coins_val as i32),
|
||||||
has_ldm.eq(input.ldm.unwrap_or(0)),
|
has_ldm.eq(input.ldm.unwrap_or(0).clamp(0, 1)),
|
||||||
two_player.eq(two_player_val)
|
two_player.eq(two_player_val)
|
||||||
))
|
))
|
||||||
.get_result::<Level, >(connection)
|
.get_result::<Level, >(connection)
|
||||||
|
@ -156,7 +156,7 @@ pub fn upload_level(input: Form<FormUploadLevel>) -> status::Custom<&'static str
|
||||||
name: helpers::clean::clean_basic(&input.levelName).chars().take(20).collect(),
|
name: helpers::clean::clean_basic(&input.levelName).chars().take(20).collect(),
|
||||||
user_id: user_id_val,
|
user_id: user_id_val,
|
||||||
description: description_val.chars().take(140).collect(),
|
description: description_val.chars().take(140).collect(),
|
||||||
original: input.original.unwrap_or(0),
|
original: input.original,
|
||||||
game_version: input.gameVersion,
|
game_version: input.gameVersion,
|
||||||
binary_version: input.binaryVersion.unwrap_or(0),
|
binary_version: input.binaryVersion.unwrap_or(0),
|
||||||
password: input.password.clone(),
|
password: input.password.clone(),
|
||||||
|
|
|
@ -38,31 +38,33 @@ pub fn get_users(input: Form<FormGetUsers>) -> status::Custom<&'static str> {
|
||||||
.get_results::<User, >(connection)
|
.get_results::<User, >(connection)
|
||||||
.expect("Fatal error loading users")
|
.expect("Fatal error loading users")
|
||||||
} {
|
} {
|
||||||
|
let user: User = result;
|
||||||
|
|
||||||
let formatted_result = helpers::format::format(hashmap! {
|
let formatted_result = helpers::format::format(hashmap! {
|
||||||
1 => result.username,
|
1 => user.username,
|
||||||
2 => result.id.to_string(),
|
2 => user.id.to_string(),
|
||||||
3 => result.stars.to_string(),
|
3 => user.stars.to_string(),
|
||||||
4 => result.demons.to_string(),
|
4 => user.demons.to_string(),
|
||||||
8 => result.creator_points.to_string(),
|
8 => user.creator_points.to_string(),
|
||||||
9 => {
|
9 => {
|
||||||
vec![
|
vec![
|
||||||
result.cube,
|
user.cube,
|
||||||
result.ship,
|
user.ship,
|
||||||
result.ball,
|
user.ball,
|
||||||
result.ufo,
|
user.ufo,
|
||||||
result.wave,
|
user.wave,
|
||||||
result.robot
|
user.robot
|
||||||
][result.icon_type as usize].to_string()
|
][user.icon_type as usize].to_string()
|
||||||
},
|
},
|
||||||
10 => result.color1.to_string(),
|
10 => user.color1.to_string(),
|
||||||
11 => result.color2.to_string(),
|
11 => user.color2.to_string(),
|
||||||
13 => result.coins.to_string(),
|
13 => user.coins.to_string(),
|
||||||
14 => result.icon_type.to_string(),
|
14 => user.icon_type.to_string(),
|
||||||
15 => result.special.to_string(),
|
15 => user.special.to_string(),
|
||||||
16 => {
|
16 => {
|
||||||
match result.account_id {
|
match user.account_id {
|
||||||
Some(account_id_value) => account_id_value.to_string(),
|
Some(account_id_value) => account_id_value.to_string(),
|
||||||
None => match result.udid {
|
None => match user.udid {
|
||||||
Some(udid_value) => udid_value.to_string(),
|
Some(udid_value) => udid_value.to_string(),
|
||||||
None => panic!("user has no account_id or udid?!?!?")
|
None => panic!("user has no account_id or udid?!?!?")
|
||||||
}
|
}
|
||||||
|
@ -83,7 +85,7 @@ pub fn get_users(input: Form<FormGetUsers>) -> status::Custom<&'static str> {
|
||||||
let amount = query_users_count
|
let amount = query_users_count
|
||||||
.count()
|
.count()
|
||||||
.get_result::<i64>(connection)
|
.get_result::<i64>(connection)
|
||||||
.expect("Error querying user count");
|
.expect("error querying user count");
|
||||||
|
|
||||||
let response = if results.is_empty() {
|
let response = if results.is_empty() {
|
||||||
String::from("-1")
|
String::from("-1")
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum LevelDifficulty {
|
pub enum LevelDifficulty {
|
||||||
Auto,
|
Auto,
|
||||||
Easy,
|
Easy,
|
||||||
|
@ -9,7 +10,32 @@ pub enum LevelDifficulty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LevelDifficulty {
|
impl LevelDifficulty {
|
||||||
pub fn to_star_difficulty(&self) -> i32 {
|
pub fn new(value: i32) -> LevelDifficulty {
|
||||||
|
match value {
|
||||||
|
0 => LevelDifficulty::Auto,
|
||||||
|
1 => LevelDifficulty::Easy,
|
||||||
|
2 => LevelDifficulty::Normal,
|
||||||
|
3 => LevelDifficulty::Hard,
|
||||||
|
4 => LevelDifficulty::Harder,
|
||||||
|
5 => LevelDifficulty::Insane,
|
||||||
|
6 => LevelDifficulty::Demon,
|
||||||
|
_ => panic!("invalid level difficulty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(self) -> i32 {
|
||||||
|
match self {
|
||||||
|
LevelDifficulty::Auto => 0,
|
||||||
|
LevelDifficulty::Easy => 1,
|
||||||
|
LevelDifficulty::Normal => 2,
|
||||||
|
LevelDifficulty::Hard => 3,
|
||||||
|
LevelDifficulty::Harder => 4,
|
||||||
|
LevelDifficulty::Insane => 5,
|
||||||
|
LevelDifficulty::Demon => 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_star_difficulty(self) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
LevelDifficulty::Auto => 5,
|
LevelDifficulty::Auto => 5,
|
||||||
LevelDifficulty::Easy => 1,
|
LevelDifficulty::Easy => 1,
|
||||||
|
@ -20,4 +46,59 @@ impl LevelDifficulty {
|
||||||
LevelDifficulty::Demon => 5,
|
LevelDifficulty::Demon => 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stars_to_diff(stars: i32) -> Self {
|
||||||
|
match stars {
|
||||||
|
1 => LevelDifficulty::Auto,
|
||||||
|
2 => LevelDifficulty::Easy,
|
||||||
|
3 => LevelDifficulty::Normal,
|
||||||
|
4 | 5 => LevelDifficulty::Hard,
|
||||||
|
6 | 7 => LevelDifficulty::Harder,
|
||||||
|
8 | 9 => LevelDifficulty::Insane,
|
||||||
|
10 => LevelDifficulty::Demon,
|
||||||
|
_ => panic!("invalid difficulty!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DemonDifficulty {
|
||||||
|
Easy,
|
||||||
|
Medium,
|
||||||
|
Hard,
|
||||||
|
Insane,
|
||||||
|
Extreme
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DemonDifficulty {
|
||||||
|
pub fn new(value: i32) -> DemonDifficulty {
|
||||||
|
match value {
|
||||||
|
0 => DemonDifficulty::Easy,
|
||||||
|
1 => DemonDifficulty::Medium,
|
||||||
|
2 => DemonDifficulty::Hard,
|
||||||
|
3 => DemonDifficulty::Insane,
|
||||||
|
4 => DemonDifficulty::Extreme,
|
||||||
|
5 => DemonDifficulty::Insane,
|
||||||
|
_ => panic!("invalid demon difficulty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(self) -> i32 {
|
||||||
|
match self {
|
||||||
|
DemonDifficulty::Easy => 0,
|
||||||
|
DemonDifficulty::Medium => 1,
|
||||||
|
DemonDifficulty::Hard => 2,
|
||||||
|
DemonDifficulty::Insane => 3,
|
||||||
|
DemonDifficulty::Extreme => 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_demon_difficulty(self) -> i32 {
|
||||||
|
match self {
|
||||||
|
DemonDifficulty::Easy => 3,
|
||||||
|
DemonDifficulty::Medium => 4,
|
||||||
|
DemonDifficulty::Hard => 0,
|
||||||
|
DemonDifficulty::Insane => 5,
|
||||||
|
DemonDifficulty::Extreme => 6
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -28,3 +28,23 @@ pub fn decode_gjp(gjp: String) -> String {
|
||||||
let xor_decoded = cyclic_xor_string(&base64_decoded, "37526");
|
let xor_decoded = cyclic_xor_string(&base64_decoded, "37526");
|
||||||
return xor_decoded
|
return xor_decoded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gen_multi(level_hash_data: Vec<(i32, i32, bool)>) -> String {
|
||||||
|
let mut input_str = String::new();
|
||||||
|
|
||||||
|
for (_index, val) in level_hash_data.iter().enumerate() {
|
||||||
|
let (level_id, stars, coins) = val;
|
||||||
|
let level_id_str = level_id.to_string();
|
||||||
|
|
||||||
|
input_str.push(level_id_str.chars().nth(0).unwrap());
|
||||||
|
input_str.push(level_id_str.chars().last().unwrap());
|
||||||
|
input_str.push_str(&stars.to_string());
|
||||||
|
input_str.push_str(if *coins { "1" } else { "0" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut bytes: Vec<u8> = Vec::new();
|
||||||
|
bytes.extend(input_str.as_bytes().to_vec());
|
||||||
|
bytes.extend("xI25fpAapCQg".as_bytes().to_vec());
|
||||||
|
|
||||||
|
return Sha1::default().digest(bytes.as_mut_slice()).to_hex();
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ pub fn format(map: HashMap<i32, impl ToString>) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.ends_with(":") {
|
if result.ends_with(":") {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ use base64::{Engine as _, engine::general_purpose};
|
||||||
|
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub static DEFAULT_EXTRA_STRING: LazyLock<String> = LazyLock::new(|| {
|
pub static DEFAULT_EXTRA_STRING: LazyLock<String> = LazyLock::new(|| {
|
||||||
let string = String::from("29_29_29_40_29_29_29_29_29_29_29_29_29_29_29_29");
|
let string = String::from("29_29_29_40_29_29_29_29_29_29_29_29_29_29_29_29");
|
||||||
|
|
||||||
|
@ -19,7 +21,6 @@ macro_rules! object_prop_bool {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ObjectData {
|
pub struct ObjectData {
|
||||||
|
@ -54,8 +55,8 @@ pub enum PortalSpeed {
|
||||||
VeryFast
|
VeryFast
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PortalSpeed {
|
impl Into<f64> for PortalSpeed {
|
||||||
pub fn portal_speed(&self) -> f64 {
|
fn into(self) -> f64 {
|
||||||
match self {
|
match self {
|
||||||
PortalSpeed::Slow => 251.16,
|
PortalSpeed::Slow => 251.16,
|
||||||
PortalSpeed::Normal => 311.58,
|
PortalSpeed::Normal => 311.58,
|
||||||
|
@ -78,12 +79,12 @@ pub fn id_to_portal_speed(id: i32) -> Option<PortalSpeed> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_seconds_from_xpos(pos: f64, start_speed: PortalSpeed, portals: Vec<ObjectData>) -> f64 {
|
pub fn get_seconds_from_xpos(pos: f64, start_speed: PortalSpeed, portals: Vec<ObjectData>) -> f64 {
|
||||||
let mut speed;
|
let mut speed: f64;
|
||||||
let mut last_obj_pos = 0.0;
|
let mut last_obj_pos = 0.0;
|
||||||
let mut last_segment = 0.0;
|
let mut last_segment = 0.0;
|
||||||
let mut segments = 0.0;
|
let mut segments = 0.0;
|
||||||
|
|
||||||
speed = start_speed.portal_speed();
|
speed = start_speed.into();
|
||||||
|
|
||||||
if portals.is_empty() {
|
if portals.is_empty() {
|
||||||
return pos / speed
|
return pos / speed
|
||||||
|
@ -97,7 +98,7 @@ pub fn get_seconds_from_xpos(pos: f64, start_speed: PortalSpeed, portals: Vec<Ob
|
||||||
last_segment = s;
|
last_segment = s;
|
||||||
segments += s;
|
segments += s;
|
||||||
|
|
||||||
speed = id_to_portal_speed(portal.id()).expect("not a portal").portal_speed();
|
speed = id_to_portal_speed(portal.id()).expect("not a portal").into();
|
||||||
|
|
||||||
last_obj_pos = portal.x()
|
last_obj_pos = portal.x()
|
||||||
}
|
}
|
||||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -5,6 +5,11 @@
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use rocket::fs::NamedFile;
|
||||||
|
|
||||||
|
use rocket_dyn_templates::{ Template };
|
||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
use db::*;
|
use db::*;
|
||||||
|
@ -15,6 +20,9 @@ use helpers::*;
|
||||||
mod endpoints;
|
mod endpoints;
|
||||||
use endpoints::*;
|
use endpoints::*;
|
||||||
|
|
||||||
|
mod template_endpoints;
|
||||||
|
use template_endpoints::*;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
use config::*;
|
use config::*;
|
||||||
|
|
||||||
|
@ -23,15 +31,28 @@ fn index() -> String {
|
||||||
return String::from("gdps-server | https://git.reidlab.online/reidlab/gdps-server");
|
return String::from("gdps-server | https://git.reidlab.online/reidlab/gdps-server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/<file..>")]
|
||||||
|
async fn files(file: PathBuf) -> Option<NamedFile> {
|
||||||
|
NamedFile::open(Path::new("public/").join(file)).await.ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
fs::create_dir_all(&CONFIG.db.data_folder).expect("failed to create data directory!");
|
// this is a bit scuffed
|
||||||
|
fs::create_dir_all(&CONFIG.db.data_folder).expect("failed to create data directory! (probably a permission err)");
|
||||||
fs::create_dir_all(format!("{}/levels", &CONFIG.db.data_folder)).expect("failed to create data directory for levels");
|
fs::create_dir_all(format!("{}/levels", &CONFIG.db.data_folder)).expect("failed to create data directory for levels");
|
||||||
|
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.configure(rocket::Config::figment().merge(("port", CONFIG.general.port)))
|
.configure(rocket::Config::figment().merge(("port", CONFIG.general.port)))
|
||||||
|
// actual website
|
||||||
.mount("/", routes![
|
.mount("/", routes![
|
||||||
index,
|
template_endpoints::index::index
|
||||||
])
|
])
|
||||||
|
// assets
|
||||||
|
.mount("/", routes![
|
||||||
|
files
|
||||||
|
])
|
||||||
|
// GEOMETRY DASH https://www.youtube.com/watch?v=_pLrtsf5yfE
|
||||||
.mount(CONFIG.general.append_path.as_str(), routes![
|
.mount(CONFIG.general.append_path.as_str(), routes![
|
||||||
endpoints::accounts::login_account::login_account,
|
endpoints::accounts::login_account::login_account,
|
||||||
endpoints::accounts::register_account::register_account,
|
endpoints::accounts::register_account::register_account,
|
||||||
|
@ -39,6 +60,9 @@ fn rocket() -> _ {
|
||||||
|
|
||||||
endpoints::users::get_users::get_users,
|
endpoints::users::get_users::get_users,
|
||||||
|
|
||||||
|
endpoints::levels::get_levels::get_levels,
|
||||||
endpoints::levels::upload_level::upload_level
|
endpoints::levels::upload_level::upload_level
|
||||||
])
|
])
|
||||||
|
// so templates work i think
|
||||||
|
.attach(Template::fairing())
|
||||||
}
|
}
|
1
src/template_endpoints.rs
Normal file
1
src/template_endpoints.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod index;
|
18
src/template_endpoints/index.rs
Normal file
18
src/template_endpoints/index.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use rocket_dyn_templates::{Template, context};
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub fn index() -> Template {
|
||||||
|
let silly_strings: Vec<&str> = vec![
|
||||||
|
"the trianges consume",
|
||||||
|
"geomtry das"
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let random_index = rng.gen_range(0..silly_strings.len());
|
||||||
|
|
||||||
|
let silly_string = silly_strings[random_index];
|
||||||
|
|
||||||
|
Template::render("index", context! { silly_string: silly_string })
|
||||||
|
}
|
34
templates/index.html.hbs
Normal file
34
templates/index.html.hbs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="stylesheet" href="/style.css" />
|
||||||
|
<title>gdps-server</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="display: flex; align-items: center; gap: 1.5em; flex-direction: column">
|
||||||
|
<h1 style="display: flex; align-items: center; gap: 1em">
|
||||||
|
<img src="/favicon.png" width="64" height="auto">
|
||||||
|
gdps-server
|
||||||
|
</h1>
|
||||||
|
<div class="block">
|
||||||
|
<p>
|
||||||
|
<b>gdps-server</b> is a WIP <a href="https://store.steampowered.com/app/322170/Geometry_Dash/" target="_blank" rel="noreferrer noopener">Geometry Dash</a> private server written in <a href="https://rust-lang.org/" target="_blank" rel="noreferrer noopener">Rust</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You can check out other shit here:
|
||||||
|
<br>
|
||||||
|
<el>
|
||||||
|
<li>The <a href="https://git.reidlab.online/reidlab/gdps-server">Git repository</a></li>
|
||||||
|
</el>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="dim">
|
||||||
|
{{ silly_string }}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue