diff --git a/src/routes/register.rs b/src/routes/register.rs index a5062c3..f253911 100644 --- a/src/routes/register.rs +++ b/src/routes/register.rs @@ -1,12 +1,58 @@ -use std::time::Duration; +use std::{time::Duration, collections::HashSet}; use axum::{extract::State, Json}; use reqwest::StatusCode; -use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, Set, ActiveValue::NotSet}; +use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, Set, ActiveValue::NotSet, DatabaseConnection, DbErr}; use tracing::info; use crate::{AppState, proto::{self, Response}, entities}; +// TODO shouldn't be here probably +pub async fn fill_missing_skins(db: &DatabaseConnection) -> Result<(), DbErr> { + let mut users_with_skins = HashSet::new(); + + for skin in entities::property::Entity::find().all(db).await? { + users_with_skins.insert(skin.user_id); + } + + for user in entities::user::Entity::find().all(db).await? { + if users_with_skins.contains(&user.id) { + continue; + } + + info!("Updating skin for user {} ({})", user.name, user.uuid); + let url = format!("https://sessionserver.mojang.com/session/minecraft/profile/{}?unsigned=false", user.uuid.simple()); + let res = reqwest::Client::new().get(url.clone()) //TODO: needs trimmed uuid, is it trimmed by default? + .json(&()).send() + .await.map_err(|_| DbErr::Custom(format!("could not fetch profile for user {}", user.uuid)))? + .text().await.expect("invalid body on response"); + + let doc = serde_json::from_str::(&res) + .map_err(|_| DbErr::Json("invalid texture response".into()))?; + + let mut skin = proto::Property::default_skin(); + + for s in doc.properties.expect("missing properties field") { + if s.name == "textures" { + skin = s; + break; + } + } + + entities::property::Entity::insert( + entities::property::ActiveModel { + id: NotSet, + name: Set("textures".into()), + user_id: Set(user.id), + value: Set(skin.value), + signature: Set(skin.signature), + } + ).exec(db).await?; + } + + Ok(()) +} + //TODO: replace format! with axum's own pub async fn register_unmigrated(State(state): State, Json(payload): Json) -> Response { info!(target: "REGISTER", "[UNMIGRATED] called with {:?}", payload);