c-rust / src /common /utils.rs
kevin
rust
cd872f9
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<char> = 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<TokenProfile> {
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::<UsageProfile>(&text).ok()?;
let usage = client
.send()
.await
.ok()?
.json::<UsageProfile>()
.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<StripeProfile> {
let client = super::client::build_profile_client(auth_token);
let response = client
.send()
.await
.ok()?
.json::<StripeProfile>()
.await
.ok()?;
Some(response)
}
pub async fn get_user_profile(auth_token: &str) -> Option<UserProfile> {
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::<UserProfile>().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<String> {
// 解析 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
}