mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-18 00:08:54 +00:00
Pull info from an attached .osu/.osz file (#18)
This commit is contained in:
parent
acc0e339a0
commit
2e3c6f61be
10 changed files with 631 additions and 125 deletions
315
Cargo.lock
generated
315
Cargo.lock
generated
|
@ -14,9 +14,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
|
@ -121,6 +133,12 @@ version = "0.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.1"
|
||||
|
@ -158,6 +176,15 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
|
@ -172,9 +199,9 @@ checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
|
|||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
|
@ -188,11 +215,35 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0"
|
||||
dependencies = [
|
||||
"bzip2-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.11+1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -210,10 +261,19 @@ dependencies = [
|
|||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"time 0.1.43",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codeforces"
|
||||
version = "0.3.1"
|
||||
|
@ -239,6 +299,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.1"
|
||||
|
@ -255,6 +321,15 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpuid-bool"
|
||||
version = "0.1.2"
|
||||
|
@ -272,9 +347,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
@ -301,15 +376,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.3"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "4.0.2"
|
||||
|
@ -329,6 +413,17 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.2",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
|
@ -374,9 +469,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.20"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
|
||||
checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crc32fast",
|
||||
|
@ -625,6 +720,15 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest 0.10.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.3"
|
||||
|
@ -633,7 +737,7 @@ checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747"
|
|||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"fnv",
|
||||
"itoa",
|
||||
"itoa 0.4.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -682,7 +786,7 @@ dependencies = [
|
|||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"itoa 0.4.7",
|
||||
"pin-project 1.0.5",
|
||||
"socket2",
|
||||
"tokio",
|
||||
|
@ -770,6 +874,21 @@ version = "0.4.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.47"
|
||||
|
@ -800,9 +919,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.85"
|
||||
version = "0.2.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
|
||||
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
|
@ -875,12 +994,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.3"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
|
||||
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -984,6 +1102,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
|
@ -1029,6 +1156,14 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "osuparse"
|
||||
version = "2.0.1"
|
||||
source = "git+https://github.com/eltrufas/osuparse?rev=ad8f6e5e7771e7cbaa2ec96c376558f9731139af#ad8f6e5e7771e7cbaa2ec96c376558f9731139af"
|
||||
dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
|
@ -1054,6 +1189,29 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core 0.6.1",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7"
|
||||
dependencies = [
|
||||
"digest 0.10.3",
|
||||
"hmac",
|
||||
"password-hash",
|
||||
"sha2 0.10.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
@ -1451,7 +1609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"itoa 0.4.7",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1463,7 +1621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"itoa 0.4.7",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1513,26 +1671,48 @@ version = "0.9.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4b312c3731e3fe78a185e6b9b911a7aa715b8e31cce117975219aab2acf285d"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if",
|
||||
"cpuid-bool",
|
||||
"digest",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.10.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if",
|
||||
"cpuid-bool",
|
||||
"digest",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.10.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
|
@ -1616,7 +1796,7 @@ dependencies = [
|
|||
"futures-util",
|
||||
"hashlink",
|
||||
"hex",
|
||||
"itoa",
|
||||
"itoa 0.4.7",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
"log",
|
||||
|
@ -1626,7 +1806,7 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"rustls",
|
||||
"serde",
|
||||
"sha2",
|
||||
"sha2 0.9.3",
|
||||
"smallvec",
|
||||
"sqlformat",
|
||||
"sqlx-rt",
|
||||
|
@ -1655,7 +1835,7 @@ dependencies = [
|
|||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sha2 0.9.3",
|
||||
"sqlx-core",
|
||||
"sqlx-rt",
|
||||
"syn",
|
||||
|
@ -1689,6 +1869,12 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.60"
|
||||
|
@ -1768,6 +1954,24 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.1.1"
|
||||
|
@ -1938,9 +2142,9 @@ checksum = "335fb14412163adc9ed4a3e53335afaa7a4b72bdd122e5f72f51b8f1db1a131e"
|
|||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
|
@ -2303,6 +2507,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"dashmap",
|
||||
"lazy_static",
|
||||
"osuparse",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rosu-pp",
|
||||
|
@ -2312,6 +2517,7 @@ dependencies = [
|
|||
"youmubot-db",
|
||||
"youmubot-db-sql",
|
||||
"youmubot-prelude",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2330,3 +2536,52 @@ dependencies = [
|
|||
"youmubot-db",
|
||||
"youmubot-db-sql",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"byteorder",
|
||||
"bzip2",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"flate2",
|
||||
"hmac",
|
||||
"pbkdf2",
|
||||
"sha1",
|
||||
"time 0.3.9",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.10.0+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b1365becbe415f3f0fcd024e2f7b45bacfb5bdd055f0dc113571394114e7bdd"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "4.1.4+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f7cd17c9af1a4d6c24beb1cc54b17e2ef7b593dc92f19e9d9acad8b182bbaee"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "1.6.3+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
|
6
flake.lock
generated
6
flake.lock
generated
|
@ -35,11 +35,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1648746709,
|
||||
"narHash": "sha256-MSwb5UZuplAkwhZrA8TsNEX57Dy8tJODtF82aKY+amA=",
|
||||
"lastModified": 1651263162,
|
||||
"narHash": "sha256-OOw4ll+7Ql8Fh4NRWWXxnuSxFGD6rrLB3SdGtZrfy4I=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9cd1fa9bcef3b578a732a391436aad804e03e3ca",
|
||||
"rev": "e850f1e4d0a645d2ec4cd5fcc427254fd4cec79a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
23
flake.nix
23
flake.nix
|
@ -34,16 +34,21 @@
|
|||
defaultApp = apps.youmubot;
|
||||
|
||||
# `nix develop`
|
||||
devShell = pkgs.mkShell {
|
||||
nativeBuildInputs =
|
||||
(with pkgs; [ rustc cargo rust-analyzer rustfmt ]) ++
|
||||
nixpkgs.lib.optionals (nixpkgs.lib.strings.hasSuffix "darwin" system) (with pkgs; [
|
||||
libiconv
|
||||
darwin.apple_sdk.frameworks.Security
|
||||
]);
|
||||
};
|
||||
|
||||
devShell = pkgs.mkShell
|
||||
{
|
||||
nativeBuildInputs =
|
||||
(with pkgs; [ rustc cargo rust-analyzer rustfmt ])
|
||||
++ nixpkgs.lib.optionals (nixpkgs.lib.strings.hasSuffix "darwin" system) (with pkgs; [
|
||||
libiconv
|
||||
darwin.apple_sdk.frameworks.Security
|
||||
])
|
||||
++ nixpkgs.lib.optionals (nixpkgs.lib.strings.hasSuffix "linux" system) (with pkgs; [
|
||||
pkg-config
|
||||
openssl
|
||||
]);
|
||||
};
|
||||
# module
|
||||
nixosModule = import ./module.nix defaultPackage;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,16 +7,18 @@ edition = "2018"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serenity = "0.10"
|
||||
chrono = "0.4"
|
||||
reqwest = "0.11"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
bitflags = "1"
|
||||
lazy_static = "1"
|
||||
regex = "1"
|
||||
rosu-pp = "0.4"
|
||||
dashmap = "4"
|
||||
bincode = "1"
|
||||
bitflags = "1"
|
||||
chrono = "0.4"
|
||||
dashmap = "4"
|
||||
lazy_static = "1"
|
||||
osuparse = { git = "https://github.com/eltrufas/osuparse", rev = "ad8f6e5e7771e7cbaa2ec96c376558f9731139af" }
|
||||
regex = "1"
|
||||
reqwest = "0.11"
|
||||
rosu-pp = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serenity = "0.10"
|
||||
zip = "0.6.2"
|
||||
|
||||
youmubot-db = { path = "../youmubot-db" }
|
||||
youmubot-db-sql = { path = "../youmubot-db-sql" }
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use super::BeatmapWithMode;
|
||||
use crate::{
|
||||
discord::oppai_cache::{Accuracy, BeatmapContent, BeatmapInfo, BeatmapInfoWithPP},
|
||||
models::{Beatmap, Mode, Mods, Rank, Score, User},
|
||||
models::{Beatmap, Difficulty, Mode, Mods, Rank, Score, User},
|
||||
};
|
||||
use serenity::{builder::CreateEmbed, utils::MessageBuilder};
|
||||
use std::time::Duration;
|
||||
use youmubot_prelude::*;
|
||||
|
||||
/// Writes a number grouped in groups of 3.
|
||||
|
@ -55,42 +56,54 @@ fn beatmap_description(b: &Beatmap) -> String {
|
|||
.build()
|
||||
}
|
||||
|
||||
pub fn beatmap_embed<'a>(
|
||||
b: &'_ Beatmap,
|
||||
pub fn beatmap_offline_embed(
|
||||
b: &'_ crate::discord::oppai_cache::BeatmapContent,
|
||||
m: Mode,
|
||||
mods: Mods,
|
||||
info: Option<BeatmapInfoWithPP>,
|
||||
c: &'a mut CreateEmbed,
|
||||
) -> &'a mut CreateEmbed {
|
||||
let mod_str = if mods == Mods::NOMOD {
|
||||
"".to_owned()
|
||||
) -> Result<Box<dyn FnOnce(&mut CreateEmbed) -> &mut CreateEmbed + Send + Sync>> {
|
||||
let bm = b.content.clone();
|
||||
let metadata = b.metadata.clone();
|
||||
let (info, pp) = b.get_possible_pp_with(mods)?;
|
||||
|
||||
let total_length = if bm.hit_objects.len() >= 1 {
|
||||
Duration::from_millis(
|
||||
(bm.hit_objects.last().unwrap().end_time() - bm.hit_objects.first().unwrap().start_time)
|
||||
as u64,
|
||||
)
|
||||
} else {
|
||||
format!(" {}", mods)
|
||||
Duration::from_secs(0)
|
||||
};
|
||||
let diff = b
|
||||
.difficulty
|
||||
.apply_mods(mods, info.map(|(v, _)| v.stars as f64));
|
||||
c.title(
|
||||
MessageBuilder::new()
|
||||
.push_bold_safe(&b.artist)
|
||||
.push(" - ")
|
||||
.push_bold_safe(&b.title)
|
||||
.push(" [")
|
||||
.push_bold_safe(&b.difficulty_name)
|
||||
.push("]")
|
||||
.push(&mod_str)
|
||||
.build(),
|
||||
)
|
||||
.author(|a| {
|
||||
a.name(&b.creator)
|
||||
.url(format!("https://osu.ppy.sh/users/{}", b.creator_id))
|
||||
.icon_url(format!("https://a.ppy.sh/{}", b.creator_id))
|
||||
})
|
||||
.url(b.link())
|
||||
.image(b.cover_url())
|
||||
.color(0xffb6c1)
|
||||
.fields(info.map(|(_, pp)| {
|
||||
(
|
||||
|
||||
let diff = Difficulty {
|
||||
stars: info.stars,
|
||||
aim: None, // TODO: this is currently unused
|
||||
speed: None, // TODO: this is currently unused
|
||||
cs: bm.cs as f64,
|
||||
od: bm.od as f64,
|
||||
ar: bm.ar as f64,
|
||||
hp: bm.hp as f64,
|
||||
count_normal: bm.n_circles as u64,
|
||||
count_slider: bm.n_sliders as u64,
|
||||
count_spinner: bm.n_spinners as u64,
|
||||
max_combo: Some(info.max_combo as u64),
|
||||
bpm: bm.bpm(),
|
||||
drain_length: total_length, // It's hard to calculate so maybe just skip...
|
||||
total_length,
|
||||
}
|
||||
.apply_mods(mods, Some(info.stars));
|
||||
Ok(Box::new(move |c: &mut CreateEmbed| {
|
||||
c.title(beatmap_title(
|
||||
&metadata.artist,
|
||||
&metadata.title,
|
||||
&metadata.version,
|
||||
mods,
|
||||
))
|
||||
.author(|a| {
|
||||
a.name(&metadata.creator)
|
||||
.url(format!("https://osu.ppy.sh/users/{}", metadata.creator))
|
||||
})
|
||||
.color(0xffb6c1)
|
||||
.field(
|
||||
"Calculated pp",
|
||||
format!(
|
||||
"95%: **{:.2}**pp, 98%: **{:.2}**pp, 99%: **{:.2}**pp, 100%: **{:.2}**pp",
|
||||
|
@ -98,15 +111,73 @@ pub fn beatmap_embed<'a>(
|
|||
),
|
||||
false,
|
||||
)
|
||||
.field("Information", diff.format_info(m, mods, None), false)
|
||||
// .description(beatmap_description(b))
|
||||
}))
|
||||
.field("Information", diff.format_info(m, mods, b), false)
|
||||
.description(beatmap_description(b))
|
||||
.footer(|f| {
|
||||
if info.is_none() && mods != Mods::NOMOD {
|
||||
f.text("Star difficulty not reflecting mods applied.");
|
||||
}
|
||||
f
|
||||
})
|
||||
}
|
||||
|
||||
// Some helper functions here
|
||||
|
||||
/// Create a properly formatted beatmap title, in the `Artist - Title [Difficulty] +mods` format.
|
||||
fn beatmap_title(
|
||||
artist: impl AsRef<str>,
|
||||
title: impl AsRef<str>,
|
||||
difficulty: impl AsRef<str>,
|
||||
mods: Mods,
|
||||
) -> String {
|
||||
let mod_str = if mods == Mods::NOMOD {
|
||||
"".to_owned()
|
||||
} else {
|
||||
format!(" {}", mods)
|
||||
};
|
||||
MessageBuilder::new()
|
||||
.push_bold_safe(artist.as_ref())
|
||||
.push(" - ")
|
||||
.push_bold_safe(title.as_ref())
|
||||
.push(" [")
|
||||
.push_bold_safe(difficulty.as_ref())
|
||||
.push("]")
|
||||
.push(&mod_str)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn beatmap_embed<'a>(
|
||||
b: &'_ Beatmap,
|
||||
m: Mode,
|
||||
mods: Mods,
|
||||
info: Option<BeatmapInfoWithPP>,
|
||||
c: &'a mut CreateEmbed,
|
||||
) -> &'a mut CreateEmbed {
|
||||
let diff = b
|
||||
.difficulty
|
||||
.apply_mods(mods, info.map(|(v, _)| v.stars as f64));
|
||||
c.title(beatmap_title(&b.artist, &b.title, &b.difficulty_name, mods))
|
||||
.author(|a| {
|
||||
a.name(&b.creator)
|
||||
.url(format!("https://osu.ppy.sh/users/{}", b.creator_id))
|
||||
.icon_url(format!("https://a.ppy.sh/{}", b.creator_id))
|
||||
})
|
||||
.url(b.link())
|
||||
.image(b.cover_url())
|
||||
.color(0xffb6c1)
|
||||
.fields(info.map(|(_, pp)| {
|
||||
(
|
||||
"Calculated pp",
|
||||
format!(
|
||||
"95%: **{:.2}**pp, 98%: **{:.2}**pp, 99%: **{:.2}**pp, 100%: **{:.2}**pp",
|
||||
pp[0], pp[1], pp[2], pp[3]
|
||||
),
|
||||
false,
|
||||
)
|
||||
}))
|
||||
.field("Information", diff.format_info(m, mods, b), false)
|
||||
.description(beatmap_description(b))
|
||||
.footer(|f| {
|
||||
if info.is_none() && mods != Mods::NOMOD {
|
||||
f.text("Star difficulty not reflecting mods applied.");
|
||||
}
|
||||
f
|
||||
})
|
||||
}
|
||||
|
||||
const MAX_DIFFS: usize = 25 - 4;
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
};
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serenity::{model::channel::Message, utils::MessageBuilder};
|
||||
use serenity::{builder::CreateEmbed, model::channel::Message, utils::MessageBuilder};
|
||||
use std::str::FromStr;
|
||||
use youmubot_prelude::*;
|
||||
|
||||
|
@ -23,6 +23,101 @@ lazy_static! {
|
|||
).unwrap();
|
||||
}
|
||||
|
||||
pub fn dot_osu_hook<'a>(
|
||||
ctx: &'a Context,
|
||||
msg: &'a Message,
|
||||
) -> std::pin::Pin<Box<dyn future::Future<Output = Result<()>> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if msg.author.bot {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Take all the .osu attachments
|
||||
let mut osu_embeds = msg
|
||||
.attachments
|
||||
.iter()
|
||||
.filter(
|
||||
|a| a.filename.ends_with(".osu") && a.size < 1024 * 1024, /* 1mb */
|
||||
)
|
||||
.map(|attachment| {
|
||||
let url = attachment.url.clone();
|
||||
|
||||
async move {
|
||||
let data = ctx.data.read().await;
|
||||
let oppai = data.get::<BeatmapCache>().unwrap();
|
||||
let (beatmap, _) = oppai.download_beatmap_from_url(&url, None).await.ok()?;
|
||||
let embed_fn = crate::discord::embeds::beatmap_offline_embed(
|
||||
&beatmap,
|
||||
Mode::from(beatmap.content.mode as u8), /*For now*/
|
||||
msg.content.trim().parse().unwrap_or(Mods::NOMOD),
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
let mut create_embed = CreateEmbed::default();
|
||||
embed_fn(&mut create_embed);
|
||||
|
||||
Some(create_embed)
|
||||
}
|
||||
})
|
||||
.collect::<stream::FuturesUnordered<_>>()
|
||||
.filter_map(|v| future::ready(v))
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
|
||||
let osz_embeds = msg
|
||||
.attachments
|
||||
.iter()
|
||||
.filter(
|
||||
|a| a.filename.ends_with(".osz") && a.size < 20 * 1024 * 1024, /* 20mb */
|
||||
)
|
||||
.map(|attachment| {
|
||||
let url = attachment.url.clone();
|
||||
async move {
|
||||
let data = ctx.data.read().await;
|
||||
let oppai = data.get::<BeatmapCache>().unwrap();
|
||||
let beatmaps = oppai.download_osz_from_url(&url).await.pls_ok()?;
|
||||
Some(
|
||||
beatmaps
|
||||
.into_iter()
|
||||
.filter_map(|beatmap| {
|
||||
let embed_fn = crate::discord::embeds::beatmap_offline_embed(
|
||||
&beatmap,
|
||||
Mode::from(beatmap.content.mode as u8), /*For now*/
|
||||
msg.content.trim().parse().unwrap_or(Mods::NOMOD),
|
||||
)
|
||||
.pls_ok()?;
|
||||
|
||||
let mut create_embed = CreateEmbed::default();
|
||||
embed_fn(&mut create_embed);
|
||||
Some(create_embed)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect::<stream::FuturesUnordered<_>>()
|
||||
.filter_map(|v| future::ready(v))
|
||||
.filter(|v| future::ready(v.len() > 0))
|
||||
.collect::<Vec<_>>()
|
||||
.await
|
||||
.concat();
|
||||
osu_embeds.extend(osz_embeds);
|
||||
|
||||
if osu_embeds.len() > 0 {
|
||||
msg.channel_id
|
||||
.send_message(ctx, |f| {
|
||||
f.reference_message(msg)
|
||||
.content(format!("{} attached beatmaps found", osu_embeds.len()))
|
||||
.add_embeds(osu_embeds)
|
||||
})
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hook<'a>(
|
||||
ctx: &'a Context,
|
||||
msg: &'a Message,
|
||||
|
|
|
@ -31,7 +31,7 @@ mod server_rank;
|
|||
use db::OsuUser;
|
||||
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUserBests};
|
||||
use embeds::{beatmap_embed, score_embed, user_embed};
|
||||
pub use hook::hook;
|
||||
pub use hook::{dot_osu_hook, hook};
|
||||
use server_rank::{SERVER_RANK_COMMAND, UPDATE_LEADERBOARD_COMMAND};
|
||||
|
||||
/// The osu! client.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::mods::Mods;
|
||||
use osuparse::MetadataSection;
|
||||
use rosu_pp::{Beatmap, BeatmapExt};
|
||||
use std::io::Read;
|
||||
use std::sync::Arc;
|
||||
use youmubot_db_sql::{models::osu as models, Pool};
|
||||
use youmubot_prelude::*;
|
||||
|
@ -7,8 +9,9 @@ use youmubot_prelude::*;
|
|||
/// the information collected from a download/Oppai request.
|
||||
#[derive(Debug)]
|
||||
pub struct BeatmapContent {
|
||||
id: u64,
|
||||
content: Arc<Beatmap>,
|
||||
id: Option<u64>,
|
||||
pub metadata: MetadataSection,
|
||||
pub content: Arc<Beatmap>,
|
||||
}
|
||||
|
||||
/// the output of "one" oppai run.
|
||||
|
@ -128,25 +131,82 @@ impl BeatmapCache {
|
|||
BeatmapCache { client, pool }
|
||||
}
|
||||
|
||||
async fn download_beatmap(&self, id: u64) -> Result<BeatmapContent> {
|
||||
let content = self
|
||||
fn parse_beatmap(content: impl AsRef<str>, id: Option<u64>) -> Result<BeatmapContent> {
|
||||
let content = content.as_ref();
|
||||
let metadata = osuparse::parse_beatmap(content)
|
||||
.map_err(|e| Error::msg(format!("Cannot parse metadata: {:?}", e)))?
|
||||
.metadata;
|
||||
Ok(BeatmapContent {
|
||||
id,
|
||||
metadata,
|
||||
content: Arc::new(Beatmap::parse(content.as_bytes())?),
|
||||
})
|
||||
}
|
||||
|
||||
/// Downloads the given osz and try to parse every osu file in there (limited to <1mb files)
|
||||
pub async fn download_osz_from_url(
|
||||
&self,
|
||||
url: impl reqwest::IntoUrl,
|
||||
) -> Result<Vec<BeatmapContent>> {
|
||||
let osz = self
|
||||
.client
|
||||
.borrow()
|
||||
.await?
|
||||
.get(&format!("https://osu.ppy.sh/osu/{}", id))
|
||||
.get(url)
|
||||
.send()
|
||||
.await?
|
||||
.bytes()
|
||||
.await?;
|
||||
let bm = BeatmapContent {
|
||||
id,
|
||||
content: Arc::new(Beatmap::parse(content.as_ref())?),
|
||||
};
|
||||
|
||||
let mut osz = zip::read::ZipArchive::new(std::io::Cursor::new(osz.as_ref()))?;
|
||||
let osu_files = osz.file_names().map(|v| v.to_owned()).collect::<Vec<_>>();
|
||||
let osu_files = osu_files
|
||||
.into_iter()
|
||||
.filter(|n| n.ends_with(".osu"))
|
||||
.filter_map(|v| {
|
||||
let mut v = osz.by_name(&v[..]).ok()?;
|
||||
if v.size() > 1024 * 1024
|
||||
/*1mb*/
|
||||
{
|
||||
return None;
|
||||
};
|
||||
let mut content = String::new();
|
||||
v.read_to_string(&mut content).pls_ok()?;
|
||||
Self::parse_beatmap(content, None).pls_ok()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Ok(osu_files)
|
||||
}
|
||||
|
||||
/// Downloads the beatmap from an URL and returns it.
|
||||
/// Does not deal with any caching.
|
||||
pub async fn download_beatmap_from_url(
|
||||
&self,
|
||||
url: impl reqwest::IntoUrl,
|
||||
id: Option<u64>,
|
||||
) -> Result<(BeatmapContent, String)> {
|
||||
let content = self
|
||||
.client
|
||||
.borrow()
|
||||
.await?
|
||||
.get(url)
|
||||
.send()
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
let bm = Self::parse_beatmap(&content, id)?;
|
||||
Ok((bm, content))
|
||||
}
|
||||
|
||||
async fn download_beatmap(&self, id: u64) -> Result<BeatmapContent> {
|
||||
let (bm, content) = self
|
||||
.download_beatmap_from_url(&format!("https://osu.ppy.sh/osu/{}", id), Some(id))
|
||||
.await?;
|
||||
|
||||
let mut bc = models::CachedBeatmapContent {
|
||||
beatmap_id: id as i64,
|
||||
cached_at: chrono::Utc::now(),
|
||||
content: content.as_ref().to_owned(),
|
||||
content: content.into_bytes(),
|
||||
};
|
||||
bc.store(&self.pool).await?;
|
||||
Ok(bm)
|
||||
|
@ -155,12 +215,7 @@ impl BeatmapCache {
|
|||
async fn get_beatmap_db(&self, id: u64) -> Result<Option<BeatmapContent>> {
|
||||
Ok(models::CachedBeatmapContent::by_id(id as i64, &self.pool)
|
||||
.await?
|
||||
.map(|v| {
|
||||
Ok(BeatmapContent {
|
||||
id,
|
||||
content: Arc::new(Beatmap::parse(&v.content[..])?),
|
||||
}) as Result<_>
|
||||
})
|
||||
.map(|v| Self::parse_beatmap(String::from_utf8(v.content)?, Some(id)))
|
||||
.transpose()?)
|
||||
}
|
||||
|
||||
|
|
|
@ -130,34 +130,55 @@ impl Difficulty {
|
|||
}
|
||||
|
||||
/// Format the difficulty info into a short summary.
|
||||
pub fn format_info(&self, mode: Mode, mods: Mods, original_beatmap: &Beatmap) -> String {
|
||||
let is_not_ranked = !matches!(original_beatmap.approval, ApprovalStatus::Ranked(_));
|
||||
let three_lines = is_not_ranked;
|
||||
pub fn format_info<'a>(
|
||||
&self,
|
||||
mode: Mode,
|
||||
mods: Mods,
|
||||
original_beatmap: impl Into<Option<&'a Beatmap>> + 'a,
|
||||
) -> String {
|
||||
let original_beatmap = original_beatmap.into();
|
||||
let is_not_ranked = !matches!(
|
||||
original_beatmap.map(|v| v.approval),
|
||||
Some(ApprovalStatus::Ranked(_))
|
||||
);
|
||||
let three_lines = original_beatmap.is_some() && is_not_ranked;
|
||||
let bpm = (self.bpm * 100.0).round() / 100.0;
|
||||
MessageBuilder::new()
|
||||
.push(format!(
|
||||
"[[Link]]({}) [[DL]]({}) [[Alt]]({}) (`{}`)",
|
||||
original_beatmap.link(),
|
||||
original_beatmap.download_link(false),
|
||||
original_beatmap.download_link(true),
|
||||
original_beatmap.short_link(Some(mode), Some(mods))
|
||||
))
|
||||
.push(
|
||||
original_beatmap
|
||||
.map(|original_beatmap| {
|
||||
format!(
|
||||
"[[Link]]({}) [[DL]]({}) [[Alt]]({}) (`{}`)",
|
||||
original_beatmap.link(),
|
||||
original_beatmap.download_link(false),
|
||||
original_beatmap.download_link(true),
|
||||
original_beatmap.short_link(Some(mode), Some(mods))
|
||||
)
|
||||
})
|
||||
.unwrap_or("**Uploaded**".to_owned()),
|
||||
)
|
||||
.push(if three_lines { "\n" } else { ", " })
|
||||
.push_bold(format!("{:.2}⭐", self.stars))
|
||||
.push(", ")
|
||||
.push(
|
||||
original_beatmap
|
||||
.difficulty
|
||||
.max_combo
|
||||
self.max_combo
|
||||
.map(|c| format!("max **{}x**, ", c))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
)
|
||||
.push(if is_not_ranked {
|
||||
format!("status **{}**, mode ", original_beatmap.approval)
|
||||
format!(
|
||||
"status **{}**, mode ",
|
||||
original_beatmap
|
||||
.map(|v| v.approval)
|
||||
.unwrap_or(ApprovalStatus::WIP)
|
||||
)
|
||||
} else {
|
||||
"".to_owned()
|
||||
})
|
||||
.push_bold_line(format_mode(mode, original_beatmap.mode))
|
||||
.push_bold_line(format_mode(
|
||||
mode,
|
||||
original_beatmap.map(|v| v.mode).unwrap_or(mode),
|
||||
))
|
||||
.push("CS")
|
||||
.push_bold(format!("{:.1}", self.cs))
|
||||
.push(", AR")
|
||||
|
|
|
@ -82,6 +82,8 @@ async fn main() {
|
|||
// Set up hooks
|
||||
#[cfg(feature = "osu")]
|
||||
handler.push_hook(youmubot_osu::discord::hook);
|
||||
#[cfg(feature = "osu")]
|
||||
handler.push_hook(youmubot_osu::discord::dot_osu_hook);
|
||||
#[cfg(feature = "codeforces")]
|
||||
handler.push_hook(youmubot_cf::InfoHook);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue