mod checksum; pub use checksum::*; mod tokens; pub use tokens::*; use super::models::userinfo::{StripeProfile, TokenProfile, UsageProfile, UserProfile}; use crate::app::{ constant::{FALSE, TRUE}, lazy::{TOKEN_DELIMITER, TOKEN_DELIMITER_LEN}, }; pub fn parse_bool_from_env(key: &str, default: bool) -> bool { std::env::var(key) .ok() .map(|v| match v.to_lowercase().as_str() { TRUE | "1" => true, FALSE | "0" => false, _ => default, }) .unwrap_or(default) } pub fn parse_string_from_env(key: &str, default: &str) -> String { std::env::var(key).unwrap_or_else(|_| default.to_string()) } pub fn parse_ascii_char_from_env(key: &str, default: char) -> char { std::env::var(key) .ok() .and_then(|v| { let chars: Vec = v.chars().collect(); if chars.len() == 1 && chars[0].is_ascii() { Some(chars[0]) } else { None } }) .unwrap_or(default) } pub fn parse_usize_from_env(key: &str, default: usize) -> usize { std::env::var(key) .ok() .and_then(|v| v.parse().ok()) .unwrap_or(default) } pub async fn get_token_profile(auth_token: &str) -> Option { let user_id = extract_user_id(auth_token)?; // 构建请求客户端 let client = super::client::build_usage_client(&user_id, auth_token); // 发送请求并获取响应 // let response = client.send().await.ok()?; // let bytes = response.bytes().await?; // println!("Raw response bytes: {:?}", bytes); // let usage = serde_json::from_str::(&text).ok()?; let usage = client .send() .await .ok()? .json::() .await .ok()?; let user = get_user_profile(auth_token).await?; // 从 Stripe 获取用户资料 let stripe = get_stripe_profile(auth_token).await?; // 映射响应数据到 TokenProfile Some(TokenProfile { usage, user, stripe, }) } pub async fn get_stripe_profile(auth_token: &str) -> Option { let client = super::client::build_profile_client(auth_token); let response = client .send() .await .ok()? .json::() .await .ok()?; Some(response) } pub async fn get_user_profile(auth_token: &str) -> Option { let user_id = extract_user_id(auth_token)?; // 构建请求客户端 let client = super::client::build_userinfo_client(&user_id, auth_token); // 发送请求并获取响应 let user_profile = client.send().await.ok()?.json::().await.ok()?; Some(user_profile) } pub fn validate_token_and_checksum(auth_token: &str) -> Option<(String, String)> { // 找最后一个逗号 let comma_pos = auth_token.rfind(*TOKEN_DELIMITER)?; let (token_part, checksum) = auth_token.split_at(comma_pos); let checksum = &checksum[*TOKEN_DELIMITER_LEN..]; // 跳过逗号 // 解析 token - 为了向前兼容,忽略最后一个:或%3A前的内容 let colon_pos = token_part.rfind(':'); let encoded_colon_pos = token_part.rfind("%3A"); let token = match (colon_pos, encoded_colon_pos) { (None, None) => token_part, // 最简单的构成: token,checksum (Some(pos1), None) => &token_part[(pos1 + 1)..], (None, Some(pos2)) => &token_part[(pos2 + 3)..], (Some(pos1), Some(pos2)) => { let pos = pos1.max(pos2); let start = if pos == pos2 { pos + 3 } else { pos + 1 }; &token_part[start..] } }; // 验证 token 和 checksum 有效性 if validate_token(token) && validate_checksum(checksum) { Some((token.to_string(), checksum.to_string())) } else { None } } pub fn extract_token(auth_token: &str) -> Option { // 解析 token let token_part = match auth_token.rfind(*TOKEN_DELIMITER) { Some(pos) => &auth_token[..pos], None => auth_token, }; // 向前兼容 let colon_pos = token_part.rfind(':'); let encoded_colon_pos = token_part.rfind("%3A"); let token = match (colon_pos, encoded_colon_pos) { (None, None) => token_part, (Some(pos1), None) => &token_part[(pos1 + 1)..], (None, Some(pos2)) => &token_part[(pos2 + 3)..], (Some(pos1), Some(pos2)) => { let pos = pos1.max(pos2); let start = if pos == pos2 { pos + 3 } else { pos + 1 }; &token_part[start..] } }; // 验证 token 有效性 if validate_token(token) { Some(token.to_string()) } else { None } } pub fn format_time_ms(seconds: f64) -> f64 { (seconds * 1000.0).round() / 1000.0 }