mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 16:58:55 +00:00
Use rosu_map to parse metadata and collect beatmap background from osz
This commit is contained in:
parent
64ff4b3ed8
commit
2315f40cf1
3 changed files with 45 additions and 26 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3294,6 +3294,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"rosu-map",
|
||||||
"rosu-pp",
|
"rosu-pp",
|
||||||
"rosu-v2",
|
"rosu-v2",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -17,6 +17,7 @@ regex = "1.5.6"
|
||||||
reqwest = "0.11.10"
|
reqwest = "0.11.10"
|
||||||
rosu-pp = "1.0"
|
rosu-pp = "1.0"
|
||||||
rosu-v2 = { git = "https://github.com/MaxOhn/rosu-v2", rev = "d2cd3ff8417e66890f0cd8ca38bc34717a9629dd" }
|
rosu-v2 = { git = "https://github.com/MaxOhn/rosu-v2", rev = "d2cd3ff8417e66890f0cd8ca38bc34717a9629dd" }
|
||||||
|
rosu-map = "0.1"
|
||||||
time = "0.3"
|
time = "0.3"
|
||||||
serde = { version = "1.0.137", features = ["derive"] }
|
serde = { version = "1.0.137", features = ["derive"] }
|
||||||
serenity = "0.12"
|
serenity = "0.12"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use osuparse::MetadataSection;
|
use rosu_map::Beatmap as BeatmapMetadata;
|
||||||
use rosu_pp::any::DifficultyAttributes;
|
|
||||||
use rosu_pp::Beatmap;
|
use rosu_pp::Beatmap;
|
||||||
|
|
||||||
use youmubot_db_sql::{models::osu as models, Pool};
|
use youmubot_db_sql::{models::osu as models, Pool};
|
||||||
|
@ -13,8 +13,18 @@ use crate::{models::Mode, mods::Mods};
|
||||||
/// the information collected from a download/Oppai request.
|
/// the information collected from a download/Oppai request.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BeatmapContent {
|
pub struct BeatmapContent {
|
||||||
pub metadata: MetadataSection,
|
pub metadata: BeatmapMetadata,
|
||||||
pub content: Arc<Beatmap>,
|
pub content: Arc<Beatmap>,
|
||||||
|
|
||||||
|
/// Beatmap background, if provided as part of an .osz
|
||||||
|
pub beatmap_background: Option<Arc<BeatmapBackground>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Beatmap background, if provided as part of an .osz
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BeatmapBackground {
|
||||||
|
pub filename: String,
|
||||||
|
pub content: Box<[u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// the output of "one" oppai run.
|
/// the output of "one" oppai run.
|
||||||
|
@ -25,16 +35,6 @@ pub struct BeatmapInfo {
|
||||||
pub stars: f64,
|
pub stars: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeatmapInfo {
|
|
||||||
fn extract(beatmap: &Beatmap, attrs: DifficultyAttributes) -> Self {
|
|
||||||
BeatmapInfo {
|
|
||||||
objects: beatmap.hit_objects.len(),
|
|
||||||
max_combo: attrs.max_combo() as usize,
|
|
||||||
stars: attrs.stars(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Accuracy {
|
pub enum Accuracy {
|
||||||
ByCount(u64, u64, u64, u64),
|
ByCount(u64, u64, u64, u64),
|
||||||
|
@ -148,14 +148,14 @@ impl BeatmapCache {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_beatmap(content: impl AsRef<str>) -> Result<BeatmapContent> {
|
fn parse_beatmap(content: impl AsRef<[u8]>) -> Result<BeatmapContent> {
|
||||||
let content = content.as_ref();
|
let content = content.as_ref();
|
||||||
let metadata = osuparse::parse_beatmap(content)
|
let metadata = BeatmapMetadata::from_bytes(content)
|
||||||
.map_err(|e| Error::msg(format!("Cannot parse metadata: {:?}", e)))?
|
.map_err(|e| Error::msg(format!("Cannot parse metadata: {:?}", e)))?;
|
||||||
.metadata;
|
|
||||||
Ok(BeatmapContent {
|
Ok(BeatmapContent {
|
||||||
metadata,
|
metadata,
|
||||||
content: Arc::new(Beatmap::from_bytes(content.as_bytes())?),
|
content: Arc::new(Beatmap::from_bytes(content)?),
|
||||||
|
beatmap_background: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,8 @@ impl BeatmapCache {
|
||||||
|
|
||||||
let mut osz = zip::read::ZipArchive::new(std::io::Cursor::new(osz.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 = osz.file_names().map(|v| v.to_owned()).collect::<Vec<_>>();
|
||||||
let osu_files = osu_files
|
let mut backgrounds: HashMap<String, Option<Arc<BeatmapBackground>>> = HashMap::new();
|
||||||
|
let mut osu_files = osu_files
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|n| n.ends_with(".osu"))
|
.filter(|n| n.ends_with(".osu"))
|
||||||
.filter_map(|v| {
|
.filter_map(|v| {
|
||||||
|
@ -186,11 +187,27 @@ impl BeatmapCache {
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let mut content = String::new();
|
let mut content = Vec::<u8>::new();
|
||||||
v.read_to_string(&mut content).pls_ok()?;
|
v.read_to_end(&mut content).pls_ok()?;
|
||||||
Self::parse_beatmap(content).pls_ok()
|
Self::parse_beatmap(content).pls_ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
for beatmap in &mut osu_files {
|
||||||
|
if beatmap.metadata.background_file != "" {
|
||||||
|
let bg = backgrounds
|
||||||
|
.entry(beatmap.metadata.background_file.clone())
|
||||||
|
.or_insert_with(|| {
|
||||||
|
let mut file = osz.by_name(&beatmap.metadata.background_file).ok()?;
|
||||||
|
let mut content = Vec::new();
|
||||||
|
file.read_to_end(&mut content).ok()?;
|
||||||
|
Some(Arc::new(BeatmapBackground {
|
||||||
|
filename: beatmap.metadata.background_file.clone(),
|
||||||
|
content: content.into_boxed_slice(),
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
beatmap.beatmap_background = bg.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(osu_files)
|
Ok(osu_files)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +216,7 @@ impl BeatmapCache {
|
||||||
pub async fn download_beatmap_from_url(
|
pub async fn download_beatmap_from_url(
|
||||||
&self,
|
&self,
|
||||||
url: impl reqwest::IntoUrl,
|
url: impl reqwest::IntoUrl,
|
||||||
) -> Result<(BeatmapContent, String)> {
|
) -> Result<(BeatmapContent, Vec<u8>)> {
|
||||||
let content = self
|
let content = self
|
||||||
.client
|
.client
|
||||||
.borrow()
|
.borrow()
|
||||||
|
@ -207,10 +224,10 @@ impl BeatmapCache {
|
||||||
.get(url)
|
.get(url)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.text()
|
.bytes()
|
||||||
.await?;
|
.await?;
|
||||||
let bm = Self::parse_beatmap(&content)?;
|
let bm = Self::parse_beatmap(&content)?;
|
||||||
Ok((bm, content))
|
Ok((bm, content.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn download_beatmap(&self, id: u64) -> Result<BeatmapContent> {
|
async fn download_beatmap(&self, id: u64) -> Result<BeatmapContent> {
|
||||||
|
@ -221,7 +238,7 @@ impl BeatmapCache {
|
||||||
let mut bc = models::CachedBeatmapContent {
|
let mut bc = models::CachedBeatmapContent {
|
||||||
beatmap_id: id as i64,
|
beatmap_id: id as i64,
|
||||||
cached_at: chrono::Utc::now(),
|
cached_at: chrono::Utc::now(),
|
||||||
content: content.into_bytes(),
|
content,
|
||||||
};
|
};
|
||||||
bc.store(&self.pool).await?;
|
bc.store(&self.pool).await?;
|
||||||
Ok(bm)
|
Ok(bm)
|
||||||
|
@ -230,7 +247,7 @@ impl BeatmapCache {
|
||||||
async fn get_beatmap_db(&self, id: u64) -> Result<Option<BeatmapContent>> {
|
async fn get_beatmap_db(&self, id: u64) -> Result<Option<BeatmapContent>> {
|
||||||
models::CachedBeatmapContent::by_id(id as i64, &self.pool)
|
models::CachedBeatmapContent::by_id(id as i64, &self.pool)
|
||||||
.await?
|
.await?
|
||||||
.map(|v| Self::parse_beatmap(String::from_utf8(v.content)?))
|
.map(|v| Self::parse_beatmap(v.content))
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue