From 47fa13259f3ffbef7a870e573d58d57805557b4b Mon Sep 17 00:00:00 2001 From: Ethan O'Brien Date: Sat, 4 Jul 2026 17:33:35 -0500 Subject: [PATCH] Cleanup gifts --- src/router/global.rs | 27 ++++++- src/router/home.rs | 2 +- src/router/items.rs | 73 +++++++++++++----- src/router/live.rs | 2 +- src/router/login.rs | 2 +- src/router/mission.rs | 167 ++++++++++++++++++++++++++++++++--------- src/router/tutorial.rs | 2 +- 7 files changed, 217 insertions(+), 58 deletions(-) diff --git a/src/router/global.rs b/src/router/global.rs index 87ec9f7..1436191 100644 --- a/src/router/global.rs +++ b/src/router/global.rs @@ -185,10 +185,35 @@ pub fn timestamp_since_midnight() -> u64 { let midnight = unix_timestamp.as_secs() % (24 * 60 * 60); - + unix_timestamp.as_secs() - midnight } +pub fn get_uid(headers: &HeaderMap) -> i64 { + let blank_header = HeaderValue::from_static(""); + headers.get("aoharu-user-id").unwrap_or(&blank_header).to_str().unwrap_or("").parse::().unwrap_or(0) +} + +fn civil_from_days(z: i64) -> (i64, i64, i64) { + let z = z + 719468; + let era = if z >= 0 { z } else { z - 146096 } / 146097; + let doe = z - era * 146097; + let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + let y = yoe + era * 400; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + let mp = (5 * doy + 2) / 153; + let d = doy - (153 * mp + 2) / 5 + 1; + let m = if mp < 10 { mp + 3 } else { mp - 9 }; + (if m <= 2 { y + 1 } else { y }, m, d) +} + +pub fn format_datetime(time: u64) -> String { + let days = (time / 86400) as i64; + let secs = time % 86400; + let (y, m, d) = civil_from_days(days); + format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", y, m, d, secs / 3600, (secs % 3600) / 60, secs % 60) +} + fn init_time(current_time: u64, server_data: &mut JsonValue, token: &str, max_time: u64, max: bool) { let mut edited = false; let default_time = 1709272800; diff --git a/src/router/home.rs b/src/router/home.rs index 1a2c3e9..2c1b9e2 100644 --- a/src/router/home.rs +++ b/src/router/home.rs @@ -95,7 +95,7 @@ async fn home(req: HttpRequest) -> impl Responder { check_gifts(&mut user); let mut user_missions = userdata::get_acc_missions(&key); - let clear = items::completed_daily_mission(1253003, &mut user_missions); + let clear = items::completed_daily_mission(1253003, global::timestamp(), &mut user_missions); userdata::save_acc_home(&key, user.clone()); user["clear_mission_ids"] = clear; if !user["clear_mission_ids"].is_empty() { diff --git a/src/router/items.rs b/src/router/items.rs index bfb5da0..8b850f3 100644 --- a/src/router/items.rs +++ b/src/router/items.rs @@ -268,7 +268,7 @@ pub fn gift_item_basic(id: i32, value: i64, ty_pe: i32, reason: &str, user: &mut } pub fn lp_modification(user: &mut JsonValue, change_amount: u64, remove: bool) -> bool { - let now = global::set_time(global::timestamp(), user["user"]["id"].as_i64().unwrap_or(0), false); + let now = global::timestamp(); let max = get_user_rank_data(user["user"]["exp"].as_i64().unwrap())["maxLp"].as_u64().unwrap(); let orig_stamina = user["stamina"]["stamina"].as_u64().unwrap(); @@ -486,32 +486,67 @@ pub fn advance_mission(id: i64, count: i64, max: i64, missions: &mut JsonValue) None } -pub fn completed_daily_mission(id: i64, missions: &mut JsonValue) -> JsonValue { - let all_daily_missions = array![1224003, 1253003, 1273009, 1273010, 1273011, 1273012]; - +pub const DAILY_MISSION_IDS: [i64; 6] = [1224003, 1253003, 1273009, 1273010, 1273011, 1273012]; + +pub fn get_expire(now: u64) -> u64 { + let jst = now + 9 * 60 * 60; + ((jst / 86400 + 1) * 86400 - 9 * 60 * 60) - 1 +} + +pub fn refresh_dailies(missions: &mut JsonValue, now: u64) -> bool { + let target = get_expire(now); + let mut changed = false; + for id in DAILY_MISSION_IDS { + for mission in missions.members_mut() { + if mission["master_mission_id"].as_i64() != Some(id) { + continue; + } + let expire = mission["expire_date_time"].as_u64().unwrap_or(0); + if expire == 0 { + mission["expire_date_time"] = target.into(); + changed = true; + } else if now > expire { + mission["status"] = (1).into(); + mission["progress"] = (0).into(); + mission["expire_date_time"] = target.into(); + changed = true; + } + break; + } + } + changed +} + +pub fn completed_daily_mission(id: i64, now: u64, missions: &mut JsonValue) -> JsonValue { + refresh_dailies(missions, now); + let mission = get_mission_status(id, missions); - if mission["expire_date_time"].as_u64().unwrap_or(0) >= global::timestamp() && mission["status"].as_i32().unwrap() > 1 { + if mission.is_empty() || mission["status"].as_i32().unwrap_or(0) > 1 { return array![]; } let mut rv = array![]; if id == 1253003 { rv = advance_variable_mission(1153001, 1153019, 1, missions); - } - let mut mission = get_mission_status(1224003, missions); - let next_reset = global::timestamp_since_midnight() + (24 * 60 * 60); - if mission["expire_date_time"].as_u64().unwrap_or(0) < global::timestamp() { - update_mission_status_multi(all_daily_missions, next_reset, false, false, 0, missions); - mission = get_mission_status(1224003, missions); - } - - if mission["progress"].as_i32().unwrap_or(0) == 4 { - if update_mission_status(1224003, 0, true, false, 1, missions).is_some() { - rv.push(1224003).unwrap(); + if update_mission_status(1653001, 0, true, false, 1, missions).is_some() { + rv.push(1653001).unwrap(); } - } else if update_mission_status(1224003, 0, false, false, 1, missions).is_some() { - rv.push(1224003).unwrap(); } - if update_mission_status(id, next_reset, true, false, 1, missions).is_some() { + for mission in missions.members_mut() { + if mission["master_mission_id"].as_i64() != Some(1224003) { + continue; + } + let was_completed = mission["status"] == 2; + let progress = mission["progress"].as_i64().unwrap_or(0) + 1; + mission["progress"] = progress.into(); + if progress >= 5 { + mission["status"] = (2).into(); + if !was_completed { + rv.push(1224003).unwrap(); + } + } + break; + } + if update_mission_status(id, get_expire(now), true, false, 1, missions).is_some() { rv.push(id).unwrap(); } rv diff --git a/src/router/live.rs b/src/router/live.rs index 6e57c5d..5cb3457 100644 --- a/src/router/live.rs +++ b/src/router/live.rs @@ -638,7 +638,7 @@ pub fn live_end(req: &HttpRequest, body: &str, skipped: bool) -> JsonValue { if body["master_live_id"].to_string().len() > 1 { let id = body["master_live_id"].to_string().split("").collect::>()[2].parse::().unwrap_or(0); if (1..=4).contains(&id) { - let to_push = items::completed_daily_mission(1273009 + id - 1, &mut user_missions); + let to_push = items::completed_daily_mission(1273009 + id - 1, global::timestamp(), &mut user_missions); for data in to_push.members() { cleared_missions.push(data.as_i32().unwrap()).unwrap(); } diff --git a/src/router/login.rs b/src/router/login.rs index 244d2e7..259f8e8 100644 --- a/src/router/login.rs +++ b/src/router/login.rs @@ -66,7 +66,7 @@ async fn bonus(req: HttpRequest, body: String) -> impl Responder { let mut cleared_missions = array![]; if !to_send.is_empty() { - cleared_missions = items::completed_daily_mission(1253003, &mut user_missions); + cleared_missions = items::completed_daily_mission(1253003, global::timestamp(), &mut user_missions); userdata::save_acc_missions(&key, user_missions); } diff --git a/src/router/mission.rs b/src/router/mission.rs index d85f0f0..985dea3 100644 --- a/src/router/mission.rs +++ b/src/router/mission.rs @@ -1,4 +1,4 @@ -use jzon::{array, object}; +use jzon::{array, object, JsonValue}; use actix_web::{web, HttpRequest, Responder}; use crate::router::{global, userdata, items, databases}; @@ -13,9 +13,23 @@ pub fn routes(cfg: &mut web::ServiceConfig) { ); } +const VARIABLE_MISSIONS: [[i64; 2]; 5] = [[1153001, 1153019], [1105001, 1105017], [1101001, 1101030], [1121001, 1121019], [1112001, 1112033]]; + async fn mission(req: HttpRequest) -> impl Responder { let key = global::get_login(req.headers(), ""); - let missions = userdata::get_acc_missions(&key); + let user = userdata::get_acc(&key); + let step = user["tutorial_step"].as_i64().unwrap_or(0); + + if (1..130).contains(&step) { + return global::api(&req, Some(object!{ + "mission_list": array![] + })); + } + + let mut missions = userdata::get_acc_missions(&key); + if items::refresh_dailies(&mut missions, global::timestamp()) { + userdata::save_acc_missions(&key, missions.clone()); + } global::api(&req, Some(object!{ "mission_list": missions @@ -24,69 +38,154 @@ async fn mission(req: HttpRequest) -> impl Responder { async fn clear(req: HttpRequest, body: String) -> impl Responder { let key = global::get_login(req.headers(), &body); - + let mut missions = userdata::get_acc_missions(&key); let body = jzon::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); - + + let mut cleared = array![]; for id in body["master_mission_ids"].members() { - items::update_mission_status(id.as_i64().unwrap(), 0, true, true, 1, &mut missions); + let mission = items::get_mission_status(id.as_i64().unwrap(), &missions); + if mission.is_empty() || mission["status"].as_i32().unwrap_or(0) >= 2 { + continue; + } + items::update_mission_status(id.as_i64().unwrap(), 0, true, false, 1, &mut missions); + cleared.push(id.clone()).unwrap(); } - + userdata::save_acc_missions(&key, missions); - + global::api(&req, Some(object!{ - "clear_mission_ids": body["master_mission_ids"].clone() + "clear_mission_ids": cleared })) } async fn receive(req: HttpRequest, body: String) -> impl Responder { let key = global::get_login(req.headers(), &body); let body = jzon::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); - + let uid = global::get_uid(req.headers()); + let now = global::timestamp(); + let mut missions = userdata::get_acc_missions(&key); let mut user = userdata::get_acc(&key); let mut chats = userdata::get_acc_chats(&key); let mut rewards = array![]; - + let mut mission_list = array![]; + let mut touched_gem = false; + let mut touched_coin = false; + let mut touched_items = array![]; + for mission in body["master_mission_ids"].members() { - let mission_info = databases::MISSION_LIST[mission.to_string()].clone(); - let mut gift = databases::MISSION_REWARD[mission_info["masterMissionRewardId"].to_string()].clone(); - gift["reward_type"] = gift["type"].clone(); - gift["amount"] = gift["amount"].as_i64().unwrap().into(); - items::give_gift(&gift, &mut user, &mut missions, &mut array![], &mut chats); - rewards.push(gift).unwrap(); - - let variable_missions = array![[1153001, 1153019], [1105001, 1105017], [1101001, 1101030], [1121001, 1121019], [1112001, 1112033]]; + let mid = mission.as_i64().unwrap(); + let mission_info = databases::MISSION_LIST[mid.to_string()].clone(); + let master = databases::MISSION_REWARD[mission_info["masterMissionRewardId"].to_string()].clone(); + let reward_type = master["type"].as_i64().unwrap(); + + rewards.push(object!{ + give_type: master["giveType"].clone(), + type: master["type"].clone(), + value: master["value"].clone(), + level: master["level"].clone(), + amount: master["amount"].clone() + }).unwrap(); + + items::give_gift(&object!{ + reward_type: reward_type, + value: master["value"].clone(), + amount: master["amount"].clone() + }, &mut user, &mut missions, &mut array![], &mut chats); + + match reward_type { + 1 => touched_gem = true, + 4 => touched_coin = true, + _ => { touched_items.push(master["value"].clone()).unwrap(); } + } + let mut variable = false; - for id in variable_missions.members() { - if mission.as_i64().unwrap() >= id[0].as_i64().unwrap() && mission.as_i64().unwrap() < id[1].as_i64().unwrap() { - items::change_mission_id(mission.as_i64().unwrap(), mission.as_i64().unwrap() + 1, &mut missions); - items::advance_variable_mission(id[0].as_i64().unwrap(), id[1].as_i64().unwrap(), 0, &mut missions); + for range in VARIABLE_MISSIONS { + if mid >= range[0] && mid < range[1] { + items::change_mission_id(mid, mid + 1, &mut missions); + let next = databases::MISSION_LIST[(mid + 1).to_string()]["conditionNumber"].as_i64().unwrap_or(0); + for m in missions.members_mut() { + if m["master_mission_id"].as_i64() == Some(mid + 1) { + let progress = m["progress"].as_i64().unwrap_or(0); + m["status"] = if progress >= next { 2 } else { 1 }.into(); + mission_list.push(m.clone()).unwrap(); + break; + } + } variable = true; break; } } - if mission.as_i64().unwrap() >= 1158001 && mission.as_i64().unwrap() <= 1158039 { - items::change_mission_id(mission.as_i64().unwrap(), mission.as_i64().unwrap() + 39, &mut missions); - items::update_mission_status(mission.as_i64().unwrap() + 39, 0, false, false, 0, &mut missions); + if !variable && (1158001..=1158039).contains(&mid) { + items::change_mission_id(mid, mid + 39, &mut missions); + items::update_mission_status(mid + 39, 0, false, false, 0, &mut missions); + for m in missions.members_mut() { + if m["master_mission_id"].as_i64() == Some(mid + 39) { + mission_list.push(m.clone()).unwrap(); + break; + } + } variable = true; } if !variable { - items::update_mission_status(mission.as_i64().unwrap(), 0, true, true, 0, &mut missions); + for m in missions.members_mut() { + if m["master_mission_id"].as_i64() == Some(mid) { + m["status"] = (3).into(); + break; + } + } + let m = items::get_mission_status(mid, &missions); + let expire = m["expire_date_time"].as_u64().unwrap_or(0); + mission_list.push(object!{ + user_id: uid, + master_mission_id: mid, + status: 3, + progress: if expire != 0 { m["progress"].clone() } else { JsonValue::Null }, + expire_date: if expire != 0 { global::format_datetime(expire).into() } else { JsonValue::Null }, + received_date: global::format_datetime(now) + }).unwrap(); } } - + userdata::save_acc(&key, user.clone()); userdata::save_acc_chats(&key, chats); - userdata::save_acc_missions(&key, missions.clone()); + userdata::save_acc_missions(&key, missions); + + let mut updated_value_list = object!{}; + if touched_gem { + updated_value_list["gem"] = user["gem"].clone(); + } + if !touched_items.is_empty() { + let mut item_list = array![]; + for id in touched_items.members() { + for item in user["item_list"].members() { + if item["master_item_id"] == *id { + item_list.push(item.clone()).unwrap(); + break; + } + } + } + updated_value_list["item_list"] = item_list; + } + if touched_coin { + let mut point_list = array![]; + for point in user["point_list"].members() { + if point["type"].as_i64() == Some(1) { + point_list.push(object!{ + type: 1, + amount: point["amount"].clone() + }).unwrap(); + break; + } + } + updated_value_list["point_list"] = point_list; + } global::api(&req, Some(object!{ "reward_list": rewards, - "updated_value_list": { - "gem": user["gem"].clone(), - "item_list": user["item_list"].clone(), - "point_list": user["point_list"].clone() - }, - "mission_list": missions + "gift_list": array![], + "updated_value_list": updated_value_list, + "mission_list": mission_list })) } diff --git a/src/router/tutorial.rs b/src/router/tutorial.rs index 6f0a94f..98a7da6 100644 --- a/src/router/tutorial.rs +++ b/src/router/tutorial.rs @@ -16,7 +16,7 @@ async fn tutorial(req: HttpRequest, body: String) -> impl Responder { if user["tutorial_step"].as_i32().unwrap() < 130 { user["tutorial_step"] = body["step"].clone(); user["stamina"]["stamina"] = (100).into(); - user["stamina"]["last_updated_time"] = global::set_time(global::timestamp(), user["user"]["id"].as_i64().unwrap(), false).into(); + user["stamina"]["last_updated_time"] = global::timestamp().into(); userdata::save_acc(&key, user); }