From eb1785569f159f75af68810a2fe800c481b527ef Mon Sep 17 00:00:00 2001 From: cxw620 Date: Tue, 10 Jan 2023 12:56:49 +0800 Subject: [PATCH 1/4] temporarily disable special cache --- src/mods/types.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mods/types.rs b/src/mods/types.rs index 5558fe5c..540b678b 100644 --- a/src/mods/types.rs +++ b/src/mods/types.rs @@ -188,14 +188,14 @@ impl<'bili_runtime> BiliRuntime<'bili_runtime> { // vip用户获取到playurl后刷新缓存, keys[0]就是vip的key, keys[1]就是non-vip的key redis_set(self.redis_pool, &keys[0], value, expire_time).await; // 双保险, 虽然实际上应该只需要`keys.len() > 1` - if params.is_vip && !params.ep_need_vip { - let playurl_type = ¶ms.get_playurl_type(); - if let Some(value) = remove_viponly_clarity(playurl_type, value).await { - redis_set(self.redis_pool, &keys[1], &value, expire_time) - .await - .unwrap() - } - } + // if params.is_vip && !params.ep_need_vip { + // let playurl_type = ¶ms.get_playurl_type(); + // if let Some(value) = remove_viponly_clarity(playurl_type, value).await { + // redis_set(self.redis_pool, &keys[1], &value, expire_time) + // .await + // .unwrap() + // } + // } } _ => { for key in keys { From 68c97dc99f3e93c1b12766f19268d0dfd40c46b7 Mon Sep 17 00:00:00 2001 From: cxw620 Date: Tue, 10 Jan 2023 14:51:24 +0800 Subject: [PATCH 2/4] fix: -663 panic --- src/mods/types.rs | 3 +- src/mods/upstream_res.rs | 1016 ++++++++++++++++++++++++++------------ src/mods/user_info.rs | 11 +- 3 files changed, 715 insertions(+), 315 deletions(-) diff --git a/src/mods/types.rs b/src/mods/types.rs index 540b678b..86c7af76 100644 --- a/src/mods/types.rs +++ b/src/mods/types.rs @@ -1,7 +1,6 @@ use super::{ ep_info::get_ep_need_vip, request::{redis_get, redis_set}, - tools::remove_viponly_clarity, }; use actix_web::HttpRequest; use async_channel::{Sender, TrySendError}; @@ -184,7 +183,7 @@ impl<'bili_runtime> BiliRuntime<'bili_runtime> { let keys = cache_type.gen_key(); // let _new_value: &str; match cache_type { - CacheType::Playurl(params) => { + CacheType::Playurl(_params) => { // vip用户获取到playurl后刷新缓存, keys[0]就是vip的key, keys[1]就是non-vip的key redis_set(self.redis_pool, &keys[0], value, expire_time).await; // 双保险, 虽然实际上应该只需要`keys.len() > 1` diff --git a/src/mods/upstream_res.rs b/src/mods/upstream_res.rs index 71ba3762..82d6f5ef 100644 --- a/src/mods/upstream_res.rs +++ b/src/mods/upstream_res.rs @@ -9,8 +9,7 @@ use super::ep_info::get_ep_need_vip; use super::health::report_health; use super::request::async_getwebpage; use super::tools::{ - check_vip_status_from_playurl, get_mobi_app, get_user_mid_from_playurl, mid_to_eid, - remove_parameters_playurl, + check_vip_status_from_playurl, get_user_mid_from_playurl, remove_parameters_playurl, }; use super::types::{ Area, BiliRuntime, ClientType, EType, EpInfo, FakeUA, HealthData, HealthReportType, @@ -19,271 +18,253 @@ use super::types::{ use super::user_info::get_blacklist_info; use crate::{build_signed_url, random_string}; use chrono::prelude::*; -use log::{debug, error}; +use log::{debug, error, info}; use qstring::QString; -use rand::Rng; use reqwest::header::{HeaderMap, HeaderValue}; use serde_json::json; use std::string::String; -pub async fn get_upstream_bili_account_info( - access_key: &str, - appkey: &str, - is_app: bool, - client_type: &ClientType, - bili_runtime: &BiliRuntime<'_>, -) -> Result { - match get_upstream_bili_account_info_app(access_key, appkey, client_type, bili_runtime).await { - Ok(value) => Ok(value), - Err(err_type) => { - // more method get mid - if let Some(mid) = - get_upstream_bili_account_info_ak_to_mid(access_key, client_type, bili_runtime) - .await - { - if let Some(vip_expire_time) = - get_upstream_bili_account_info_vip_due_date(mid, bili_runtime).await - { - return Ok(UserInfo::new(0, access_key, mid, vip_expire_time)); - } - }; - match err_type { - // web端可能appkey不可用? - EType::ServerReqError("-663错误, 被鼠鼠制裁了, 请稍后重试") => { - if !is_app { - let new_user_info = UserInfo::new_unintended_error(access_key); - update_user_info_cache(&new_user_info, bili_runtime).await; - Ok(new_user_info) - } else { - // app端再次出现-663就是寄 - Err(err_type) - } - } - _ => Err(err_type), - } - } - } -} - -async fn get_upstream_bili_account_info_app( - access_key: &str, - _appkey: &str, - client_type: &ClientType, - bili_runtime: &BiliRuntime<'_>, -) -> Result { - let dt = Local::now(); - let ts = dt.timestamp_millis() as u64; - let ts_min = dt.timestamp() as u64; - let ts_min_string = ts_min.to_string(); +// pub async fn get_upstream_bili_account_info( +// access_key: &str, +// appkey: &str, +// is_app: bool, +// client_type: &ClientType, +// bili_runtime: &BiliRuntime<'_>, +// ) -> Result { +// // match get_upstream_bili_account_info_app(access_key, appkey, client_type, bili_runtime).await { +// // Ok(value) => Ok(value), +// // Err(err_type) => { +// // // more method get mid +// // if let Some(mid) = +// // get_upstream_bili_account_info_ak_to_mid(access_key, client_type, bili_runtime) +// // .await +// // { +// // if let Some(vip_expire_time) = +// // get_upstream_bili_account_info_vip_due_date(mid, bili_runtime).await +// // { +// // return Ok(UserInfo::new(0, access_key, mid, vip_expire_time)); +// // } +// // }; +// // match err_type { +// // // web端可能appkey不可用? +// // EType::ServerReqError("-663错误, 被鼠鼠制裁了, 请稍后重试") => { +// // if !is_app { +// // let new_user_info = UserInfo::new_unintended_error(access_key); +// // update_user_info_cache(&new_user_info, bili_runtime).await; +// // Ok(new_user_info) +// // } else { +// // // app端再次出现-663就是寄 +// // Err(err_type) +// // } +// // } +// // _ => Err(err_type), +// // } +// // } +// // } +// } - let (appkey, appsec, mobi_app) = get_mobi_app(client_type); +pub fn get_upstream_bili_account_info_rec<'rec>( + access_key: &'rec str, + client_type: &'rec ClientType, + bili_runtime: &'rec BiliRuntime, + is_rec: bool, +) -> futures::future::BoxFuture<'rec, Result> { + futures::FutureExt::boxed(async move { + let dt = Local::now(); + let ts = dt.timestamp_millis() as u64; + let ts_min = dt.timestamp() as u64; + let ts_min_string = ts_min.to_string(); + // 必要信息 + let appkey = client_type.appkey(); + let appsec = client_type.appsec(); - let rand_string_36 = { - let words: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - let mut rng = rand::thread_rng(); - (0..36) - .map(|_| { - let idx = rng.gen_range(0..words.len()); - words[idx] as char - }) - .collect::() - }; + // 降级至build 5360000 + // let rand_num = { + // let mut rng = rand::thread_rng(); + // rng.gen_range(1000000..100000000) + // }; - let rand_num = { - let mut rng = rand::thread_rng(); - rng.gen_range(1000000..100000000) - }; - let mut req_vec = vec![ //以防万一,昨天抓了下包尽可能补全 - ("access_key", access_key), - ("appkey", appkey), - ("build", "6800300"), - ("buvid", &rand_string_36), - ("c_locale", "zh_CN"), - ("channel", "master"), - ("disable_rcmd", "0"), - ("local_id",&rand_string_36), - ("mobi_app",mobi_app), - ("platform", "android"), - ("s_locale","zh_CN"), - ("statistics","%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.80.0%22%2C%22abtest%22%3A%22%22%7D"), - ("ts", &ts_min_string), - ]; - req_vec.sort_by_key(|v| v.0); + let mut req_vec = vec![ //以防万一,昨天抓了下包尽可能补全 + ("access_key", access_key), + ("appkey", appkey), + ("build", "5360000"), + // ("buvid", &fake_buvid), + // ("c_locale", "zh_CN"), + // ("channel", "master"), + // ("disable_rcmd", "0"), + // ("local_id",&rand_string_36), + ("mobi_app",client_type.mobi_app().unwrap_or_else(|| { + error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default mobi_app 'android'"); + "android" + })), + ("platform", client_type.platform().unwrap_or_else(|| { + error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default platform 'android'"); + "android" + })), + // ("s_locale","zh_CN"), + // ("statistics","%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.80.0%22%2C%22abtest%22%3A%22%22%7D"), + ("ts", &ts_min_string), + ]; + req_vec.sort_by_key(|v| v.0); - // fix -663 error - let mut headers = HeaderMap::new(); - headers.insert( - "x-bili-aurora-eid", - HeaderValue::from_bytes(mid_to_eid(&format!("{}", rand_num)).as_bytes()).unwrap(), - ); - headers.insert("x-bili-aurora-zone", HeaderValue::from_static("sh001")); - // headers.insert("app-key",HeaderValue::from_static("android64")); + // fix -663 error + // let mut headers = HeaderMap::new(); + // headers.insert( + // "x-bili-aurora-eid", + // HeaderValue::from_bytes(mid_to_eid(&format!("{}", rand_num)).as_bytes()).unwrap(), + // ); + // headers.insert("x-bili-aurora-zone", HeaderValue::from_static("sh001")); + // headers.insert("app-key",HeaderValue::from_static("android64")); - let api = format!( - "https://{}/x/v2/account/myinfo", - bili_runtime.config.general_app_bilibili_com_proxy_api - ); - let (signed_url, sign) = build_signed_url!(api, req_vec, appsec); - let upstream_raw_resp = match async_getwebpage( - &signed_url, - bili_runtime.config.cn_proxy_accesskey_open, - &bili_runtime.config.cn_proxy_accesskey_url, - &FakeUA::Bilibili.gen(), // 客户端请求UA和普通的不一样 - "", - Some(headers), - ) - .await - { - Ok(data) => data, - Err(_) => { - error!( - "[GET USER_INFO][U] AK {} | Req failed. Network Problems. RAW QUERY -> APPKEY {} TS {} APPSEC {} Use Proxy {} - {}", - access_key, appkey, ts_min, appsec, bili_runtime.config.cn_proxy_accesskey_open, &bili_runtime.config.cn_proxy_accesskey_url, + let headers = { + let fake_buvid = UniqueId::UserInfoOld.buvid(); + let mut headers = HeaderMap::new(); + headers.insert("buvid", HeaderValue::from_str(&fake_buvid).unwrap()); + let fake_display_id = { + let mut display_id = String::with_capacity(100); + display_id.push_str("0-"); + display_id.push_str(&ts_min_string); + display_id + }; + headers.insert( + "display-id", + HeaderValue::from_str(&fake_display_id).unwrap(), ); - let health_report_type = HealthReportType::Others(HealthData { - area_num: 0, - is_200_ok: false, - upstream_reply: UpstreamReply { - proxy_open: bili_runtime.config.cn_proxy_accesskey_open, - proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), - ..Default::default() - }, - is_custom: true, - custom_message: "[GET USERINFO][U] 致命错误! 获取用户信息失败!".to_owned(), - }); - report_health(health_report_type, bili_runtime).await; - let new_user_info = UserInfo::new_unintended_error(access_key); - update_user_info_cache(&new_user_info, bili_runtime).await; - return Ok(new_user_info); - } - }; + // 如: Pg5oWT8NNQJmVTAEeAR4 + headers.insert( + "device-id", + HeaderValue::from_str(&{ + random_string!( + 20, + b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + ) + }) + .unwrap(), + ); + headers + }; - let upstream_raw_resp_json = upstream_raw_resp - .json() - .unwrap_or(json!({"code": -500, "message": "[SERVER] 解析上游JSON错误"})); - let code = if let Some(value) = upstream_raw_resp_json["code"].as_i64() { - value - } else { - debug!( - "[GET USER_INFO][U] AK {} | Parsing Upstream reply failed, Upstream Reply -> {}", - access_key, upstream_raw_resp + let api = format!( + "https://{}/x/v2/account/myinfo", + bili_runtime.config.general_app_bilibili_com_proxy_api ); - let health_report_type = HealthReportType::Others(HealthData { - area_num: 0, - is_200_ok: true, - upstream_reply: UpstreamReply { - upstream_header: upstream_raw_resp.read_headers(), - proxy_open: bili_runtime.config.cn_proxy_accesskey_open, - proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), - ..Default::default() - }, - is_custom: true, - custom_message: format!("致命错误! 解析用户信息失败!\n上游返回: {upstream_raw_resp}"), - }); - report_health(health_report_type, bili_runtime).await; - return Err(EType::ServerReqError("解析用户信息失败")); - }; - - match code { - 0 => { - if upstream_raw_resp_json["data"]["mid"].as_u64().unwrap_or(0) == 0 { - // accesskey失效时mid为0, 缓存25d - update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; + let (signed_url, sign) = build_signed_url!(api, req_vec, appsec); + let upstream_raw_resp = match async_getwebpage( + &signed_url, + bili_runtime.config.cn_proxy_accesskey_open, + &bili_runtime.config.cn_proxy_accesskey_url, + // &FakeUA::Bilibili.gen(), + "Mozilla/5.0 BiliDroid/5.36.0 (bbcallen@gmail.com)", // 旧版客户端请求UA固定此值 + "", + Some(headers), + ) + .await + { + Ok(data) => data, + Err(_) => { error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", - access_key, upstream_raw_resp_json - ); - Err(EType::UserNotLoginedError) - } else { - let vip_expire_time = upstream_raw_resp_json["data"]["vip"]["due_date"] - .as_u64() - .unwrap(); - let output_struct = UserInfo { - code: 0, - access_key: String::from(access_key), - uid: upstream_raw_resp_json["data"]["mid"].as_u64().unwrap(), - vip_expire_time, - expire_time: { - if ts < vip_expire_time && vip_expire_time < ts + 25 * 24 * 60 * 60 * 1000 { - vip_expire_time - } else { - ts + 25 * 24 * 60 * 60 * 1000 - } - }, //用户状态25天强制更新 - }; - update_user_info_cache(&output_struct, bili_runtime).await; - Ok(output_struct) + "[GET USER_INFO][U] AK {} | Req failed. Network Problems. RAW QUERY -> TS {} Use Proxy {} - {}", + access_key, ts_min, bili_runtime.config.cn_proxy_accesskey_open, &bili_runtime.config.cn_proxy_accesskey_url, + ); + { + let health_report_type = HealthReportType::Others(HealthData { + area_num: 0, + is_200_ok: false, + upstream_reply: UpstreamReply { + proxy_open: bili_runtime.config.cn_proxy_accesskey_open, + proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), + ..Default::default() + }, + is_custom: true, + custom_message: "[GET USERINFO][U] 致命错误! 获取用户信息失败!".to_owned(), + }); + report_health(health_report_type, bili_runtime).await; + } + + let new_user_info = UserInfo::new_unintended_error(access_key); + update_user_info_cache(&new_user_info, bili_runtime).await; + return Ok(new_user_info); } - } - -3 => { - // 不应该出现签名错误, 除非B站更改签名算法 - error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -3. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", - access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json + }; + + let upstream_raw_resp_json = upstream_raw_resp + .json() + .unwrap_or(json!({"code": -500, "message": "[SERVER] 解析上游JSON错误"})); + let code = if let Some(value) = upstream_raw_resp_json["code"].as_i64() { + value + } else { + debug!( + "[GET USER_INFO][U] AK {} | Parsing Upstream reply failed, Upstream Reply -> {}", + access_key, upstream_raw_resp ); - Ok(UserInfo::new_unintended_error(access_key)) - } - -400 | -404 => { - error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. Invalid APPKEY -> APPKEY {} | TS {} | APPSEC {}. Upstream Reply -> {}", - access_key, appkey, ts_min, appsec, upstream_raw_resp - ); let health_report_type = HealthReportType::Others(HealthData { area_num: 0, is_200_ok: true, upstream_reply: UpstreamReply { - code, - message: upstream_raw_resp_json["message"] - .as_str() - .unwrap_or("null") - .to_owned(), upstream_header: upstream_raw_resp.read_headers(), proxy_open: bili_runtime.config.cn_proxy_accesskey_open, proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), + ..Default::default() }, is_custom: true, custom_message: format!( - "[GET USER_INFO][U] 致命错误: 不能用于获取用户信息的APPKEY {appkey} - APPSEC {appsec}" + "致命错误! 解析用户信息失败!\n上游返回: {upstream_raw_resp}" ), }); report_health(health_report_type, bili_runtime).await; - Err(EType::ServerReqError("APPKEY失效")) - } - // -400 => { - // // 已经指定appkey, 不应当出现此错误 - // error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -400. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {}. Upstream Reply -> {}", - // access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json - // ); - // Err(EType::OtherError(-400, "可能你用的不是手机")) - // } - -101 => { - // -101必定是登录失效, 观察发现也只有网页端会这样, 缓存25天 - update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; - // update_user_info_cache(&output_struct, bili_runtime).await; - error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", - access_key, upstream_raw_resp_json - ); - Err(EType::UserNotLoginedError) - } - 61000 => { - // 那先看成未登录 - // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 - update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; - error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", - access_key, upstream_raw_resp_json - ); - Err(EType::UserLoginInvalid) - } - -412 => { - error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed -412. Upstream Reply -> {}", - access_key, upstream_raw_resp_json - ); - let health_report_type = HealthReportType::Others(HealthData { + return Err(EType::ServerReqError("解析用户信息失败")); + }; + + match code { + 0 => { + if upstream_raw_resp_json["data"]["mid"].as_u64().unwrap_or(0) == 0 { + // accesskey失效时mid为0, 缓存25d + update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime) + .await; + error!( + "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", + access_key, upstream_raw_resp_json + ); + Err(EType::UserNotLoginedError) + } else { + let vip_expire_time = upstream_raw_resp_json["data"]["vip"]["due_date"] + .as_u64() + .unwrap(); + let output_struct = UserInfo { + code: 0, + access_key: String::from(access_key), + uid: upstream_raw_resp_json["data"]["mid"].as_u64().unwrap(), + vip_expire_time, + expire_time: { + if ts < vip_expire_time + && vip_expire_time < ts + 25 * 24 * 60 * 60 * 1000 + { + vip_expire_time + } else { + ts + 25 * 24 * 60 * 60 * 1000 + } + }, //用户状态25天强制更新 + }; + update_user_info_cache(&output_struct, bili_runtime).await; + Ok(output_struct) + } + } + -3 => { + // 不应该出现签名错误, 除非B站更改签名算法 + error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -3. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", + access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json + ); + Ok(UserInfo::new_unintended_error(access_key)) + } + -400 | -404 => { + error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. Invalid APPKEY -> APPKEY {} | TS {} | APPSEC {}. Upstream Reply -> {}", + access_key, appkey, ts_min, appsec, upstream_raw_resp + ); + let health_report_type = HealthReportType::Others(HealthData { area_num: 0, is_200_ok: true, upstream_reply: UpstreamReply { - code: -412, + code, message: upstream_raw_resp_json["message"] .as_str() .unwrap_or("null") @@ -294,80 +275,498 @@ async fn get_upstream_bili_account_info_app( }, is_custom: true, custom_message: format!( - "[GET USER_INFO][U] 致命错误! 机子-412喵! 上游返回: {upstream_raw_resp}" - ), - }); - report_health(health_report_type, bili_runtime).await; - Err(EType::ServerFatalError) - } - -663 => { - // app端的-663不应该. - error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed -663. Upstream Reply -> {}", + "[GET USER_INFO][U] 致命错误: 不能用于获取用户信息的APPKEY {appkey} - APPSEC {appsec}" + ), + }); + report_health(health_report_type, bili_runtime).await; + Err(EType::ServerReqError("APPKEY失效")) + } + // -400 => { + // // 已经指定appkey, 不应当出现此错误 + // error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -400. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {}. Upstream Reply -> {}", + // access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json + // ); + // Err(EType::OtherError(-400, "可能你用的不是手机")) + // } + -101 => { + // -101必定是登录失效, 观察发现也只有网页端会这样, 缓存25天 + update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; + // update_user_info_cache(&output_struct, bili_runtime).await; + error!( + "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", + access_key, upstream_raw_resp_json + ); + Err(EType::UserNotLoginedError) + } + 61000 => { + // 那先看成未登录 + // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 + update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; + error!( + "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", access_key, upstream_raw_resp_json ); - let output_struct = UserInfo { - code, - access_key: access_key.to_owned(), - expire_time: ts + 10 * 60 * 1000, // 暂时缓存10m - ..Default::default() - }; - update_user_info_cache(&output_struct, bili_runtime).await; - let health_report_type = HealthReportType::Others(HealthData { - area_num: 0, - is_200_ok: true, - upstream_reply: UpstreamReply { + Err(EType::UserLoginInvalid) + } + -412 => { + error!( + "[GET USER_INFO][U] AK {} | Get UserInfo failed -412. Upstream Reply -> {}", + access_key, upstream_raw_resp_json + ); + let health_report_type = HealthReportType::Others(HealthData { + area_num: 0, + is_200_ok: true, + upstream_reply: UpstreamReply { + code: -412, + message: upstream_raw_resp_json["message"] + .as_str() + .unwrap_or("null") + .to_owned(), + upstream_header: upstream_raw_resp.read_headers(), + proxy_open: bili_runtime.config.cn_proxy_accesskey_open, + proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), + }, + is_custom: true, + custom_message: format!( + "[GET USER_INFO][U] 致命错误! 机子-412喵! 上游返回: {upstream_raw_resp}" + ), + }); + report_health(health_report_type, bili_runtime).await; + Err(EType::ServerFatalError) + } + -663 => { + // 已知的-663错误的原因 + // 1. access_key和appkey不对应, message为"鉴权失败,请联系账号组" + // 2. api已经弃用, meassage为"-663" + error!( + "[GET USER_INFO][U] AK {} | Get UserInfo failed -663. Using appkey: {}. Upstream Reply -> {}", + access_key, appkey, upstream_raw_resp_json + ); + let upstream_message = upstream_raw_resp_json["message"] + .as_str() + .unwrap_or("null") + .to_owned(); + if upstream_message == "鉴权失败,请联系账号组" && !is_rec { + if let Ok(new_value) = get_upstream_bili_account_info_rec( + access_key, + &ClientType::Web, + bili_runtime, + true, // 防止递归黑洞 + ) + .await + { + info!("[GET USER_INFO][U] AK {access_key} | AK异常, 疑似Web脚本生成, 重试成功."); + return Ok(new_value); + } + } + let output_struct = UserInfo { code, - message: upstream_raw_resp_json["message"].as_str().unwrap_or("null").to_owned(), - upstream_header: upstream_raw_resp.read_headers(), - proxy_open: bili_runtime.config.cn_proxy_accesskey_open, - proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), - }, - is_custom: true, - custom_message: format!( - "[GET USER_INFO][U] 致命错误: 上游返回-663! 正在尝试修复\nDevice: {}, APPKEY: {}, AK: {}, TS: {}", - mobi_app, appkey, access_key, ts - ), - }); - report_health(health_report_type, bili_runtime).await; - Err(EType::ServerReqError("-663错误, 被鼠鼠制裁了, 请稍后重试")) - } - _ => { - error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", + access_key: access_key.to_owned(), + expire_time: ts + 10 * 60 * 1000, // 暂时缓存10m + ..Default::default() + }; + update_user_info_cache(&output_struct, bili_runtime).await; + let health_report_type = HealthReportType::Others(HealthData { + area_num: 0, + is_200_ok: true, + upstream_reply: UpstreamReply { + code, + message: upstream_message, + upstream_header: upstream_raw_resp.read_headers(), + proxy_open: bili_runtime.config.cn_proxy_accesskey_open, + proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), + }, + is_custom: true, + custom_message: format!( + "[GET USER_INFO][U] -663错误, 大概率access_key和appkey不对应. 频繁出现此错误请提issue处理\nAPPKEY: {}, AK: {}, TS: {}", + appkey, access_key, ts + ), + }); + report_health(health_report_type, bili_runtime).await; + // Err(EType::ServerReqError("-663错误, 请检查access_key是否由对应appkey生成")) + Err(EType::OtherUpstreamError( + -663, + "-663, 请稍后重试".to_owned(), + )) + } + _ => { + error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json ); - error!("[GET USER_INFO][U] URL {}", signed_url); - // 不采用常规方法更新, 仅限用于未知的错误码下的刷新 - update_cached_user_info_background(access_key.to_owned(), bili_runtime).await; - let health_report_type = HealthReportType::Others(HealthData { - area_num: 0, - is_200_ok: true, - upstream_reply: UpstreamReply { + error!("[GET USER_INFO][U] URL {}", signed_url); + // 不采用常规方法更新, 仅限用于未知的错误码下的刷新 + update_cached_user_info_background(access_key.to_owned(), bili_runtime).await; + let health_report_type = HealthReportType::Others(HealthData { + area_num: 0, + is_200_ok: true, + upstream_reply: UpstreamReply { + code, + message: upstream_raw_resp_json["message"] + .as_str() + .unwrap_or("null") + .to_owned(), + upstream_header: upstream_raw_resp.read_headers(), + proxy_open: bili_runtime.config.cn_proxy_accesskey_open, + proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), + }, + is_custom: true, + custom_message: format!( + "[GET USER_INFO][U] 致命错误! 未知的错误码! 上游返回: {upstream_raw_resp}" + ), + }); + report_health(health_report_type, bili_runtime).await; + Err(EType::OtherUpstreamError( code, - message: upstream_raw_resp_json["message"] + upstream_raw_resp_json["message"] .as_str() - .unwrap_or("null") - .to_owned(), - upstream_header: upstream_raw_resp.read_headers(), - proxy_open: bili_runtime.config.cn_proxy_accesskey_open, - proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), - }, - is_custom: true, - custom_message: format!( - "[GET USER_INFO][U] 致命错误! 未知的错误码! 上游返回: {upstream_raw_resp}" - ), - }); - report_health(health_report_type, bili_runtime).await; - Err(EType::OtherUpstreamError( - code, - upstream_raw_resp_json["message"] - .as_str() - .unwrap_or("NULL") - .to_string(), - )) + .unwrap_or("NULL") + .to_string(), + )) + } } - } + }) } +// async fn get_upstream_bili_account_info_app( +// access_key: &str, +// client_type: &ClientType, +// bili_runtime: &BiliRuntime<'_>, +// ) -> Result { +// let dt = Local::now(); +// let ts = dt.timestamp_millis() as u64; +// let ts_min = dt.timestamp() as u64; +// let ts_min_string = ts_min.to_string(); +// // 必要信息 +// let appkey = client_type.appkey(); +// let appsec = client_type.appsec(); + +// // 降级至build 5360000 +// // let rand_num = { +// // let mut rng = rand::thread_rng(); +// // rng.gen_range(1000000..100000000) +// // }; + +// let mut req_vec = vec![ //以防万一,昨天抓了下包尽可能补全 +// ("access_key", access_key), +// ("appkey", appkey), +// ("build", "5360000"), +// // ("buvid", &fake_buvid), +// // ("c_locale", "zh_CN"), +// // ("channel", "master"), +// // ("disable_rcmd", "0"), +// // ("local_id",&rand_string_36), +// ("mobi_app",client_type.mobi_app().unwrap_or_else(|| { +// error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default mobi_app 'android'"); +// "android" +// })), +// ("platform", client_type.platform().unwrap_or_else(|| { +// error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default platform 'android'"); +// "android" +// })), +// // ("s_locale","zh_CN"), +// // ("statistics","%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.80.0%22%2C%22abtest%22%3A%22%22%7D"), +// ("ts", &ts_min_string), +// ]; +// req_vec.sort_by_key(|v| v.0); + +// // fix -663 error +// // let mut headers = HeaderMap::new(); +// // headers.insert( +// // "x-bili-aurora-eid", +// // HeaderValue::from_bytes(mid_to_eid(&format!("{}", rand_num)).as_bytes()).unwrap(), +// // ); +// // headers.insert("x-bili-aurora-zone", HeaderValue::from_static("sh001")); +// // headers.insert("app-key",HeaderValue::from_static("android64")); + +// let headers = { +// let fake_buvid = UniqueId::UserInfoOld.buvid(); +// let mut headers = HeaderMap::new(); +// headers.insert("buvid", HeaderValue::from_str(&fake_buvid).unwrap()); +// let fake_display_id = { +// let mut display_id = String::with_capacity(100); +// display_id.push_str("0-"); +// display_id.push_str(&ts_min_string); +// display_id +// }; +// headers.insert( +// "display-id", +// HeaderValue::from_str(&fake_display_id).unwrap(), +// ); +// // 如: Pg5oWT8NNQJmVTAEeAR4 +// headers.insert( +// "device-id", +// HeaderValue::from_str(&{ +// random_string!( +// 20, +// b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +// ) +// }) +// .unwrap(), +// ); +// headers +// }; + +// let api = format!( +// "https://{}/x/v2/account/myinfo", +// bili_runtime.config.general_app_bilibili_com_proxy_api +// ); +// let (signed_url, sign) = build_signed_url!(api, req_vec, appsec); +// let upstream_raw_resp = match async_getwebpage( +// &signed_url, +// bili_runtime.config.cn_proxy_accesskey_open, +// &bili_runtime.config.cn_proxy_accesskey_url, +// // &FakeUA::Bilibili.gen(), +// "Mozilla/5.0 BiliDroid/5.36.0 (bbcallen@gmail.com)", // 旧版客户端请求UA固定此值 +// "", +// Some(headers), +// ) +// .await +// { +// Ok(data) => data, +// Err(_) => { +// error!( +// "[GET USER_INFO][U] AK {} | Req failed. Network Problems. RAW QUERY -> TS {} Use Proxy {} - {}", +// access_key, ts_min, bili_runtime.config.cn_proxy_accesskey_open, &bili_runtime.config.cn_proxy_accesskey_url, +// ); +// { +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: false, +// upstream_reply: UpstreamReply { +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// ..Default::default() +// }, +// is_custom: true, +// custom_message: "[GET USERINFO][U] 致命错误! 获取用户信息失败!".to_owned(), +// }); +// report_health(health_report_type, bili_runtime).await; +// } + +// let new_user_info = UserInfo::new_unintended_error(access_key); +// update_user_info_cache(&new_user_info, bili_runtime).await; +// return Ok(new_user_info); +// } +// }; + +// let upstream_raw_resp_json = upstream_raw_resp +// .json() +// .unwrap_or(json!({"code": -500, "message": "[SERVER] 解析上游JSON错误"})); +// let code = if let Some(value) = upstream_raw_resp_json["code"].as_i64() { +// value +// } else { +// debug!( +// "[GET USER_INFO][U] AK {} | Parsing Upstream reply failed, Upstream Reply -> {}", +// access_key, upstream_raw_resp +// ); +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: true, +// upstream_reply: UpstreamReply { +// upstream_header: upstream_raw_resp.read_headers(), +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// ..Default::default() +// }, +// is_custom: true, +// custom_message: format!("致命错误! 解析用户信息失败!\n上游返回: {upstream_raw_resp}"), +// }); +// report_health(health_report_type, bili_runtime).await; +// return Err(EType::ServerReqError("解析用户信息失败")); +// }; + +// match code { +// 0 => { +// if upstream_raw_resp_json["data"]["mid"].as_u64().unwrap_or(0) == 0 { +// // accesskey失效时mid为0, 缓存25d +// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; +// error!( +// "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", +// access_key, upstream_raw_resp_json +// ); +// Err(EType::UserNotLoginedError) +// } else { +// let vip_expire_time = upstream_raw_resp_json["data"]["vip"]["due_date"] +// .as_u64() +// .unwrap(); +// let output_struct = UserInfo { +// code: 0, +// access_key: String::from(access_key), +// uid: upstream_raw_resp_json["data"]["mid"].as_u64().unwrap(), +// vip_expire_time, +// expire_time: { +// if ts < vip_expire_time && vip_expire_time < ts + 25 * 24 * 60 * 60 * 1000 { +// vip_expire_time +// } else { +// ts + 25 * 24 * 60 * 60 * 1000 +// } +// }, //用户状态25天强制更新 +// }; +// update_user_info_cache(&output_struct, bili_runtime).await; +// Ok(output_struct) +// } +// } +// -3 => { +// // 不应该出现签名错误, 除非B站更改签名算法 +// error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -3. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", +// access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json +// ); +// Ok(UserInfo::new_unintended_error(access_key)) +// } +// -400 | -404 => { +// error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. Invalid APPKEY -> APPKEY {} | TS {} | APPSEC {}. Upstream Reply -> {}", +// access_key, appkey, ts_min, appsec, upstream_raw_resp +// ); +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: true, +// upstream_reply: UpstreamReply { +// code, +// message: upstream_raw_resp_json["message"] +// .as_str() +// .unwrap_or("null") +// .to_owned(), +// upstream_header: upstream_raw_resp.read_headers(), +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// }, +// is_custom: true, +// custom_message: format!( +// "[GET USER_INFO][U] 致命错误: 不能用于获取用户信息的APPKEY {appkey} - APPSEC {appsec}" +// ), +// }); +// report_health(health_report_type, bili_runtime).await; +// Err(EType::ServerReqError("APPKEY失效")) +// } +// // -400 => { +// // // 已经指定appkey, 不应当出现此错误 +// // error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -400. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {}. Upstream Reply -> {}", +// // access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json +// // ); +// // Err(EType::OtherError(-400, "可能你用的不是手机")) +// // } +// -101 => { +// // -101必定是登录失效, 观察发现也只有网页端会这样, 缓存25天 +// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; +// // update_user_info_cache(&output_struct, bili_runtime).await; +// error!( +// "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", +// access_key, upstream_raw_resp_json +// ); +// Err(EType::UserNotLoginedError) +// } +// 61000 => { +// // 那先看成未登录 +// // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 +// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; +// error!( +// "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", +// access_key, upstream_raw_resp_json +// ); +// Err(EType::UserLoginInvalid) +// } +// -412 => { +// error!( +// "[GET USER_INFO][U] AK {} | Get UserInfo failed -412. Upstream Reply -> {}", +// access_key, upstream_raw_resp_json +// ); +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: true, +// upstream_reply: UpstreamReply { +// code: -412, +// message: upstream_raw_resp_json["message"] +// .as_str() +// .unwrap_or("null") +// .to_owned(), +// upstream_header: upstream_raw_resp.read_headers(), +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// }, +// is_custom: true, +// custom_message: format!( +// "[GET USER_INFO][U] 致命错误! 机子-412喵! 上游返回: {upstream_raw_resp}" +// ), +// }); +// report_health(health_report_type, bili_runtime).await; +// Err(EType::ServerFatalError) +// } +// -663 => { +// // 已知的-663错误的原因 +// // 1. access_key和appkey不对应, message为"鉴权失败,请联系账号组" +// // 2. api已经弃用, meassage为"-663" +// error!( +// "[GET USER_INFO][U] AK {} | Get UserInfo failed -663. Using appkey: {}. Upstream Reply -> {}", +// access_key, appkey, upstream_raw_resp_json +// ); +// let output_struct = UserInfo { +// code, +// access_key: access_key.to_owned(), +// expire_time: ts + 10 * 60 * 1000, // 暂时缓存10m +// ..Default::default() +// }; +// update_user_info_cache(&output_struct, bili_runtime).await; +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: true, +// upstream_reply: UpstreamReply { +// code, +// message: upstream_raw_resp_json["message"].as_str().unwrap_or("null").to_owned(), +// upstream_header: upstream_raw_resp.read_headers(), +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// }, +// is_custom: true, +// custom_message: format!( +// "[GET USER_INFO][U] -663错误, 大概率access_key和appkey不对应. 频繁出现此错误请提issue处理\nAPPKEY: {}, AK: {}, TS: {}", +// appkey, access_key, ts +// ), +// }); +// report_health(health_report_type, bili_runtime).await; +// // Err(EType::ServerReqError("-663错误, 请检查access_key是否由对应appkey生成")) +// Err(EType::OtherUpstreamError( +// -663, +// upstream_raw_resp_json["message"] +// .as_str() +// .unwrap_or("null") +// .to_owned(), +// )) +// } +// _ => { +// error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", +// access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json +// ); +// error!("[GET USER_INFO][U] URL {}", signed_url); +// // 不采用常规方法更新, 仅限用于未知的错误码下的刷新 +// update_cached_user_info_background(access_key.to_owned(), bili_runtime).await; +// let health_report_type = HealthReportType::Others(HealthData { +// area_num: 0, +// is_200_ok: true, +// upstream_reply: UpstreamReply { +// code, +// message: upstream_raw_resp_json["message"] +// .as_str() +// .unwrap_or("null") +// .to_owned(), +// upstream_header: upstream_raw_resp.read_headers(), +// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, +// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), +// }, +// is_custom: true, +// custom_message: format!( +// "[GET USER_INFO][U] 致命错误! 未知的错误码! 上游返回: {upstream_raw_resp}" +// ), +// }); +// report_health(health_report_type, bili_runtime).await; +// Err(EType::OtherUpstreamError( +// code, +// upstream_raw_resp_json["message"] +// .as_str() +// .unwrap_or("NULL") +// .to_string(), +// )) +// } +// } +// } pub async fn get_upstream_bili_account_info_vip_due_date( mid: u64, @@ -401,9 +800,10 @@ pub async fn get_upstream_bili_account_info_vip_due_date( } /// 仅适配粉版客户端, 其他客户端未测试 +/// 需要使用此法刷新的, 大概率是web端的key pub async fn get_upstream_bili_account_info_ak_to_mid( access_key: &str, - client_type: &ClientType, + _client_type: &ClientType, bili_runtime: &BiliRuntime<'_>, ) -> Option { let ts_min_string = Local::now().timestamp().to_string(); @@ -414,7 +814,7 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( ); let req_vec = vec![ ("access_key", access_key), - ("appkey", client_type.appkey()), + ("appkey", "27eb53fc9058f8c3"), // 写死为ios的key ("build", "5360000"), ("mobi_app", "android"), ("platform", "android"), @@ -426,9 +826,8 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( let mut headers = HeaderMap::new(); headers.insert("buvid", HeaderValue::from_str(&fake_buvid).unwrap()); let fake_display_id = { - let mut display_id = String::with_capacity(200); - display_id.push_str(&fake_buvid); - display_id.push_str("-"); + let mut display_id = String::with_capacity(100); + display_id.push_str("0-"); display_id.push_str(&ts_min_string); display_id }; @@ -450,7 +849,7 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( headers }; - let (signed_api, _) = build_signed_url!(api, req_vec, client_type.appsec()); + let (signed_api, _) = build_signed_url!(api, req_vec, "c2ed53a74eeefe3cf99fbd01d8c9c375"); // 写死是ios的appsec let upstream_raw_resp = match async_getwebpage( &signed_api, bili_runtime.config.cn_proxy_accesskey_open, @@ -576,7 +975,10 @@ pub async fn get_upstream_blacklist_info( match async_getwebpage(&format!("{api}{uid}"), false, "", &user_agent, "", None).await { Ok(data) => data, Err(_) => { - error!("[GET USER_CER_INFO][U] 服务器网络问题 URL {}",format!("{api}{uid}")); + error!( + "[GET USER_CER_INFO][U] 服务器网络问题 URL {}", + format!("{api}{uid}") + ); let health_report_type = HealthReportType::Others(HealthData { area_num: 0, is_200_ok: false, diff --git a/src/mods/user_info.rs b/src/mods/user_info.rs index a3d77a66..fc3dab5b 100644 --- a/src/mods/user_info.rs +++ b/src/mods/user_info.rs @@ -1,7 +1,7 @@ use super::cache::{get_cached_blacklist_info, get_cached_user_info}; use super::request::{async_getwebpage, async_postwebpage}; use super::types::{BiliRuntime, ClientType, EType, PlayurlParams, UserInfo, UserResignInfo}; -use super::upstream_res::{get_upstream_bili_account_info, get_upstream_blacklist_info}; +use super::upstream_res::{get_upstream_bili_account_info_rec, get_upstream_blacklist_info}; use crate::build_signed_params; use chrono::prelude::*; use log::{debug, error, info}; @@ -10,8 +10,8 @@ use log::{debug, error, info}; #[inline] pub async fn get_user_info( access_key: &str, - appkey: &str, - is_app: bool, + _appkey: &str, + _is_app: bool, client_type: &ClientType, bili_runtime: &BiliRuntime<'_>, ) -> Result { @@ -36,12 +36,11 @@ pub async fn get_user_info( } } None => { - match get_upstream_bili_account_info( + match get_upstream_bili_account_info_rec( access_key, - appkey, - is_app, client_type, bili_runtime, + false, ) .await { From dbf87bb6beb1178ae5dd484f50c0bd4f9cce09a0 Mon Sep 17 00:00:00 2001 From: cxw620 Date: Tue, 10 Jan 2023 15:14:02 +0800 Subject: [PATCH 3/4] fix: ParseIntError panic --- src/mods/upstream_res.rs | 401 ++------------------------------------- 1 file changed, 14 insertions(+), 387 deletions(-) diff --git a/src/mods/upstream_res.rs b/src/mods/upstream_res.rs index 82d6f5ef..f0f2d92b 100644 --- a/src/mods/upstream_res.rs +++ b/src/mods/upstream_res.rs @@ -24,45 +24,6 @@ use reqwest::header::{HeaderMap, HeaderValue}; use serde_json::json; use std::string::String; -// pub async fn get_upstream_bili_account_info( -// access_key: &str, -// appkey: &str, -// is_app: bool, -// client_type: &ClientType, -// bili_runtime: &BiliRuntime<'_>, -// ) -> Result { -// // match get_upstream_bili_account_info_app(access_key, appkey, client_type, bili_runtime).await { -// // Ok(value) => Ok(value), -// // Err(err_type) => { -// // // more method get mid -// // if let Some(mid) = -// // get_upstream_bili_account_info_ak_to_mid(access_key, client_type, bili_runtime) -// // .await -// // { -// // if let Some(vip_expire_time) = -// // get_upstream_bili_account_info_vip_due_date(mid, bili_runtime).await -// // { -// // return Ok(UserInfo::new(0, access_key, mid, vip_expire_time)); -// // } -// // }; -// // match err_type { -// // // web端可能appkey不可用? -// // EType::ServerReqError("-663错误, 被鼠鼠制裁了, 请稍后重试") => { -// // if !is_app { -// // let new_user_info = UserInfo::new_unintended_error(access_key); -// // update_user_info_cache(&new_user_info, bili_runtime).await; -// // Ok(new_user_info) -// // } else { -// // // app端再次出现-663就是寄 -// // Err(err_type) -// // } -// // } -// // _ => Err(err_type), -// // } -// // } -// // } -// } - pub fn get_upstream_bili_account_info_rec<'rec>( access_key: &'rec str, client_type: &'rec ClientType, @@ -426,347 +387,6 @@ pub fn get_upstream_bili_account_info_rec<'rec>( } }) } -// async fn get_upstream_bili_account_info_app( -// access_key: &str, -// client_type: &ClientType, -// bili_runtime: &BiliRuntime<'_>, -// ) -> Result { -// let dt = Local::now(); -// let ts = dt.timestamp_millis() as u64; -// let ts_min = dt.timestamp() as u64; -// let ts_min_string = ts_min.to_string(); -// // 必要信息 -// let appkey = client_type.appkey(); -// let appsec = client_type.appsec(); - -// // 降级至build 5360000 -// // let rand_num = { -// // let mut rng = rand::thread_rng(); -// // rng.gen_range(1000000..100000000) -// // }; - -// let mut req_vec = vec![ //以防万一,昨天抓了下包尽可能补全 -// ("access_key", access_key), -// ("appkey", appkey), -// ("build", "5360000"), -// // ("buvid", &fake_buvid), -// // ("c_locale", "zh_CN"), -// // ("channel", "master"), -// // ("disable_rcmd", "0"), -// // ("local_id",&rand_string_36), -// ("mobi_app",client_type.mobi_app().unwrap_or_else(|| { -// error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default mobi_app 'android'"); -// "android" -// })), -// ("platform", client_type.platform().unwrap_or_else(|| { -// error!("[GET USER_INFO][U] AK {access_key} | Detect invalid req, try default platform 'android'"); -// "android" -// })), -// // ("s_locale","zh_CN"), -// // ("statistics","%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.80.0%22%2C%22abtest%22%3A%22%22%7D"), -// ("ts", &ts_min_string), -// ]; -// req_vec.sort_by_key(|v| v.0); - -// // fix -663 error -// // let mut headers = HeaderMap::new(); -// // headers.insert( -// // "x-bili-aurora-eid", -// // HeaderValue::from_bytes(mid_to_eid(&format!("{}", rand_num)).as_bytes()).unwrap(), -// // ); -// // headers.insert("x-bili-aurora-zone", HeaderValue::from_static("sh001")); -// // headers.insert("app-key",HeaderValue::from_static("android64")); - -// let headers = { -// let fake_buvid = UniqueId::UserInfoOld.buvid(); -// let mut headers = HeaderMap::new(); -// headers.insert("buvid", HeaderValue::from_str(&fake_buvid).unwrap()); -// let fake_display_id = { -// let mut display_id = String::with_capacity(100); -// display_id.push_str("0-"); -// display_id.push_str(&ts_min_string); -// display_id -// }; -// headers.insert( -// "display-id", -// HeaderValue::from_str(&fake_display_id).unwrap(), -// ); -// // 如: Pg5oWT8NNQJmVTAEeAR4 -// headers.insert( -// "device-id", -// HeaderValue::from_str(&{ -// random_string!( -// 20, -// b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" -// ) -// }) -// .unwrap(), -// ); -// headers -// }; - -// let api = format!( -// "https://{}/x/v2/account/myinfo", -// bili_runtime.config.general_app_bilibili_com_proxy_api -// ); -// let (signed_url, sign) = build_signed_url!(api, req_vec, appsec); -// let upstream_raw_resp = match async_getwebpage( -// &signed_url, -// bili_runtime.config.cn_proxy_accesskey_open, -// &bili_runtime.config.cn_proxy_accesskey_url, -// // &FakeUA::Bilibili.gen(), -// "Mozilla/5.0 BiliDroid/5.36.0 (bbcallen@gmail.com)", // 旧版客户端请求UA固定此值 -// "", -// Some(headers), -// ) -// .await -// { -// Ok(data) => data, -// Err(_) => { -// error!( -// "[GET USER_INFO][U] AK {} | Req failed. Network Problems. RAW QUERY -> TS {} Use Proxy {} - {}", -// access_key, ts_min, bili_runtime.config.cn_proxy_accesskey_open, &bili_runtime.config.cn_proxy_accesskey_url, -// ); -// { -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: false, -// upstream_reply: UpstreamReply { -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// ..Default::default() -// }, -// is_custom: true, -// custom_message: "[GET USERINFO][U] 致命错误! 获取用户信息失败!".to_owned(), -// }); -// report_health(health_report_type, bili_runtime).await; -// } - -// let new_user_info = UserInfo::new_unintended_error(access_key); -// update_user_info_cache(&new_user_info, bili_runtime).await; -// return Ok(new_user_info); -// } -// }; - -// let upstream_raw_resp_json = upstream_raw_resp -// .json() -// .unwrap_or(json!({"code": -500, "message": "[SERVER] 解析上游JSON错误"})); -// let code = if let Some(value) = upstream_raw_resp_json["code"].as_i64() { -// value -// } else { -// debug!( -// "[GET USER_INFO][U] AK {} | Parsing Upstream reply failed, Upstream Reply -> {}", -// access_key, upstream_raw_resp -// ); -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: true, -// upstream_reply: UpstreamReply { -// upstream_header: upstream_raw_resp.read_headers(), -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// ..Default::default() -// }, -// is_custom: true, -// custom_message: format!("致命错误! 解析用户信息失败!\n上游返回: {upstream_raw_resp}"), -// }); -// report_health(health_report_type, bili_runtime).await; -// return Err(EType::ServerReqError("解析用户信息失败")); -// }; - -// match code { -// 0 => { -// if upstream_raw_resp_json["data"]["mid"].as_u64().unwrap_or(0) == 0 { -// // accesskey失效时mid为0, 缓存25d -// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; -// error!( -// "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", -// access_key, upstream_raw_resp_json -// ); -// Err(EType::UserNotLoginedError) -// } else { -// let vip_expire_time = upstream_raw_resp_json["data"]["vip"]["due_date"] -// .as_u64() -// .unwrap(); -// let output_struct = UserInfo { -// code: 0, -// access_key: String::from(access_key), -// uid: upstream_raw_resp_json["data"]["mid"].as_u64().unwrap(), -// vip_expire_time, -// expire_time: { -// if ts < vip_expire_time && vip_expire_time < ts + 25 * 24 * 60 * 60 * 1000 { -// vip_expire_time -// } else { -// ts + 25 * 24 * 60 * 60 * 1000 -// } -// }, //用户状态25天强制更新 -// }; -// update_user_info_cache(&output_struct, bili_runtime).await; -// Ok(output_struct) -// } -// } -// -3 => { -// // 不应该出现签名错误, 除非B站更改签名算法 -// error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -3. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", -// access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json -// ); -// Ok(UserInfo::new_unintended_error(access_key)) -// } -// -400 | -404 => { -// error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. Invalid APPKEY -> APPKEY {} | TS {} | APPSEC {}. Upstream Reply -> {}", -// access_key, appkey, ts_min, appsec, upstream_raw_resp -// ); -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: true, -// upstream_reply: UpstreamReply { -// code, -// message: upstream_raw_resp_json["message"] -// .as_str() -// .unwrap_or("null") -// .to_owned(), -// upstream_header: upstream_raw_resp.read_headers(), -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// }, -// is_custom: true, -// custom_message: format!( -// "[GET USER_INFO][U] 致命错误: 不能用于获取用户信息的APPKEY {appkey} - APPSEC {appsec}" -// ), -// }); -// report_health(health_report_type, bili_runtime).await; -// Err(EType::ServerReqError("APPKEY失效")) -// } -// // -400 => { -// // // 已经指定appkey, 不应当出现此错误 -// // error!("[GET USER_INFO][U] AK {} | Get UserInfo failed -400. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {}. Upstream Reply -> {}", -// // access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json -// // ); -// // Err(EType::OtherError(-400, "可能你用的不是手机")) -// // } -// -101 => { -// // -101必定是登录失效, 观察发现也只有网页端会这样, 缓存25天 -// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; -// // update_user_info_cache(&output_struct, bili_runtime).await; -// error!( -// "[GET USER_INFO][U] AK {} | Get UserInfo failed -101. Upstream Reply -> {}", -// access_key, upstream_raw_resp_json -// ); -// Err(EType::UserNotLoginedError) -// } -// 61000 => { -// // 那先看成未登录 -// // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 -// update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; -// error!( -// "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", -// access_key, upstream_raw_resp_json -// ); -// Err(EType::UserLoginInvalid) -// } -// -412 => { -// error!( -// "[GET USER_INFO][U] AK {} | Get UserInfo failed -412. Upstream Reply -> {}", -// access_key, upstream_raw_resp_json -// ); -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: true, -// upstream_reply: UpstreamReply { -// code: -412, -// message: upstream_raw_resp_json["message"] -// .as_str() -// .unwrap_or("null") -// .to_owned(), -// upstream_header: upstream_raw_resp.read_headers(), -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// }, -// is_custom: true, -// custom_message: format!( -// "[GET USER_INFO][U] 致命错误! 机子-412喵! 上游返回: {upstream_raw_resp}" -// ), -// }); -// report_health(health_report_type, bili_runtime).await; -// Err(EType::ServerFatalError) -// } -// -663 => { -// // 已知的-663错误的原因 -// // 1. access_key和appkey不对应, message为"鉴权失败,请联系账号组" -// // 2. api已经弃用, meassage为"-663" -// error!( -// "[GET USER_INFO][U] AK {} | Get UserInfo failed -663. Using appkey: {}. Upstream Reply -> {}", -// access_key, appkey, upstream_raw_resp_json -// ); -// let output_struct = UserInfo { -// code, -// access_key: access_key.to_owned(), -// expire_time: ts + 10 * 60 * 1000, // 暂时缓存10m -// ..Default::default() -// }; -// update_user_info_cache(&output_struct, bili_runtime).await; -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: true, -// upstream_reply: UpstreamReply { -// code, -// message: upstream_raw_resp_json["message"].as_str().unwrap_or("null").to_owned(), -// upstream_header: upstream_raw_resp.read_headers(), -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// }, -// is_custom: true, -// custom_message: format!( -// "[GET USER_INFO][U] -663错误, 大概率access_key和appkey不对应. 频繁出现此错误请提issue处理\nAPPKEY: {}, AK: {}, TS: {}", -// appkey, access_key, ts -// ), -// }); -// report_health(health_report_type, bili_runtime).await; -// // Err(EType::ServerReqError("-663错误, 请检查access_key是否由对应appkey生成")) -// Err(EType::OtherUpstreamError( -// -663, -// upstream_raw_resp_json["message"] -// .as_str() -// .unwrap_or("null") -// .to_owned(), -// )) -// } -// _ => { -// error!("[GET USER_INFO][U] AK {} -> Get UserInfo failed. REQ Params -> APPKEY {} | TS {} | APPSEC {} | SIGN {:?}. Upstream Reply -> {}", -// access_key, appkey, ts_min, appsec, sign, upstream_raw_resp_json -// ); -// error!("[GET USER_INFO][U] URL {}", signed_url); -// // 不采用常规方法更新, 仅限用于未知的错误码下的刷新 -// update_cached_user_info_background(access_key.to_owned(), bili_runtime).await; -// let health_report_type = HealthReportType::Others(HealthData { -// area_num: 0, -// is_200_ok: true, -// upstream_reply: UpstreamReply { -// code, -// message: upstream_raw_resp_json["message"] -// .as_str() -// .unwrap_or("null") -// .to_owned(), -// upstream_header: upstream_raw_resp.read_headers(), -// proxy_open: bili_runtime.config.cn_proxy_accesskey_open, -// proxy_url: bili_runtime.config.cn_proxy_accesskey_url.clone(), -// }, -// is_custom: true, -// custom_message: format!( -// "[GET USER_INFO][U] 致命错误! 未知的错误码! 上游返回: {upstream_raw_resp}" -// ), -// }); -// report_health(health_report_type, bili_runtime).await; -// Err(EType::OtherUpstreamError( -// code, -// upstream_raw_resp_json["message"] -// .as_str() -// .unwrap_or("NULL") -// .to_string(), -// )) -// } -// } -// } pub async fn get_upstream_bili_account_info_vip_due_date( mid: u64, @@ -803,10 +423,12 @@ pub async fn get_upstream_bili_account_info_vip_due_date( /// 需要使用此法刷新的, 大概率是web端的key pub async fn get_upstream_bili_account_info_ak_to_mid( access_key: &str, - _client_type: &ClientType, + client_type: &ClientType, bili_runtime: &BiliRuntime<'_>, ) -> Option { let ts_min_string = Local::now().timestamp().to_string(); + let appkey = client_type.appkey(); + let appsec = client_type.appsec(); let api = format!( "https://{}/x/v2/display/id", @@ -814,7 +436,7 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( ); let req_vec = vec![ ("access_key", access_key), - ("appkey", "27eb53fc9058f8c3"), // 写死为ios的key + ("appkey", appkey), ("build", "5360000"), ("mobi_app", "android"), ("platform", "android"), @@ -849,7 +471,7 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( headers }; - let (signed_api, _) = build_signed_url!(api, req_vec, "c2ed53a74eeefe3cf99fbd01d8c9c375"); // 写死是ios的appsec + let (signed_api, _) = build_signed_url!(api, req_vec, appsec); let upstream_raw_resp = match async_getwebpage( &signed_api, bili_runtime.config.cn_proxy_accesskey_open, @@ -871,10 +493,15 @@ pub async fn get_upstream_bili_account_info_ak_to_mid( match code { 0 => { if let Some(id) = upstream_raw_resp_json["data"]["id"].as_str() { - let mid = id.split("-").collect::>()[0] - .parse::() - .unwrap(); - Some(mid) + let mid = id + .split("-") + .map(|split_part| split_part.parse::().unwrap_or(0)) + .collect::>(); + if mid[0] > 0 { + Some(mid[0] as u64) + } else { + None + } } else { let health_report_type = HealthReportType::Others(HealthData { area_num: 0, From 32d3c561a7189c1645a8678c125e1e0375c3013e Mon Sep 17 00:00:00 2001 From: cxw620 Date: Tue, 10 Jan 2023 15:49:22 +0800 Subject: [PATCH 4/4] fix: 61000 error --- src/mods/upstream_res.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/mods/upstream_res.rs b/src/mods/upstream_res.rs index f0f2d92b..5b15bb63 100644 --- a/src/mods/upstream_res.rs +++ b/src/mods/upstream_res.rs @@ -249,8 +249,9 @@ pub fn get_upstream_bili_account_info_rec<'rec>( // ); // Err(EType::OtherError(-400, "可能你用的不是手机")) // } - -101 => { + -101 | 61000 => { // -101必定是登录失效, 观察发现也只有网页端会这样, 缓存25天 + // 61000是因为用了错误的appkey且登录失效 update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; // update_user_info_cache(&output_struct, bili_runtime).await; error!( @@ -259,16 +260,16 @@ pub fn get_upstream_bili_account_info_rec<'rec>( ); Err(EType::UserNotLoginedError) } - 61000 => { - // 那先看成未登录 - // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 - update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; - error!( - "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", - access_key, upstream_raw_resp_json - ); - Err(EType::UserLoginInvalid) - } + // 61000 => { + // // 那先看成未登录 + // // 61000是登录失效, 观察发现后续应该无法使用这个accesskey获取到用户信息了, 缓存25天 + // update_user_info_cache(&UserInfo::new(code, access_key, 0, 0), bili_runtime).await; + // error!( + // "[GET USER_INFO][U] AK {} | Get UserInfo failed 61000. Maybe AK out of date. Upstream Reply -> {}", + // access_key, upstream_raw_resp_json + // ); + // Err(EType::UserLoginInvalid) + // } -412 => { error!( "[GET USER_INFO][U] AK {} | Get UserInfo failed -412. Upstream Reply -> {}",