mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-20 09:18:54 +00:00
333 lines
8.9 KiB
Rust
333 lines
8.9 KiB
Rust
use crate::models::*;
|
|
|
|
pub struct LastBeatmap {
|
|
pub channel_id: i64,
|
|
pub beatmap: Vec<u8>,
|
|
pub mode: u8,
|
|
}
|
|
|
|
impl LastBeatmap {
|
|
/// Get a [`LastBeatmap`] by the channel id.
|
|
pub async fn by_channel_id(
|
|
id: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Option<LastBeatmap>> {
|
|
let m = query_as!(
|
|
LastBeatmap,
|
|
r#"SELECT
|
|
channel_id as "channel_id: i64",
|
|
beatmap,
|
|
mode as "mode: u8"
|
|
FROM osu_last_beatmaps
|
|
WHERE channel_id = ?"#,
|
|
id
|
|
)
|
|
.fetch_optional(conn)
|
|
.await?;
|
|
Ok(m)
|
|
}
|
|
}
|
|
|
|
impl LastBeatmap {
|
|
/// Store the value.
|
|
pub async fn store(&self, conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
query!(
|
|
r#"INSERT INTO
|
|
osu_last_beatmaps (channel_id, beatmap, mode)
|
|
VALUES
|
|
(?, ?, ?)
|
|
ON CONFLICT (channel_id) DO UPDATE
|
|
SET
|
|
beatmap = excluded.beatmap,
|
|
mode = excluded.mode"#,
|
|
self.channel_id,
|
|
self.beatmap,
|
|
self.mode,
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct UserBestScore {
|
|
pub beatmap_id: i64,
|
|
pub mode: u8,
|
|
pub user_id: i64,
|
|
pub mods: i64,
|
|
|
|
pub cached_at: DateTime,
|
|
/// To be deserialized by `bincode`
|
|
pub score: Vec<u8>,
|
|
}
|
|
|
|
impl UserBestScore {
|
|
/// Get a list of scores by the given map and user.
|
|
pub async fn by_map_and_user(
|
|
beatmap: i64,
|
|
mode: u8,
|
|
user: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Vec<Self>> {
|
|
query_as!(
|
|
UserBestScore,
|
|
r#"SELECT
|
|
beatmap_id as "beatmap_id: i64",
|
|
mode as "mode: u8",
|
|
user_id as "user_id: i64",
|
|
mods as "mods: i64",
|
|
cached_at as "cached_at: DateTime",
|
|
score as "score: Vec<u8>"
|
|
FROM osu_user_best_scores
|
|
WHERE
|
|
beatmap_id = ?
|
|
AND mode = ?
|
|
AND user_id = ?"#,
|
|
beatmap,
|
|
mode,
|
|
user
|
|
)
|
|
.fetch_all(conn)
|
|
.await
|
|
.map_err(Error::from)
|
|
}
|
|
/// Get a list of scores by the given map.
|
|
pub async fn by_map(
|
|
beatmap: i64,
|
|
mode: u8,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Vec<Self>> {
|
|
query_as!(
|
|
UserBestScore,
|
|
r#"SELECT
|
|
beatmap_id as "beatmap_id: i64",
|
|
mode as "mode: u8",
|
|
user_id as "user_id: i64",
|
|
mods as "mods: i64",
|
|
cached_at as "cached_at: DateTime",
|
|
score as "score: Vec<u8>"
|
|
FROM osu_user_best_scores
|
|
WHERE
|
|
beatmap_id = ?
|
|
AND mode = ?"#,
|
|
beatmap,
|
|
mode
|
|
)
|
|
.fetch_all(conn)
|
|
.await
|
|
.map_err(Error::from)
|
|
}
|
|
}
|
|
|
|
impl UserBestScore {
|
|
pub async fn store(&mut self, conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
self.cached_at = chrono::Utc::now();
|
|
query!(
|
|
r#"
|
|
INSERT INTO
|
|
osu_user_best_scores (beatmap_id, mode, user_id, mods, cached_at, score)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT (beatmap_id, mode, user_id, mods)
|
|
DO UPDATE
|
|
SET
|
|
cached_at = excluded.cached_at,
|
|
score = excluded.score
|
|
"#,
|
|
self.beatmap_id,
|
|
self.mode,
|
|
self.user_id,
|
|
self.mods,
|
|
self.cached_at,
|
|
self.score
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn clear_user(
|
|
user_id: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<()> {
|
|
query!(
|
|
"DELETE FROM osu_user_best_scores WHERE user_id = ?",
|
|
user_id
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct CachedBeatmap {
|
|
pub beatmap_id: i64,
|
|
pub mode: u8,
|
|
pub cached_at: DateTime,
|
|
pub beatmap: Vec<u8>,
|
|
}
|
|
|
|
impl CachedBeatmap {
|
|
/// Get a cached beatmap by its id.
|
|
pub async fn by_id(
|
|
id: i64,
|
|
mode: u8,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Option<Self>> {
|
|
query_as!(
|
|
Self,
|
|
r#"SELECT
|
|
beatmap_id as "beatmap_id: i64",
|
|
mode as "mode: u8",
|
|
cached_at as "cached_at: DateTime",
|
|
beatmap as "beatmap: Vec<u8>"
|
|
FROM osu_cached_beatmaps
|
|
WHERE
|
|
beatmap_id = ?
|
|
AND mode = ?
|
|
"#,
|
|
id,
|
|
mode
|
|
)
|
|
.fetch_optional(conn)
|
|
.await
|
|
.map_err(Error::from)
|
|
}
|
|
|
|
pub async fn by_beatmapset(
|
|
beatmapset: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Vec<Self>> {
|
|
query_as!(
|
|
Self,
|
|
r#"SELECT
|
|
beatmap.beatmap_id as "beatmap_id: i64",
|
|
beatmap.mode as "mode: u8",
|
|
beatmap.cached_at as "cached_at: DateTime",
|
|
beatmap.beatmap as "beatmap: Vec<u8>"
|
|
FROM osu_cached_beatmapsets
|
|
INNER JOIN osu_cached_beatmaps AS beatmap
|
|
ON osu_cached_beatmapsets.beatmap_id = beatmap.beatmap_id
|
|
AND osu_cached_beatmapsets.mode = beatmap.mode
|
|
WHERE
|
|
beatmapset_id = ?
|
|
"#,
|
|
beatmapset
|
|
)
|
|
.fetch_all(conn)
|
|
.await
|
|
.map_err(Error::from)
|
|
}
|
|
|
|
/// Delete all of the caches.
|
|
pub async fn clear_all(conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
conn.execute("DELETE FROM osu_cached_beatmapsets; DELETE FROM osu_cached_beatmaps;")
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl CachedBeatmap {
|
|
pub async fn store(&mut self, conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
self.cached_at = chrono::Utc::now();
|
|
query!(
|
|
r#"
|
|
INSERT INTO
|
|
osu_cached_beatmaps (beatmap_id, mode, cached_at, beatmap)
|
|
VALUES
|
|
(?, ?, ?, ?)
|
|
ON CONFLICT (beatmap_id, mode)
|
|
DO UPDATE
|
|
SET
|
|
cached_at = excluded.cached_at,
|
|
beatmap = excluded.beatmap
|
|
"#,
|
|
self.beatmap_id,
|
|
self.mode,
|
|
self.cached_at,
|
|
self.beatmap
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn link_beatmapset(
|
|
&self,
|
|
beatmapset_id: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<()> {
|
|
query!(
|
|
r#"INSERT INTO osu_cached_beatmapsets(beatmapset_id, beatmap_id, mode)
|
|
VALUES (?, ?, ?)
|
|
ON CONFLICT DO NOTHING"#,
|
|
beatmapset_id,
|
|
self.beatmap_id,
|
|
self.mode,
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct CachedBeatmapContent {
|
|
pub beatmap_id: i64,
|
|
pub cached_at: DateTime,
|
|
pub content: Vec<u8>,
|
|
}
|
|
|
|
impl CachedBeatmapContent {
|
|
/// Get a cached beatmap by its id.
|
|
pub async fn by_id(
|
|
id: i64,
|
|
conn: impl Executor<'_, Database = Database>,
|
|
) -> Result<Option<Self>> {
|
|
query_as!(
|
|
Self,
|
|
r#"SELECT
|
|
beatmap_id as "beatmap_id: i64",
|
|
cached_at as "cached_at: DateTime",
|
|
content as "content: Vec<u8>"
|
|
FROM osu_cached_beatmap_contents
|
|
WHERE
|
|
beatmap_id = ? "#,
|
|
id,
|
|
)
|
|
.fetch_optional(conn)
|
|
.await
|
|
.map_err(Error::from)
|
|
}
|
|
|
|
/// Delete all of the caches.
|
|
pub async fn clear_all(conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
conn.execute("DELETE FROM osu_cached_beatmap_contents;")
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl CachedBeatmapContent {
|
|
pub async fn store(&mut self, conn: impl Executor<'_, Database = Database>) -> Result<()> {
|
|
self.cached_at = chrono::Utc::now();
|
|
query!(
|
|
r#"
|
|
INSERT INTO
|
|
osu_cached_beatmap_contents (beatmap_id, cached_at, content)
|
|
VALUES
|
|
(?, ?, ?)
|
|
ON CONFLICT (beatmap_id)
|
|
DO UPDATE
|
|
SET
|
|
cached_at = excluded.cached_at,
|
|
content = excluded.content
|
|
"#,
|
|
self.beatmap_id,
|
|
self.cached_at,
|
|
self.content
|
|
)
|
|
.execute(conn)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|