Store osu! user username

This commit is contained in:
Natsu Kagami 2024-02-04 23:24:28 +01:00
parent 85954639d7
commit f7ea23ed3b
Signed by: nki
GPG key ID: 55A032EB38B49ADB
4 changed files with 34 additions and 11 deletions

View file

@ -0,0 +1,4 @@
-- Add migration script here
ALTER TABLE osu_users
ADD COLUMN username TEXT NULL DEFAULT NULL;

View file

@ -5,6 +5,7 @@ use sqlx::{query, query_as, Executor};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OsuUser { pub struct OsuUser {
pub user_id: i64, pub user_id: i64,
pub username: Option<String>, // should always be there
pub id: i64, pub id: i64,
pub last_update: DateTime, pub last_update: DateTime,
pub pp_std: Option<f64>, pub pp_std: Option<f64>,
@ -25,6 +26,7 @@ impl OsuUser {
Self, Self,
r#"SELECT r#"SELECT
user_id as "user_id: i64", user_id as "user_id: i64",
username,
id as "id: i64", id as "id: i64",
last_update as "last_update: DateTime", last_update as "last_update: DateTime",
pp_std, pp_taiko, pp_mania, pp_catch, pp_std, pp_taiko, pp_mania, pp_catch,
@ -46,6 +48,7 @@ impl OsuUser {
Self, Self,
r#"SELECT r#"SELECT
user_id as "user_id: i64", user_id as "user_id: i64",
username,
id as "id: i64", id as "id: i64",
last_update as "last_update: DateTime", last_update as "last_update: DateTime",
pp_std, pp_taiko, pp_mania, pp_catch, pp_std, pp_taiko, pp_mania, pp_catch,
@ -67,6 +70,7 @@ impl OsuUser {
Self, Self,
r#"SELECT r#"SELECT
user_id as "user_id: i64", user_id as "user_id: i64",
username,
id as "id: i64", id as "id: i64",
last_update as "last_update: DateTime", last_update as "last_update: DateTime",
pp_std, pp_taiko, pp_mania, pp_catch, pp_std, pp_taiko, pp_mania, pp_catch,
@ -86,8 +90,8 @@ impl OsuUser {
{ {
query!( query!(
r#"INSERT r#"INSERT
INTO osu_users(user_id, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures) INTO osu_users(user_id, username, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures)
VALUES(?, ?, ?, ?, ?, ?, ?, ?) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (user_id) WHERE id = ? DO UPDATE ON CONFLICT (user_id) WHERE id = ? DO UPDATE
SET SET
last_update = excluded.last_update, last_update = excluded.last_update,
@ -98,6 +102,7 @@ impl OsuUser {
failures = excluded.failures failures = excluded.failures
"#, "#,
self.user_id, self.user_id,
self.username,
self.id, self.id,
self.last_update, self.last_update,
self.pp_std, self.pp_std,

View file

@ -1,3 +1,5 @@
use std::borrow::Cow;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use youmubot_db_sql::{models::osu as models, models::osu_user as model, Pool}; use youmubot_db_sql::{models::osu as models, models::osu_user as model, Pool};
@ -151,6 +153,7 @@ impl OsuUserBests {
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OsuUser { pub struct OsuUser {
pub user_id: UserId, pub user_id: UserId,
pub username: Cow<'static, str>,
pub id: u64, pub id: u64,
pub last_update: DateTime<Utc>, pub last_update: DateTime<Utc>,
pub pp: [Option<f64>; 4], pub pp: [Option<f64>; 4],
@ -162,6 +165,7 @@ impl From<OsuUser> for model::OsuUser {
fn from(u: OsuUser) -> Self { fn from(u: OsuUser) -> Self {
Self { Self {
user_id: u.user_id.0 as i64, user_id: u.user_id.0 as i64,
username: Some(u.username.into_owned()),
id: u.id as i64, id: u.id as i64,
last_update: u.last_update, last_update: u.last_update,
pp_std: u.pp[Mode::Std as usize], pp_std: u.pp[Mode::Std as usize],
@ -177,6 +181,10 @@ impl From<model::OsuUser> for OsuUser {
fn from(u: model::OsuUser) -> Self { fn from(u: model::OsuUser) -> Self {
Self { Self {
user_id: UserId(u.user_id as u64), user_id: UserId(u.user_id as u64),
username: u
.username
.map(|v| Cow::Owned(v))
.unwrap_or("unknown".into()),
id: u.id as u64, id: u.id as u64,
last_update: u.last_update, last_update: u.last_update,
pp: [0, 1, 2, 3].map(|v| match Mode::from(v) { pp: [0, 1, 2, 3].map(|v| match Mode::from(v) {

View file

@ -2,7 +2,7 @@ use crate::{
discord::beatmap_cache::BeatmapMetaCache, discord::beatmap_cache::BeatmapMetaCache,
discord::display::ScoreListStyle, discord::display::ScoreListStyle,
discord::oppai_cache::{BeatmapCache, BeatmapInfo}, discord::oppai_cache::{BeatmapCache, BeatmapInfo},
models::{Beatmap, Mode, Mods, User}, models::{self, Beatmap, Mode, Mods, User},
request::{BeatmapRequestKind, UserID}, request::{BeatmapRequestKind, UserID},
Client as OsuHttpClient, Client as OsuHttpClient,
}; };
@ -210,12 +210,13 @@ pub async fn save(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
.await?; .await?;
return Ok(()); return Ok(());
} }
add_user(msg.author.id, u.id, &data).await?; let username = u.username.clone();
add_user(msg.author.id, u, &data).await?;
msg.reply( msg.reply(
&ctx, &ctx,
MessageBuilder::new() MessageBuilder::new()
.push("user has been set to ") .push("user has been set to ")
.push_mono_safe(u.username) .push_mono_safe(username)
.build(), .build(),
) )
.await?; .await?;
@ -238,16 +239,16 @@ pub async fn forcesave(ctx: &Context, msg: &Message, mut args: Args) -> CommandR
let osu = data.get::<OsuClient>().unwrap(); let osu = data.get::<OsuClient>().unwrap();
let target = args.single::<serenity::model::id::UserId>()?; let target = args.single::<serenity::model::id::UserId>()?;
let user = args.quoted().trimmed().single::<String>()?; let username = args.quoted().trimmed().single::<String>()?;
let user: Option<User> = osu.user(UserID::Auto(user), |f| f).await?; let user: Option<User> = osu.user(UserID::Auto(username.clone()), |f| f).await?;
match user { match user {
Some(u) => { Some(u) => {
add_user(target, u.id, &data).await?; add_user(target, u, &data).await?;
msg.reply( msg.reply(
&ctx, &ctx,
MessageBuilder::new() MessageBuilder::new()
.push("user has been set to ") .push("user has been set to ")
.push_mono_safe(u.username) .push_mono_safe(username)
.build(), .build(),
) )
.await?; .await?;
@ -259,10 +260,15 @@ pub async fn forcesave(ctx: &Context, msg: &Message, mut args: Args) -> CommandR
Ok(()) Ok(())
} }
async fn add_user(target: serenity::model::id::UserId, user_id: u64, data: &TypeMap) -> Result<()> { async fn add_user(
target: serenity::model::id::UserId,
user: models::User,
data: &TypeMap,
) -> Result<()> {
let u = OsuUser { let u = OsuUser {
user_id: target, user_id: target,
id: user_id, username: user.username.into(),
id: user.id,
failures: 0, failures: 0,
last_update: chrono::Utc::now(), last_update: chrono::Utc::now(),
pp: [None, None, None, None], pp: [None, None, None, None],