feat: 后端支持获取用户信息

This commit is contained in:
lanyeeee
2025-07-12 05:58:03 +08:00
parent e99e8d9308
commit d0c0a86977
6 changed files with 214 additions and 2 deletions
+36 -1
View File
@@ -12,7 +12,7 @@ use tauri::{
AppHandle,
};
use crate::types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus};
use crate::types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo};
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36";
const REFERRER: &str = "https://www.bilibili.com/";
@@ -97,6 +97,41 @@ impl BiliClient {
}
Ok(qrcode_status)
}
pub async fn get_user_info(&self, sessdata: &str) -> anyhow::Result<UserInfo> {
// 发送获取用户信息的请求
let request = self
.api_client
.read()
.get("https://api.bilibili.com/x/web-interface/nav")
.header("cookie", format!("SESSDATA={sessdata}"));
let http_resp = request.send().await?;
// 检查http响应状态码
let status = http_resp.status();
let body = http_resp.text().await?;
if status != StatusCode::OK {
return Err(anyhow!("预料之外的状态码({status}): {body}"));
}
// 尝试将body解析为BiliResp
let bili_resp: BiliResp =
serde_json::from_str(&body).context(format!("将body解析为BiliResp失败: {body}"))?;
// 检查BiliResp的code字段
if bili_resp.code == -101 {
return Err(anyhow!("cookie错误或已过期,请重新登录: {bili_resp:?}"));
} else if bili_resp.code != 0 {
return Err(anyhow!("预料之外的code: {bili_resp:?}"));
}
// 检查BiliResp的data是否存在
let Some(data) = bili_resp.data else {
return Err(anyhow!("BiliResp中不存在data字段: {bili_resp:?}"));
};
// 尝试将data解析为UserInfo
let data_str = data.to_string();
let user_info: UserInfo = serde_json::from_str(&data_str)
.context(format!("将data解析为UserInfo失败: {data_str}"))?;
Ok(user_info)
}
}
fn create_api_client(_app: &AppHandle) -> ClientWithMiddleware {
+12 -1
View File
@@ -6,7 +6,7 @@ use crate::{
errors::{CommandError, CommandResult},
extensions::AppHandleExt,
logger,
types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus},
types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo},
};
#[tauri::command]
@@ -80,3 +80,14 @@ pub async fn get_qrcode_status(app: AppHandle, qrcode_key: String) -> CommandRes
.map_err(|err| CommandError::from("获取二维码状态", err))?;
Ok(qrcode_status)
}
#[tauri::command(async)]
#[specta::specta]
pub async fn get_user_info(app: AppHandle, sessdata: String) -> CommandResult<UserInfo> {
let bili_client = app.get_bili_client();
let user_info = bili_client
.get_user_info(&sessdata)
.await
.map_err(|err| CommandError::from("获取用户信息失败", err))?;
Ok(user_info)
}
+1
View File
@@ -29,6 +29,7 @@ pub fn run() {
save_config,
generate_qrcode,
get_qrcode_status,
get_user_info,
])
.events(tauri_specta::collect_events![LogEvent]);
+1
View File
@@ -1,3 +1,4 @@
pub mod log_level;
pub mod qrcode_data;
pub mod qrcode_status;
pub mod user_info;
+146
View File
@@ -0,0 +1,146 @@
use serde::{Deserialize, Serialize};
use specta::Type;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct UserInfo {
#[serde(rename = "isLogin")]
pub is_login: bool,
pub email_verified: i64,
pub face: String,
pub face_nft: i64,
pub face_nft_type: i64,
pub level_info: LevelInfoInUserInfo,
pub mid: i64,
pub mobile_verified: i64,
pub money: f64,
pub moral: i64,
pub official: Official,
#[serde(rename = "officialVerify")]
pub official_verify: OfficialVerify,
pub pendant: PendantInUserInfo,
pub scores: i64,
pub uname: String,
#[serde(rename = "vipDueDate")]
pub vip_due_date: i64,
#[serde(rename = "vipStatus")]
pub vip_status: i64,
#[serde(rename = "vipType")]
pub vip_type: i64,
pub vip_pay_type: i64,
pub vip_theme_type: i64,
pub vip_label: VipLabel,
pub vip_avatar_subscript: i64,
pub vip_nickname_color: String,
pub vip: VipInUserInfo,
pub wallet: Option<Wallet>,
pub has_shop: bool,
pub shop_url: String,
pub answer_status: i64,
pub is_senior_member: i64,
pub wbi_img: WbiImg,
pub is_jury: bool,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[allow(clippy::struct_field_names)]
pub struct LevelInfoInUserInfo {
pub current_level: i64,
pub current_min: i64,
pub current_exp: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct Official {
pub role: i64,
pub title: String,
pub desc: String,
#[serde(rename = "type")]
pub type_field: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct OfficialVerify {
#[serde(rename = "type")]
pub type_field: i64,
pub desc: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct PendantInUserInfo {
pub pid: i64,
pub name: String,
pub image: String,
pub expire: i64,
pub image_enhance: String,
pub image_enhance_frame: String,
pub n_pid: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct VipLabel {
pub path: String,
pub text: String,
pub label_theme: String,
pub text_color: String,
pub bg_style: i64,
pub bg_color: String,
pub border_color: String,
pub use_img_label: bool,
pub img_label_uri_hans: String,
pub img_label_uri_hant: String,
pub img_label_uri_hans_static: String,
pub img_label_uri_hant_static: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[allow(clippy::struct_field_names)]
pub struct VipInUserInfo {
#[serde(rename = "type")]
pub type_field: i64,
pub status: i64,
pub due_date: i64,
pub vip_pay_type: i64,
pub theme_type: i64,
pub label: LabelInUserInfo,
pub avatar_subscript: i64,
pub nickname_color: String,
pub role: i64,
pub avatar_subscript_url: String,
pub tv_vip_status: i64,
pub tv_vip_pay_type: i64,
pub tv_due_date: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[allow(clippy::struct_field_names)]
pub struct LabelInUserInfo {
pub path: String,
pub text: String,
pub label_theme: String,
pub text_color: String,
pub bg_style: i64,
pub bg_color: String,
pub border_color: String,
pub use_img_label: bool,
pub img_label_uri_hans: String,
pub img_label_uri_hant: String,
pub img_label_uri_hans_static: String,
pub img_label_uri_hant_static: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct IconResource {}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct Wallet {
pub mid: i64,
pub bcoin_balance: f64,
pub coupon_balance: f64,
pub coupon_due_time: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct WbiImg {
pub img_url: String,
pub sub_url: String,
}