From ee2e8dd1c6221c09f727199fe02f2535f8879a08 Mon Sep 17 00:00:00 2001 From: zhushenwudi <55681140@163.com> Date: Mon, 6 Jan 2025 23:13:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 ++ src/logger.rs | 67 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 66 +++++++++++++++++++------------------ src/router.rs | 6 ++-- src/router/chat.rs | 4 +-- src/router/debug.rs | 6 ++-- src/router/items.rs | 10 +++--- src/router/start.rs | 6 ++-- src/router/user.rs | 4 +-- src/router/userdata/mod.rs | 4 +-- webui/src/home/Home.jsx | 2 +- 11 files changed, 125 insertions(+), 52 deletions(-) create mode 100644 src/logger.rs diff --git a/Cargo.toml b/Cargo.toml index 8108c25..8bcb206 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,3 +31,5 @@ serde = { version = "1.0.215", features = ["derive"] } futures = "0.3.31" mime_guess = "2.0.5" actix-files = "0.6.6" +simplelog = "0.12.2" +log = "0.4.22" \ No newline at end of file diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..3daf394 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,67 @@ +use log::{debug, error, info, warn, LevelFilter}; +use simplelog::*; +use std::fs::{create_dir_all, File, OpenOptions}; +use std::path::Path; + +const MAX_LOG_SIZE: u64 = 50 * 1024 * 1024; +const LOG_FILE_PATH: &str = "data/rust.log"; + +pub fn init_logger() { + let mut builder = ConfigBuilder::new(); + builder.set_time_offset_to_local().unwrap(); + let config = builder.build(); + + // 获取文件的目录路径 + let dir = Path::new(LOG_FILE_PATH).parent().unwrap(); + + // 检查并创建目录 + if !dir.exists() { + create_dir_all(dir).unwrap(); + } + + let file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(LOG_FILE_PATH).unwrap(); + + CombinedLogger::init( + vec![ + TermLogger::new(LevelFilter::Info, config.clone(), TerminalMode::Mixed, ColorChoice::Auto), + WriteLogger::new(LevelFilter::Info, config.clone(), file), + ] + ).unwrap(); +} + +// 检查文件大小并清空文件(如果超出限制) +fn check_and_clear_log_file() { + let metadata = std::fs::metadata(LOG_FILE_PATH).unwrap(); + if metadata.len() > MAX_LOG_SIZE { + // 清空文件 + File::create(LOG_FILE_PATH).expect(&format!("Can't re-create file {}", LOG_FILE_PATH)); + } +} + +#[allow(dead_code)] +pub fn debug(message: &str) { + check_and_clear_log_file(); + debug!("{}", message); +} + +#[allow(dead_code)] +pub fn info(message: &str) { + check_and_clear_log_file(); + info!("{}", message); +} + +#[allow(dead_code)] +pub fn warn(message: &str) { + check_and_clear_log_file(); + warn!("{}", message); +} + +#[allow(dead_code)] +pub fn error(message: &str) { + check_and_clear_log_file(); + error!("{}", message); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0e56259..a44ece1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod encryption; mod router; mod sql; +mod logger; use actix_web::{ rt, @@ -42,7 +43,7 @@ pub struct Args { #[arg(short, long, default_value_t = 8000, help = "Assets port to listen on")] asset_port: u16, - #[arg(long, default_value = "./", help = "Path to store database files")] + #[arg(long, default_value = "./data/", help = "Path to store database files")] path: String, #[arg(long, default_value = "./asset/", help = "Path to store database files")] @@ -110,43 +111,45 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> { let asset_port = args.asset_port; if args.purge { - println!("Purging accounts..."); - let ct = crate::router::userdata::purge_accounts(); - println!("Purged {} accounts", ct); + logger::debug("Purging accounts..."); + let ct = router::userdata::purge_accounts(); + logger::warn(&format!("Purged {} accounts", ct)); } - let webui_server = HttpServer::new(|| App::new() - .wrap_fn(|req, srv| { - println!("WebUI Request: {}", req.path()); - srv.call(req) - }) - .app_data(web::PayloadConfig::default().limit(1024 * 1024 * 25)) - .service(css) - .service(js) - .default_service(web::route().to(router::request)) - ).bind(("0.0.0.0", port))?.run(); + let webui_server = HttpServer::new(|| { + App::new() + .wrap_fn(|req, srv| { + logger::info(&format!("WebUI Request: {}", req.path())); // 使用日志记录 + srv.call(req) + }) + .app_data(web::PayloadConfig::default().limit(1024 * 1024 * 25)) + .service(css) + .service(js) + .default_service(web::route().to(router::request)) + }).bind(("0.0.0.0", port))?.run(); - println!("WebUI Server started: http://0.0.0.0:{}", port); - println!("Database path is set to {}", args.path); - println!("Sif1 transfer requests will attempt to contact NPPS4 at {}", args.npps4); + logger::info(&format!("WebUI Server started: http://0.0.0.0:{}", port)); + logger::info(&format!("Database path is set to {}", args.path)); + logger::debug(&format!("Sif1 transfer requests will attempt to contact NPPS4 at {}", args.npps4)); let mut asset_server: Option = None; if enable_asset_server { - asset_server = Some(HttpServer::new(|| App::new() - .wrap_fn(|req, srv| { - println!("Assets Request: {}", req.path()); - srv.call(req) - }) - .app_data(web::PayloadConfig::default().limit(1024 * 1024 * 1024)) - .default_service(web::route().to(router::asset_request)) - ).bind(("0.0.0.0", asset_port))?.run()); + asset_server = Some(HttpServer::new(|| { + App::new() + .wrap_fn(|req, srv| { + logger::info(&format!("Assets Request: {}", req.path())); + srv.call(req) + }) + .app_data(web::PayloadConfig::default().limit(1024 * 1024 * 1024)) + .default_service(web::route().to(router::asset_request)) + }).bind(("0.0.0.0", asset_port))?.run()); - println!("Assets Server started: http://0.0.0.0:{}", asset_port); - println!("Assets path is set to {}", args.asset_path); + logger::info(&format!("Assets Server started: http://0.0.0.0:{}", asset_port)); + logger::info(&format!("Assets path is set to {}", args.asset_path)); } if args.https { - println!("Note: gree is set to https mode. http requests will fail on jp clients."); + logger::warn("Note: gree is set to https mode. http requests will fail on jp clients."); } if in_thread { @@ -161,13 +164,13 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> { } while get_running().await { - actix_web::rt::time::sleep(Duration::from_millis(100)).await; + rt::time::sleep(Duration::from_millis(100)).await; } handle.stop(false).await; if handle2.is_some() { handle2.unwrap().stop(false).await; } - println!("Stopped"); + logger::info("Stopped"); return Ok(()); } if asset_server.is_some() { @@ -181,10 +184,11 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> { #[actix_web::main] async fn stop_server() { set_running(false).await; - println!("Stopping"); + logger::error("Stopping"); } fn main() -> std::io::Result<()> { + logger::init_logger(); run_server(false) } diff --git a/src/router.rs b/src/router.rs index cf5c8ce..c9e96ec 100644 --- a/src/router.rs +++ b/src/router.rs @@ -30,13 +30,13 @@ pub mod event_ranking; use actix_web::{HttpResponse, HttpRequest, http::header::HeaderValue, http::header::HeaderMap, Responder}; use json::{JsonValue, object}; -use crate::encryption; +use crate::{encryption, logger}; fn unhandled(req: HttpRequest, body: String) -> Option { if body != String::new() { - println!("{}", encryption::decrypt_packet(&body).unwrap_or(body)); + logger::error(&format!("{}", encryption::decrypt_packet(&body).unwrap_or(body))); } - println!("Unhandled request: {}", req.path()); + logger::error(&format!("Unhandled request: {}", req.path())); None } diff --git a/src/router/chat.rs b/src/router/chat.rs index 1eb98d9..f2b0b2d 100644 --- a/src/router/chat.rs +++ b/src/router/chat.rs @@ -2,7 +2,7 @@ use json::{object, array, JsonValue}; use actix_web::{HttpRequest}; use crate::router::{global, items, userdata, databases}; -use crate::encryption; +use crate::{encryption, logger}; pub fn add_chat(id: i64, num: i64, chats: &mut JsonValue) -> bool { for data in chats.members() { @@ -23,7 +23,7 @@ pub fn add_chat(id: i64, num: i64, chats: &mut JsonValue) -> bool { pub fn add_chat_from_chapter_id(chapter_id: i64, chats: &mut JsonValue) -> bool { let chapter = &databases::CHAPTERS_MASTER[chapter_id.to_string()]; if chapter.is_empty() { - println!("Attempted to give unknown chapter id {}", chapter_id); + logger::info(&format!("Attempted to give unknown chapter id {}", chapter_id)); return false; } add_chat(chapter["masterChatId"].as_i64().unwrap(), chapter["roomId"].as_i64().unwrap(), chats) diff --git a/src/router/debug.rs b/src/router/debug.rs index 9bcfb1d..0786059 100644 --- a/src/router/debug.rs +++ b/src/router/debug.rs @@ -1,12 +1,12 @@ use json::{JsonValue, object}; use actix_web::{HttpRequest}; -use crate::encryption; +use crate::{encryption, logger}; pub fn error(_req: HttpRequest, body: String) -> Option { let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); - - println!("client error: {}", body["code"]); + + logger::error(&format!("client error: {}", body["code"])); Some(object!{}) } diff --git a/src/router/items.rs b/src/router/items.rs index 66e7f61..d150bf8 100644 --- a/src/router/items.rs +++ b/src/router/items.rs @@ -1,7 +1,7 @@ use json::{array, object, JsonValue}; use rand::Rng; use actix_web::{HttpRequest, http::header::{HeaderMap, HeaderValue}}; -use crate::encryption; +use crate::{encryption, logger}; use crate::router::{userdata, global, databases}; @@ -113,7 +113,7 @@ pub fn use_item(item: &JsonValue, multiplier: i64, user: &mut JsonValue) { } else if item["consumeType"] == 4 { use_itemm(item["value"].as_i64().unwrap(), item["amount"].as_i64().unwrap() * multiplier, user); } else { - println!("Unknown consume type {}", item["consumeType"]); + logger::error(&format!("Unknown consume type {}", item["consumeType"])); } } @@ -142,7 +142,7 @@ pub fn give_gift(data: &JsonValue, user: &mut JsonValue, missions: &mut JsonValu } return false; } - println!("Redeeming reward not implemented for reward type {}", data["reward_type"]); + logger::error(&format!("Redeeming reward not implemented for reward type {}", data["reward_type"])); false } pub fn give_gift_basic(ty_pe: i32, id: i64, amount: i64, user: &mut JsonValue, missions: &mut JsonValue, clear_missions: &mut JsonValue, chats: &mut JsonValue) -> bool { @@ -279,7 +279,7 @@ pub fn get_rarity(id: i64) -> i32 { pub fn give_character(id: i64, user: &mut JsonValue, missions: &mut JsonValue, clear_missions: &mut JsonValue, chats: &mut JsonValue) -> bool { let character_rarity = get_rarity(id); if character_rarity == 0 { - println!("Attempted to give user undefined card!! Card id: {}", id); + logger::error(&format!("Attempted to give user undefined card!! Card id: {}", id)); return false; } @@ -498,7 +498,7 @@ pub fn use_item_req(req: HttpRequest, body: String) -> Option { if item["effectType"].as_i32().unwrap() == 1 { lp_modification(&mut user, item["effectValue"].as_u64().unwrap() * (amount as u64), false); } else { - println!("Use item not implemented for effect type {}", item["effectType"]); + logger::error(&format!("Use item not implemented for effect type {}", item["effectType"])); } use_item(&object!{ value: body["id"].as_i64().unwrap(), diff --git a/src/router/start.rs b/src/router/start.rs index 9d55ba7..2e14fff 100644 --- a/src/router/start.rs +++ b/src/router/start.rs @@ -1,12 +1,12 @@ use json::{JsonValue, object}; use actix_web::{HttpRequest, http::header::HeaderValue}; -use crate::encryption; +use crate::{encryption, logger}; use crate::router::{userdata, global}; fn get_asset_hash(req: &HttpRequest, body: &JsonValue) -> String { if body["asset_version"] != global::ASSET_VERSION && body["asset_version"] != global::ASSET_VERSION_JP { - println!("Warning! Asset version is not what was expected. (Did the app update?)"); + logger::warn("Warning! Asset version is not what was expected. (Did the app update?)"); } let blank_header = HeaderValue::from_static(""); @@ -29,7 +29,7 @@ pub fn start(req: HttpRequest, body: String) -> Option { let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap(); let mut user = userdata::get_acc(&key); - println!("Signin from uid: {}", user["user"]["id"].clone()); + logger::info(&format!("Signin from uid: {}", user["user"]["id"].clone())); user["user"]["last_login_time"] = global::timestamp().into(); diff --git a/src/router/user.rs b/src/router/user.rs index 3a89174..31ec68f 100644 --- a/src/router/user.rs +++ b/src/router/user.rs @@ -2,7 +2,7 @@ use json::{array, object, JsonValue}; use actix_web::{HttpRequest}; use sha1::{Sha1, Digest}; -use crate::encryption; +use crate::{encryption, logger}; use crate::router::{userdata, global, items}; use crate::include_file; @@ -329,7 +329,7 @@ async fn npps4_req(sha_id: String) -> Option { host.pop(); } let url = format!("{}/ewexport?sha1={}", host, sha_id); - println!("Polling NPPS4 at {}", host); + logger::debug(&format!("Polling NPPS4 at {}", host)); let client = reqwest::Client::new(); let response = client.get(url); diff --git a/src/router/userdata/mod.rs b/src/router/userdata/mod.rs index 95013f7..1258028 100644 --- a/src/router/userdata/mod.rs +++ b/src/router/userdata/mod.rs @@ -8,7 +8,7 @@ use base64::{Engine as _, engine::general_purpose}; use crate::router::global; use crate::router::items; use crate::sql::SQLite; -use crate::include_file; +use crate::{include_file, logger}; lazy_static! { static ref DATABASE: SQLite = SQLite::new("userdata.db", setup_tables); @@ -625,7 +625,7 @@ pub fn purge_accounts() -> usize { )).unwrap(); for uid in dead_uids.members() { let user_id = uid.as_i64().unwrap(); - println!("Removing dead UID: {}", user_id); + logger::error(&format!("Removing dead UID: {}", user_id)); crate::router::gree::delete_uuid(user_id); DATABASE.lock_and_exec("DELETE FROM userdata WHERE user_id=?1", params!(user_id)); DATABASE.lock_and_exec("DELETE FROM userhome WHERE user_id=?1", params!(user_id)); diff --git a/webui/src/home/Home.jsx b/webui/src/home/Home.jsx index 146eb1c..71466f8 100644 --- a/webui/src/home/Home.jsx +++ b/webui/src/home/Home.jsx @@ -1,4 +1,4 @@ -import { useState, useParams, useEffect } from 'react' +import { useState, useEffect } from 'react' import './Home.css' import Request from '../Request.jsx' let bonusItems = [];