From 9cf0ee89249b8c87f7df873d5ebf4ab894044800 Mon Sep 17 00:00:00 2001 From: Ethan O'Brien Date: Fri, 3 Jul 2026 18:45:09 -0500 Subject: [PATCH] Properly scope getting guest details --- src/router.rs | 1 + src/router/clear_rate.rs | 9 +-- src/router/event_ranking.rs | 5 +- src/router/friend.rs | 17 ++++-- src/router/global.rs | 90 ++------------------------- src/router/live.rs | 9 +-- src/router/tools/guest.rs | 119 ++++++++++++++++++++++++++++++++++++ src/router/tools/mod.rs | 1 + src/router/user.rs | 7 ++- 9 files changed, 154 insertions(+), 104 deletions(-) create mode 100644 src/router/tools/guest.rs create mode 100644 src/router/tools/mod.rs diff --git a/src/router.rs b/src/router.rs index 72e099b..e71869a 100644 --- a/src/router.rs +++ b/src/router.rs @@ -30,6 +30,7 @@ pub mod location; pub mod event_ranking; pub mod asset_lists; mod master_data; +mod tools; use actix_web::{ HttpResponse, diff --git a/src/router/clear_rate.rs b/src/router/clear_rate.rs index eb2cd93..3e674c3 100644 --- a/src/router/clear_rate.rs +++ b/src/router/clear_rate.rs @@ -1,13 +1,14 @@ -use jzon::{object, array, JsonValue}; -use actix_web::{HttpRequest, HttpResponse, Responder, http::header::ContentType}; +use jzon::{array, object, JsonValue}; +use actix_web::{http::header::ContentType, HttpRequest, HttpResponse, Responder}; use rusqlite::params; use std::sync::Mutex; use lazy_static::lazy_static; use crate::encryption; use crate::sql::SQLite; -use crate::router::{global, databases}; +use crate::router::{databases, global}; use crate::include_file; +use crate::router::tools::guest; trait SqlClearRate { fn get_live_data(&self, id: i64) -> Result; @@ -243,7 +244,7 @@ pub async fn ranking(req: HttpRequest, body: String) -> impl Responder { let mut rank = array![]; for (i, data) in scores.members().enumerate() { - let user = global::get_user(data["user"].as_i64().unwrap(), &object![], false); + let user = guest::get_user(data["user"].as_i64().unwrap(), &object![], guest::UserView::Ranking); rank.push(object!{ rank: i + 1, user: user["user"].clone(), diff --git a/src/router/event_ranking.rs b/src/router/event_ranking.rs index 1acd174..5238f34 100644 --- a/src/router/event_ranking.rs +++ b/src/router/event_ranking.rs @@ -1,10 +1,11 @@ -use jzon::{object, array, JsonValue}; +use jzon::{array, object, JsonValue}; use rusqlite::params; use std::sync::Mutex; use lazy_static::lazy_static; use crate::sql::SQLite; use crate::router::global; +use crate::router::tools::guest; lazy_static! { static ref DATABASE: SQLite = SQLite::new("event_ranking.db", setup_tables); @@ -81,7 +82,7 @@ fn get_json() -> JsonValue { let mut i = 1; for score in scores.members() { - let user = global::get_user(score["user"].as_i64().unwrap(), &object![], false); + let user = guest::get_user(score["user"].as_i64().unwrap(), &object![], guest::UserView::Ranking); rv[event.to_string()].push(object!{ "rank": i, "user_detail": user, diff --git a/src/router/friend.rs b/src/router/friend.rs index 6a070f4..ab05d31 100644 --- a/src/router/friend.rs +++ b/src/router/friend.rs @@ -1,8 +1,9 @@ -use jzon::{object, array}; +use jzon::{array, object}; use actix_web::{web, HttpRequest, Responder}; -use crate::router::{userdata, global}; +use crate::router::{global, userdata}; use crate::encryption; +use crate::router::tools::guest; pub const FRIEND_LIMIT: usize = 40; @@ -39,7 +40,7 @@ async fn friend(req: HttpRequest, body: String) -> impl Responder { }; for uid in rv_data.members() { - let mut user = global::get_user(uid.as_i64().unwrap(), &friends, false); + let mut user = guest::get_user(uid.as_i64().unwrap(), &friends, guest::UserView::Card); user["user"]["last_login_time"] = global::set_time(user["user"]["last_login_time"].as_u64().unwrap_or(0), user_id, false).into(); rv.push(user).unwrap(); } @@ -69,7 +70,7 @@ async fn recommend(req: HttpRequest, body: String) -> impl Responder { let mut rv = array![]; for uid in random.members() { - let mut user = global::get_user(uid.as_i64().unwrap(), &friends, false); + let mut user = guest::get_user(uid.as_i64().unwrap(), &friends, guest::UserView::Card); if user["user"]["friend_request_disabled"] == 1 || user.is_empty() { continue; } @@ -88,9 +89,13 @@ async fn search(req: HttpRequest, body: String) -> impl Responder { let friends = userdata::get_acc_friends(&key); let uid = body["user_id"].as_i64().unwrap(); - let user = global::get_user(uid, &friends, false); + let user = guest::get_user(uid, &friends, guest::UserView::Detail); - global::api(&req, Some(user)) + global::api(&req, Some(if user.is_empty() { + array![] + } else { + user + })) } async fn request(req: HttpRequest, body: String) -> impl Responder { diff --git a/src/router/global.rs b/src/router/global.rs index cf1ea97..87ec9f7 100644 --- a/src/router/global.rs +++ b/src/router/global.rs @@ -1,15 +1,15 @@ use jzon::{array, object, JsonValue}; use actix_web::{ - HttpResponse, + http::header::{HeaderMap, HeaderValue}, HttpRequest, - http::header::{HeaderValue, HeaderMap} + HttpResponse }; use std::time::{SystemTime, UNIX_EPOCH}; -use base64::{Engine as _, engine::general_purpose}; +use base64::{engine::general_purpose, Engine as _}; use uuid::Uuid; use crate::encryption; -use crate::router::{userdata, items}; +use crate::router::{items, userdata}; use crate::database::gree; use crate::runtime::get_easter_mode; @@ -250,7 +250,6 @@ pub fn send(mut data: JsonValue, uid: i64, headers: &HeaderMap) -> HttpResponse HttpResponse::Ok().body(resp) } -// Standard api response wrapper. None becomes the generic error response pub fn api(req: &HttpRequest, data: Option) -> HttpResponse { let blank_header = HeaderValue::from_static(""); let uid = req.headers().get("aoharu-user-id").unwrap_or(&blank_header).to_str().unwrap_or("").parse::().unwrap_or(0); @@ -300,7 +299,7 @@ pub fn get_card(id: i64, user: &JsonValue) -> JsonValue { object!{} } -fn get_cards(arr: JsonValue, user: &JsonValue) -> JsonValue { +pub(crate) fn get_cards(arr: JsonValue, user: &JsonValue) -> JsonValue { let mut rv = array![]; for data in arr.members() { let to_push = get_card(data.as_i64().unwrap_or(0), user); @@ -311,82 +310,3 @@ fn get_cards(arr: JsonValue, user: &JsonValue) -> JsonValue { } rv } - -fn get_clear_count(user: &JsonValue, level: i32) -> i64 { - let mut rv = 0; - for current in user["live_list"].members() { - if current["level"] == level { - rv += 1; - } - } - rv -} - -fn get_full_combo_count(user: &JsonValue, level: i32) -> i64 { - let mut rv = 0; - for current in user["live_mission_list"].members() { - if current["clear_master_live_mission_ids"].contains(20 + level) { - rv += 1; - } - } - rv -} - -fn get_perfect_count(user: &JsonValue, level: i32) -> i64 { - let mut rv = 0; - for current in user["live_mission_list"].members() { - if current["clear_master_live_mission_ids"].contains(40 + level) { - rv += 1; - } - } - rv -} - -pub fn get_user(id: i64, friends: &JsonValue, live_data: bool) -> JsonValue { - let user = userdata::get_acc_from_uid(id); - if !user["error"].is_empty() { - return object!{}; - } - - let mut rv = object!{ - user: user["user"].clone(), - main_deck_detail: { - total_power: 0, //how to calculate? - deck: user["deck_list"][user["user"]["main_deck_slot"].as_usize().unwrap_or(1) - 1].clone(), - card_list: get_cards(user["deck_list"][user["user"]["main_deck_slot"].as_usize().unwrap_or(1) - 1]["main_card_ids"].clone(), &user) - }, - favorite_card: get_card(user["user"]["favorite_master_card_id"].as_i64().unwrap_or(0), &user), - guest_smile_card: get_card(user["user"]["guest_smile_master_card_id"].as_i64().unwrap_or(0), &user), - guest_cool_card: get_card(user["user"]["guest_cool_master_card_id"].as_i64().unwrap_or(0), &user), - guest_pure_card: get_card(user["user"]["guest_pure_master_card_id"].as_i64().unwrap_or(0), &user), - master_title_ids: user["user"]["master_title_ids"].clone() - }; - if live_data { - rv["live_data_summary"] = object!{ - clear_count_list: [get_clear_count(&user, 1), get_clear_count(&user, 2), get_clear_count(&user, 3), get_clear_count(&user, 4)], - full_combo_list: [get_full_combo_count(&user, 1), get_full_combo_count(&user, 2), get_full_combo_count(&user, 3), get_full_combo_count(&user, 4)], - all_perfect_list: [get_perfect_count(&user, 1), get_perfect_count(&user, 2), get_perfect_count(&user, 3), get_perfect_count(&user, 4)], - high_score_rate: { - rate: 0, - detail: [] - } - }; - } - rv["user"].remove("sif_user_id"); - rv["user"].remove("ss_user_id"); - rv["user"].remove("birthday"); - - if !friends.is_empty() { - rv["status"] = if friends["friend_user_id_list"].contains(id) { - 3 - } else if friends["pending_user_id_list"].contains(id) { - 2 - } else if friends["request_user_id_list"].contains(id) { - 1 - } else { - 0 - }.into(); - } - - rv -} diff --git a/src/router/live.rs b/src/router/live.rs index 1835feb..d52bbb3 100644 --- a/src/router/live.rs +++ b/src/router/live.rs @@ -1,11 +1,12 @@ -use jzon::{object, array, JsonValue}; +use jzon::{array, object, JsonValue}; use actix_web::{web, HttpRequest, Responder}; use rand::RngExt; use lazy_static::lazy_static; -use crate::router::{global, userdata, items, databases}; +use crate::router::{databases, global, items, userdata}; use crate::encryption; use crate::router::clear_rate::live_completed; +use crate::router::tools::guest; pub fn routes(cfg: &mut web::ServiceConfig) { cfg.service( @@ -109,7 +110,7 @@ async fn guest(req: HttpRequest, body: String) -> impl Responder { }).unwrap(); } else { if !friends["friend_user_id_list"].is_empty() { - guest_list.push(global::get_user(friends["friend_user_id_list"][random_number(0, friends["friend_user_id_list"].len() - 1)].as_i64().unwrap(), &friends, false)).unwrap(); + guest_list.push(guest::get_user(friends["friend_user_id_list"][random_number(0, friends["friend_user_id_list"].len() - 1)].as_i64().unwrap(), &friends, guest::UserView::Card)).unwrap(); } let expected: usize = 5; if guest_list.len() < expected { @@ -120,7 +121,7 @@ async fn guest(req: HttpRequest, body: String) -> impl Responder { } for uid in random.members() { - let guest = global::get_user(uid.as_i64().unwrap(), &friends, false); + let guest = guest::get_user(uid.as_i64().unwrap(), &friends, guest::UserView::Card); if guest["user"]["friend_request_disabled"] == 1 || guest.is_empty() { continue; } diff --git a/src/router/tools/guest.rs b/src/router/tools/guest.rs new file mode 100644 index 0000000..b5a714c --- /dev/null +++ b/src/router/tools/guest.rs @@ -0,0 +1,119 @@ +use jzon::{array, object, JsonValue}; +use crate::router::userdata; +use crate::router::global; + +fn get_clear_count(user: &JsonValue, level: i32) -> i64 { + let mut rv = 0; + for current in user["live_list"].members() { + if current["level"] == level { + rv += 1; + } + } + rv +} + +fn get_full_combo_count(user: &JsonValue, level: i32) -> i64 { + let mut rv = 0; + for current in user["live_mission_list"].members() { + if current["clear_master_live_mission_ids"].contains(20 + level) { + rv += 1; + } + } + rv +} + +fn get_perfect_count(user: &JsonValue, level: i32) -> i64 { + let mut rv = 0; + for current in user["live_mission_list"].members() { + if current["clear_master_live_mission_ids"].contains(40 + level) { + rv += 1; + } + } + rv +} + +fn get_high_score_rate(user: &JsonValue) -> JsonValue { + let mut entries = vec![]; + for live in user["live_list"].members() { + let rate = live["high_score"].as_i64().unwrap_or(0) / 5000; + entries.push((rate, live["master_live_id"].as_i64().unwrap_or(0), live["level"].as_i64().unwrap_or(0))); + } + entries.sort_by(|a, b| b.0.cmp(&a.0)); + entries.truncate(10); + + let mut detail = array![]; + let mut total = 0; + for (rate, master_live_id, level) in entries { + total += rate; + detail.push(object!{ + master_live_id: master_live_id, + level: level, + rate: rate + }).unwrap(); + } + + object!{ + rate: total, + detail: detail + } +} + +#[derive(Clone, Copy)] +pub enum UserView { + Card, + Detail, + Ranking, +} + +pub fn get_user(id: i64, friends: &JsonValue, view: UserView) -> JsonValue { + let user = userdata::get_acc_from_uid(id); + if !user["error"].is_empty() { + return object!{}; + } + + let mut rv = object!{ + user: user["user"].clone(), + favorite_card: global::get_card(user["user"]["favorite_master_card_id"].as_i64().unwrap_or(0), &user), + guest_smile_card: global::get_card(user["user"]["guest_smile_master_card_id"].as_i64().unwrap_or(0), &user), + guest_cool_card: global::get_card(user["user"]["guest_cool_master_card_id"].as_i64().unwrap_or(0), &user), + guest_pure_card: global::get_card(user["user"]["guest_pure_master_card_id"].as_i64().unwrap_or(0), &user) + }; + + if let UserView::Detail | UserView::Ranking = view { + rv["main_deck_detail"] = object!{ + total_power: 0, + deck: user["deck_list"][user["user"]["main_deck_slot"].as_usize().unwrap_or(1) - 1].clone(), + card_list: global::get_cards(user["deck_list"][user["user"]["main_deck_slot"].as_usize().unwrap_or(1) - 1]["main_card_ids"].clone(), &user) + }; + rv["master_title_ids"] = user["user"]["master_title_ids"].clone(); + } + + if let UserView::Detail = view { + rv["live_data_summary"] = object!{ + clear_count_list: [get_clear_count(&user, 1), get_clear_count(&user, 2), get_clear_count(&user, 3), get_clear_count(&user, 4)], + full_combo_list: [get_full_combo_count(&user, 1), get_full_combo_count(&user, 2), get_full_combo_count(&user, 3), get_full_combo_count(&user, 4)], + all_perfect_list: [get_perfect_count(&user, 1), get_perfect_count(&user, 2), get_perfect_count(&user, 3), get_perfect_count(&user, 4)], + high_score_rate: get_high_score_rate(&user) + }; + } + + rv["user"].remove("sif_user_id"); + rv["user"].remove("ss_user_id"); + rv["user"].remove("birthday"); + + if let UserView::Card | UserView::Ranking = view { + if !friends.is_empty() { + rv["status"] = if friends["friend_user_id_list"].contains(id) { + 3 + } else if friends["pending_user_id_list"].contains(id) { + 2 + } else if friends["request_user_id_list"].contains(id) { + 1 + } else { + 0 + }.into(); + } + } + + rv +} diff --git a/src/router/tools/mod.rs b/src/router/tools/mod.rs new file mode 100644 index 0000000..fa733cf --- /dev/null +++ b/src/router/tools/mod.rs @@ -0,0 +1 @@ +pub mod guest; \ No newline at end of file diff --git a/src/router/user.rs b/src/router/user.rs index fa71817..80ede85 100644 --- a/src/router/user.rs +++ b/src/router/user.rs @@ -1,10 +1,11 @@ use jzon::{array, object, JsonValue}; use actix_web::{web, HttpRequest, Responder}; -use sha1::{Sha1, Digest}; +use sha1::{Digest, Sha1}; use crate::encryption; -use crate::router::{userdata, global, items}; +use crate::router::{global, items, userdata}; use crate::include_file; +use crate::router::tools::guest; pub fn routes(cfg: &mut web::ServiceConfig) { cfg.service( @@ -262,7 +263,7 @@ async fn detail(req: HttpRequest, body: String) -> impl Responder { let mut user_detail_list = array![]; for data in body["user_ids"].members() { let uid = data.as_i64().unwrap(); - let user = global::get_user(uid, &friends, true); + let user = guest::get_user(uid, &friends, guest::UserView::Detail); user_detail_list.push(user).unwrap(); } global::api(&req, Some(object!{