mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 02:00:46 +00:00
add w2l results to leaderboard (wip)
This commit is contained in:
1 parent
eeef9cc916
commit
b59d19a7c8
7 files changed
+193
-1
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,81 @@
|
||||
use anyhow::anyhow;
|
||||
use crate::util::anyhow_result::AnyhowResult;
|
||||
use log::warn;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct W2lLeaderboardRecordForList {
|
||||
pub username: String,
|
||||
pub display_name: String,
|
||||
pub gravatar_hash: String,
|
||||
pub creator_user_token: String,
|
||||
pub uploaded_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct W2lLeaderboardRecordForListRaw {
|
||||
pub username: String,
|
||||
pub display_name: String,
|
||||
pub gravatar_hash: String,
|
||||
pub creator_user_token: String,
|
||||
pub uploaded_count: i64,
|
||||
}
|
||||
|
||||
// NB: This may need to become an offline query if it is expensive.
|
||||
pub async fn calculate_w2l_template_leaderboard(
|
||||
mysql_pool: &MySqlPool
|
||||
) -> AnyhowResult<Vec<W2lLeaderboardRecordForList>> {
|
||||
let maybe_results = sqlx::query_as!(
|
||||
W2lLeaderboardRecordForListRaw,
|
||||
r#"
|
||||
SELECT
|
||||
users.username,
|
||||
users.display_name,
|
||||
users.email_gravatar_hash as gravatar_hash,
|
||||
creator_user_token,
|
||||
count(*) as uploaded_count
|
||||
FROM w2l_templates
|
||||
JOIN users
|
||||
ON
|
||||
users.token = creator_user_token
|
||||
WHERE
|
||||
is_public_listing_approved IS TRUE
|
||||
AND
|
||||
users.is_banned IS FALSE
|
||||
GROUP BY creator_user_token
|
||||
ORDER BY uploaded_count desc
|
||||
LIMIT 25;
|
||||
"#,
|
||||
)
|
||||
.fetch_all(mysql_pool)
|
||||
.await;
|
||||
|
||||
let results : Vec<W2lLeaderboardRecordForListRaw> = match maybe_results {
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("Error: {:?}", err);
|
||||
|
||||
match err {
|
||||
RowNotFound => {
|
||||
return Ok(Vec::new());
|
||||
},
|
||||
_ => {
|
||||
warn!("w2l leaderboard query error: {:?}", err);
|
||||
return Err(anyhow!("w2l leaderboard query error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(results.into_iter()
|
||||
.map(|result| {
|
||||
W2lLeaderboardRecordForList {
|
||||
username: result.username.to_string(),
|
||||
display_name: result.display_name.to_string(),
|
||||
gravatar_hash: result.gravatar_hash.to_string(),
|
||||
creator_user_token: result.creator_user_token.to_string(),
|
||||
uploaded_count: result.uploaded_count,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<W2lLeaderboardRecordForList>>())
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
pub mod badges;
|
||||
pub mod calculate_tts_model_leaderboard;
|
||||
pub mod calculate_w2l_template_leaderboard;
|
||||
pub mod create_session;
|
||||
pub mod delete_tts_model;
|
||||
pub mod delete_tts_result;
|
||||
pub mod delete_w2l_result;
|
||||
pub mod delete_w2l_template;
|
||||
pub mod get_user_profile_by_username;
|
||||
pub mod list_ip_bans;
|
||||
pub mod list_tts_models;
|
||||
pub mod list_user_badges;
|
||||
@@ -11,6 +14,5 @@ pub mod list_user_roles;
|
||||
pub mod list_w2l_templates;
|
||||
pub mod query_tts_model;
|
||||
pub mod query_tts_result;
|
||||
pub mod get_user_profile_by_username;
|
||||
pub mod query_w2l_result;
|
||||
pub mod query_w2l_template;
|
||||
@@ -0,0 +1,101 @@
|
||||
use actix_http::Error;
|
||||
use actix_http::http::header;
|
||||
use actix_web::cookie::Cookie;
|
||||
use actix_web::dev::HttpResponseBuilder;
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{Responder, web, HttpResponse, error, HttpRequest, HttpMessage};
|
||||
use chrono::{DateTime, Utc};
|
||||
use crate::AnyhowResult;
|
||||
use crate::database::queries::calculate_w2l_template_leaderboard::W2lLeaderboardRecordForList;
|
||||
use crate::database::queries::calculate_w2l_template_leaderboard::calculate_w2l_template_leaderboard;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
use derive_more::{Display, Error};
|
||||
use log::{info, warn, log};
|
||||
use regex::Regex;
|
||||
use sqlx::MySqlPool;
|
||||
use sqlx::error::DatabaseError;
|
||||
use sqlx::error::Error::Database;
|
||||
use sqlx::mysql::MySqlDatabaseError;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LeaderboardResponse {
|
||||
success: bool,
|
||||
w2l_leaderboard: Vec<W2lLeaderboardRecordForList>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct LeaderboardErrorResponse {
|
||||
pub success: bool,
|
||||
pub error_type: LeaderboardErrorType,
|
||||
pub error_message: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize)]
|
||||
pub enum LeaderboardErrorType {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl LeaderboardErrorResponse {
|
||||
fn server_error() -> Self {
|
||||
Self {
|
||||
success: false,
|
||||
error_type: LeaderboardErrorType::ServerError,
|
||||
error_message: "server error".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for LeaderboardErrorResponse {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match self.error_type {
|
||||
LeaderboardErrorType::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for LeaderboardErrorResponse {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.error_type)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn leaderboard_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, LeaderboardErrorResponse> {
|
||||
|
||||
// TODO: Fire off both requests in parallel.
|
||||
let maybe_results =
|
||||
calculate_w2l_template_leaderboard(&server_state.mysql_pool).await;
|
||||
|
||||
|
||||
let results = match maybe_results {
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Query error: {:?}", e);
|
||||
return Err(LeaderboardErrorResponse::server_error());
|
||||
}
|
||||
};
|
||||
|
||||
let response = LeaderboardResponse {
|
||||
success: true,
|
||||
w2l_leaderboard: results,
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| LeaderboardErrorResponse::server_error())?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod get_leaderboard;
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod default_route_404;
|
||||
pub mod events;
|
||||
pub mod leaderboard;
|
||||
pub mod misc;
|
||||
pub mod moderation;
|
||||
pub mod root_index;
|
||||
|
||||
@@ -106,6 +106,7 @@ use sqlx::mysql::MySqlPoolOptions;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crate::http_server::endpoints::moderation::users::list_users::list_users_handler;
|
||||
use crate::http_server::endpoints::leaderboard::get_leaderboard::leaderboard_handler;
|
||||
|
||||
// TODO TODO TODO TODO
|
||||
// TODO TODO TODO TODO
|
||||
@@ -591,6 +592,11 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()>
|
||||
.route(web::get().to(list_events_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
.service(
|
||||
web::resource("/leaderboard")
|
||||
.route(web::get().to(leaderboard_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
.service(get_root_index)
|
||||
.service(enable_alpha_handler)
|
||||
.service(enable_alpha_easy_handler)
|
||||
|
||||
Reference in new issue
Block a user