From 597ed7fb34b5b806d0f52468e9547e1e8ccaa2cc Mon Sep 17 00:00:00 2001 From: Ethan O'Brien <77750390+ethanaobrien@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:17:44 -0500 Subject: [PATCH] Implement friend endpoints --- src/main.rs | 24 +++++++ src/router/friend.rs | 142 ++++++++++++++++++++++++++++++++++--- src/router/global.rs | 60 +++++++++++++++- src/router/user.rs | 53 +------------- src/router/userdata/mod.rs | 62 ++++++++++++++-- 5 files changed, 274 insertions(+), 67 deletions(-) diff --git a/src/main.rs b/src/main.rs index dd61ac1..f7514ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,6 +99,24 @@ async fn tutorial(req: HttpRequest, body: String) -> HttpResponse { router::tuto #[post("/api/friend")] async fn friend(req: HttpRequest, body: String) -> HttpResponse { router::friend::friend(req, body) } +#[get("/api/friend/ids")] +async fn friend_ids(req: HttpRequest) -> HttpResponse { router::friend::ids(req) } + +#[post("/api/friend/search")] +async fn friend_search(req: HttpRequest, body: String) -> HttpResponse { router::friend::search(req, body) } + +#[post("/api/friend/search/recommend")] +async fn friend_recommend(req: HttpRequest, body: String) -> HttpResponse { router::friend::recommend(req, body) } + +#[post("/api/friend/request")] +async fn friend_request(req: HttpRequest, body: String) -> HttpResponse { router::friend::request(req, body) } + +#[post("/api/friend/request/approve")] +async fn friend_approve(req: HttpRequest, body: String) -> HttpResponse { router::friend::approve(req, body) } + +#[post("/api/friend/request/cancel")] +async fn friend_cancel(req: HttpRequest, body: String) -> HttpResponse { router::friend::cancel(req, body) } + #[post("/api/live/guest")] async fn live_guest(req: HttpRequest, body: String) -> HttpResponse { router::live::guest(req, body) } @@ -241,6 +259,12 @@ async fn main() -> std::io::Result<()> { .service(lottery_post) .service(lottery) .service(friend) + .service(friend_search) + .service(friend_recommend) + .service(friend_ids) + .service(friend_request) + .service(friend_approve) + .service(friend_cancel) .service(mission) .service(mission_clear) .service(mission_receive) diff --git a/src/router/friend.rs b/src/router/friend.rs index ed9de48..564b11d 100644 --- a/src/router/friend.rs +++ b/src/router/friend.rs @@ -1,21 +1,147 @@ -use json; -use json::object; +use json::{object, array}; use crate::router::global; use actix_web::{HttpResponse, HttpRequest}; -//use crate::router::userdata; +use crate::router::userdata; +use crate::encryption; -pub fn friend(_req: HttpRequest, _body: String) -> HttpResponse { - /*let blank_header = HeaderValue::from_static(""); +pub fn friend(req: HttpRequest, body: String) -> HttpResponse { + let key = global::get_login(req.headers(), &body); + let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); + let friends = userdata::get_acc_friends(&key); - let key = global::get_login(req.headers()); - let user = userdata::get_acc(&key, uid);*/ + let mut rv = array![]; + + let rv_data = if body["status"].as_i32().unwrap() == 3 { + friends["friend_user_id_list"].clone() + } else if body["status"].as_i32().unwrap() == 2 { + friends["pending_user_id_list"].clone() + } else if body["status"].as_i32().unwrap() == 1 { + friends["request_user_id_list"].clone() + } else { + array![] + }; + + for (_i, uid) in rv_data.members().enumerate() { + let mut to_push = global::get_user(uid.as_i64().unwrap()); + to_push["status"] = body["status"].clone(); + rv.push(to_push).unwrap(); + } let resp = object!{ "code": 0, "server_time": global::timestamp(), "data": { - "friend_list": [] //todo - pull from userdata + "friend_list": rv } }; global::send(resp) } + +pub fn ids(req: HttpRequest) -> HttpResponse { + let key = global::get_login(req.headers(), ""); + let friends = userdata::get_acc_friends(&key); + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": friends + }; + global::send(resp) +} + +pub fn recommend(_req: HttpRequest, _body: String) -> HttpResponse { + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": { + friend_list: [] + } + }; + global::send(resp) +} + +pub fn search(_req: HttpRequest, body: String) -> HttpResponse { + let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); + + let uid = body["user_id"].as_i64().unwrap(); + let user = global::get_user(uid); + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": user + }; + global::send(resp) +} + +pub fn request(req: HttpRequest, body: String) -> HttpResponse { + let key = global::get_login(req.headers(), &body); + let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); + let user_id = userdata::get_acc(&key)["user"]["id"].as_i64().unwrap(); + let mut friends = userdata::get_acc_friends(&key); + + let uid = body["user_id"].as_i64().unwrap(); + if !userdata::friend_request_disabled(uid) { + if !friends["request_user_id_list"].contains(uid) { + friends["request_user_id_list"].push(uid).unwrap(); + userdata::save_acc_friends(&key, friends); + } + userdata::friend_request(uid, user_id); + } + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": [] + }; + global::send(resp) +} + +pub fn approve(req: HttpRequest, body: String) -> HttpResponse { + let key = global::get_login(req.headers(), &body); + let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); + let user_id = userdata::get_acc(&key)["user"]["id"].as_i64().unwrap(); + let mut friends = userdata::get_acc_friends(&key); + + let uid = body["user_id"].as_i64().unwrap(); + let index = friends["request_user_id_list"].members().into_iter().position(|r| *r.to_string() == uid.to_string()); + if !index.is_none() { + friends["request_user_id_list"].array_remove(index.unwrap()); + } + if body["approve"].to_string() == "1" && ! friends["friend_user_id_list"].contains(uid) { + friends["friend_user_id_list"].push(uid).unwrap(); + } + + userdata::friend_request_approve(uid, user_id, body["approve"].to_string() == "1"); + userdata::save_acc_friends(&key, friends); + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": [] + }; + global::send(resp) +} + +pub fn cancel(req: HttpRequest, body: String) -> HttpResponse { + let key = global::get_login(req.headers(), &body); + let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); + let user_id = userdata::get_acc(&key)["user"]["id"].as_i64().unwrap(); + let mut friends = userdata::get_acc_friends(&key); + + let uid = body["user_id"].as_i64().unwrap(); + let index = friends["request_user_id_list"].members().into_iter().position(|r| *r.to_string() == uid.to_string()); + if !index.is_none() { + friends["request_user_id_list"].array_remove(index.unwrap()); + } + userdata::friend_request_approve(uid, user_id, false); + userdata::save_acc_friends(&key, friends); + + let resp = object!{ + "code": 0, + "server_time": global::timestamp(), + "data": [] + }; + global::send(resp) +} diff --git a/src/router/global.rs b/src/router/global.rs index 975344f..433e8f0 100644 --- a/src/router/global.rs +++ b/src/router/global.rs @@ -1,4 +1,4 @@ -use json::{object, JsonValue}; +use json::{object, JsonValue, array}; use crate::encryption; use actix_web::{ HttpResponse, @@ -7,6 +7,7 @@ use actix_web::{ use crate::router::gree; use std::time::{SystemTime, UNIX_EPOCH}; use base64::{Engine as _, engine::general_purpose}; +use crate::router::userdata; pub const ASSET_VERSION: &str = "13177023d4b7ad41ff52af4cefba5c55"; pub const ASSET_HASH_ANDROID: &str = "017ec1bcafbeea6a7714f0034b15bd0f"; @@ -135,3 +136,60 @@ pub fn give_exp(amount: i32, user: &mut JsonValue) { user["stamina"]["last_updated_time"] = timestamp().into(); } } + +fn get_card(id: i64, user: &JsonValue) -> JsonValue { + if id == 0 { + return object!{}; + } + + for (_i, data) in user["card_list"].members().enumerate() { + if data["master_card_id"].as_i64().unwrap_or(0) == id { + return data.clone(); + } + } + return object!{}; +} +fn get_cards(arr: JsonValue, user: &JsonValue) -> JsonValue { + let mut rv = array![]; + for (_i, data) in arr.members().enumerate() { + let to_push = get_card(data.as_i64().unwrap_or(0), user); + if to_push.is_empty() { + continue; + } + rv.push(to_push).unwrap(); + } + return rv; +} +pub fn get_user(id: i64) -> JsonValue { + let user = userdata::get_acc_from_uid(id); + if !user["error"].is_empty() { + return object!{}; + } + let mut rv = object!{ + user: user["user"].clone(), + live_data_summary: { + clear_count_list: [0, 0, 0, 0], + full_combo_list: [0, 0, 0, 0], + all_perfect_list: [0, 0, 0, 0], + high_score_rate: { + rate: 0, + detail: [] + } + }, + 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["master_title_ids"].clone() + }; + rv["user"].remove("sif_user_id"); + rv["user"].remove("ss_user_id"); + rv["user"].remove("birthday"); + + rv +} diff --git a/src/router/user.rs b/src/router/user.rs index 85e035e..4a1de97 100644 --- a/src/router/user.rs +++ b/src/router/user.rs @@ -364,63 +364,14 @@ pub fn migration(_req: HttpRequest, body: String) -> HttpResponse { }; global::send(resp) } -fn get_card(id: i64, user: &JsonValue) -> JsonValue { - if id == 0 { - return object!{}; - } - - for (_i, data) in user["card_list"].members().enumerate() { - if data["master_card_id"].as_i64().unwrap_or(0) == id { - return data.clone(); - } - } - return object!{}; -} -fn get_cards(arr: JsonValue, user: &JsonValue) -> JsonValue { - let mut rv = array![]; - for (_i, data) in arr.members().enumerate() { - let to_push = get_card(data.as_i64().unwrap_or(0), user); - if to_push.is_empty() { - continue; - } - rv.push(to_push).unwrap(); - } - return rv; -} pub fn detail(_req: HttpRequest, body: String) -> HttpResponse { let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); let mut user_detail_list = array![]; for (_i, data) in body["user_ids"].members().enumerate() { let uid = data.as_i64().unwrap(); - let user = userdata::get_acc_from_uid(uid); - - let mut to_push = object!{ - user: user["user"].clone(), - live_data_summary: { - clear_count_list: [0, 0, 0, 0], - full_combo_list: [0, 0, 0, 0], - all_perfect_list: [0, 0, 0, 0], - high_score_rate: { - rate: 0, - detail: [] - } - }, - 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["master_title_ids"].clone() - }; - to_push["user"].remove("sif_user_id"); - to_push["user"].remove("ss_user_id"); - to_push["user"].remove("birthday"); - user_detail_list.push(to_push).unwrap(); + let user = global::get_user(uid); + user_detail_list.push(user).unwrap(); } let resp = object!{ "code": 0, diff --git a/src/router/userdata/mod.rs b/src/router/userdata/mod.rs index 97e957e..2c422a1 100644 --- a/src/router/userdata/mod.rs +++ b/src/router/userdata/mod.rs @@ -100,7 +100,8 @@ fn create_users_store() { userhome TEXT NOT NULL, missions TEXT NOT NULL, loginbonus TEXT NOT NULL, - sifcards TEXT NOT NULL + sifcards TEXT NOT NULL, + friends TEXT NOT NULL )"); } @@ -147,13 +148,14 @@ fn create_acc(uid: i64, login: &str) { new_user["user"]["id"] = uid.into(); new_user["stamina"]["last_updated_time"] = global::timestamp().into(); - lock_and_exec("INSERT INTO users (user_id, userdata, userhome, missions, loginbonus, sifcards) VALUES (?1, ?2, ?3, ?4, ?5, ?6)", params!( + lock_and_exec("INSERT INTO users (user_id, userdata, userhome, missions, loginbonus, sifcards, friends) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", params!( uid, json::stringify(new_user), include_str!("new_user_home.json"), include_str!("chat_missions.json"), format!(r#"{{"last_rewarded": 0, "bonus_list": [], "start_time": {}}}"#, global::timestamp()), - "[]" + "[]", + r#"{"friend_user_id_list":[],"request_user_id_list":[],"pending_user_id_list":[]}"# )); create_token_store(); @@ -224,6 +226,9 @@ pub fn get_acc_loginbonus(auth_key: &str) -> JsonValue { pub fn get_acc_sif(auth_key: &str) -> JsonValue { get_data(auth_key, "sifcards") } +pub fn get_acc_friends(auth_key: &str) -> JsonValue { + get_data(auth_key, "friends") +} pub fn save_data(auth_key: &str, row: &str, data: JsonValue) { let key = get_key(&auth_key); @@ -243,6 +248,9 @@ pub fn save_acc_missions(auth_key: &str, data: JsonValue) { pub fn save_acc_loginbonus(auth_key: &str, data: JsonValue) { save_data(auth_key, "loginbonus", data); } +pub fn save_acc_friends(auth_key: &str, data: JsonValue) { + save_data(auth_key, "friends", data); +} pub fn get_acc_transfer(uid: i64, token: &str, password: &str) -> JsonValue { create_migration_store(); @@ -267,7 +275,6 @@ pub fn save_acc_transfer(token: &str, password: &str) { } pub fn get_name_and_rank(uid: i64) -> JsonValue { - create_migration_store(); let login_token = get_login_token(uid); if login_token == String::new() { return object!{ @@ -292,12 +299,10 @@ pub fn get_name_and_rank(uid: i64) -> JsonValue { } pub fn get_acc_from_uid(uid: i64) -> JsonValue { - create_migration_store(); let login_token = get_login_token(uid); if login_token == String::new() { return object!{ - user_name: "", - user_rank: 1 + error: true } } let uid = get_uid(&login_token); @@ -307,3 +312,46 @@ pub fn get_acc_from_uid(uid: i64) -> JsonValue { let result = lock_and_select("SELECT userdata FROM users WHERE user_id=?1", params!(uid)); json::parse(&result.unwrap()).unwrap() } + +pub fn friend_request(uid: i64, requestor: i64) { + let login_token = get_login_token(uid); + if login_token == String::new() { + return; + } + let uid = get_uid(&login_token); + let friends = lock_and_select("SELECT friends FROM users WHERE user_id=?1", params!(uid)); + let mut friends = json::parse(&friends.unwrap()).unwrap(); + if !friends["pending_user_id_list"].contains(requestor) { + friends["pending_user_id_list"].push(requestor).unwrap(); + lock_and_exec("UPDATE users SET friends=?1 WHERE user_id=?2", params!(json::stringify(friends), uid)); + } +} + +pub fn friend_request_approve(uid: i64, requestor: i64, accepted: bool) { + let login_token = get_login_token(uid); + if login_token == String::new() { + return; + } + let uid = get_uid(&login_token); + let friends = lock_and_select("SELECT friends FROM users WHERE user_id=?1", params!(uid)); + let mut friends = json::parse(&friends.unwrap()).unwrap(); + let index = friends["pending_user_id_list"].members().into_iter().position(|r| *r.to_string() == requestor.to_string()); + if !index.is_none() { + friends["pending_user_id_list"].array_remove(index.unwrap()); + } + if accepted && !friends["friend_user_id_list"].contains(requestor) { + friends["friend_user_id_list"].push(requestor).unwrap(); + } + lock_and_exec("UPDATE users SET friends=?1 WHERE user_id=?2", params!(json::stringify(friends), uid)); +} + +pub fn friend_request_disabled(uid: i64) -> bool { + let login_token = get_login_token(uid); + if login_token == String::new() { + return true; + } + let uid = get_uid(&login_token); + let user = lock_and_select("SELECT userdata FROM users WHERE user_id=?1", params!(uid)); + let user = json::parse(&user.unwrap()).unwrap(); + user["user"]["friend_request_disabled"].to_string() == "1" +}