feat: 添加日志功能
This commit is contained in:
		@@ -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"
 | 
			
		||||
							
								
								
									
										67
									
								
								src/logger.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/logger.rs
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								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()
 | 
			
		||||
    let webui_server = HttpServer::new(|| {
 | 
			
		||||
        App::new()
 | 
			
		||||
            .wrap_fn(|req, srv| {
 | 
			
		||||
        println!("WebUI Request: {}", req.path());
 | 
			
		||||
                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();
 | 
			
		||||
    }).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<Server> = None;
 | 
			
		||||
    if enable_asset_server {
 | 
			
		||||
        asset_server = Some(HttpServer::new(|| App::new()
 | 
			
		||||
        asset_server = Some(HttpServer::new(|| {
 | 
			
		||||
            App::new()
 | 
			
		||||
                .wrap_fn(|req, srv| {
 | 
			
		||||
                println!("Assets Request: {}", req.path());
 | 
			
		||||
                    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());
 | 
			
		||||
        }).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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<JsonValue> {
 | 
			
		||||
    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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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<JsonValue> {
 | 
			
		||||
    let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
 | 
			
		||||
 | 
			
		||||
    println!("client error: {}", body["code"]);
 | 
			
		||||
    logger::error(&format!("client error: {}", body["code"]));
 | 
			
		||||
    
 | 
			
		||||
    Some(object!{})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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<JsonValue> {
 | 
			
		||||
    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(),
 | 
			
		||||
 
 | 
			
		||||
@@ -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<JsonValue> {
 | 
			
		||||
    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();
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -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<JsonValue> {
 | 
			
		||||
        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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = [];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user