opt: wbiSign (#332)

This commit is contained in:
My-Responsitories
2025-02-26 14:01:38 +00:00
committed by GitHub
parent fb11208bbe
commit 1c3d77b95d
8 changed files with 57 additions and 101 deletions

View File

@@ -278,7 +278,7 @@ class MemberHttp {
dynamic wwebid,
}) async {
space(mid: mid);
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'mid': mid,
'token': token,
'platform': 'web',
@@ -348,7 +348,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'mid': mid,
'ps': ps,
'tid': tid,
@@ -393,7 +393,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'offset': offset ?? '',
'host_mid': mid,
'timezone_offset': '-480',
@@ -595,7 +595,7 @@ class MemberHttp {
// 最近投币
static Future<LoadingState> getRecentCoinVideo({required int mid}) async {
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'mid': mid,
'gaia_source': 'main_web',
'web_location': 333.999,
@@ -621,7 +621,7 @@ class MemberHttp {
// 最近点赞
static Future<LoadingState> getRecentLikeVideo({required int mid}) async {
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'mid': mid,
'gaia_source': 'main_web',
'web_location': 333.999,
@@ -713,7 +713,7 @@ class MemberHttp {
'name': name,
'web_location': 333.999,
};
Map params = await WbiSign().makSign(data);
Map params = await WbiSign.makSign(data);
var res = await Request().get(Api.followSearch, queryParameters: {
...data,
'w_rid': params['w_rid'],

View File

@@ -258,7 +258,7 @@ class MsgHttp {
String? biz,
}) async {
String csrf = await Request.getCsrf();
Map<String, dynamic> data = await WbiSign().makSign({
Map<String, dynamic> data = await WbiSign.makSign({
'file_up': await MultipartFile.fromFile(path),
if (category != null) 'category': category,
if (biz != null) 'biz': biz,
@@ -285,7 +285,7 @@ class MsgHttp {
dynamic content,
) async {
String csrf = await Request.getCsrf();
Map<String, dynamic> data = await WbiSign().makSign({
Map<String, dynamic> data = await WbiSign.makSign({
'dynamic_id': 0,
'type': 4,
'rid': 0,
@@ -311,7 +311,7 @@ class MsgHttp {
dynamic dynamicId,
) async {
String csrf = await Request.getCsrf();
Map<String, dynamic> data = await WbiSign().makSign({
Map<String, dynamic> data = await WbiSign.makSign({
'dynamic_id': dynamicId,
'csrf_token': csrf,
'csrf': csrf,
@@ -334,7 +334,7 @@ class MsgHttp {
dynamic talkerId,
) async {
String csrf = await Request.getCsrf();
Map<String, dynamic> data = await WbiSign().makSign({
Map<String, dynamic> data = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'build': 0,
@@ -387,7 +387,7 @@ class MsgHttp {
int opType,
) async {
String csrf = await Request.getCsrf();
Map<String, dynamic> data = await WbiSign().makSign({
Map<String, dynamic> data = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'op_type': opType,
@@ -422,7 +422,7 @@ class MsgHttp {
params['end_ts'] = endTs;
}
Map signParams = await WbiSign().makSign(params);
Map signParams = await WbiSign.makSign(params);
var res = await Request().get(Api.sessionList, queryParameters: signParams);
if (res.data['code'] == 0) {
try {
@@ -475,7 +475,7 @@ class MsgHttp {
static Future sessionMsg({
int? talkerId,
}) async {
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'size': 20,
@@ -508,7 +508,7 @@ class MsgHttp {
int? ackSeqno,
}) async {
String csrf = await Request.getCsrf();
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'ack_seqno': ackSeqno,
@@ -559,7 +559,7 @@ class MsgHttp {
'csrf_token': csrf,
'csrf': csrf,
};
Map<String, dynamic> params = await WbiSign().makSign(base);
Map<String, dynamic> params = await WbiSign.makSign(base);
var res = await Request().post(Api.sendMsg,
queryParameters: <String, dynamic>{
'w_sender_uid': params['msg[sender_uid]'],

View File

@@ -356,7 +356,7 @@ class UserHttp {
}
// // 相互关系查询
// static Future relationSearch(int mid) async {
// Map params = await WbiSign().makSign({
// Map params = await WbiSign.makSign({
// 'mid': mid,
// 'token': '',
// 'platform': 'web',

View File

@@ -235,7 +235,7 @@ class VideoHttp {
data['try_look'] = 1;
}
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
...data,
'fourk': 1,
'voice_balance': 1,
@@ -976,7 +976,7 @@ class VideoHttp {
int? cid,
int? upMid,
}) async {
Map params = await WbiSign().makSign({
Map params = await WbiSign.makSign({
'bvid': bvid,
'cid': cid,
'up_mid': upMid,

View File

@@ -717,7 +717,7 @@ class LocalCacheKey {
accessKey = 'accessKey',
//
wbiKeys = 'wbiKeys',
mixinKey = 'mixinKey',
timeStamp = 'timeStamp';
}

View File

@@ -5,12 +5,15 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:hive/hive.dart';
import 'package:synchronized/synchronized.dart';
import '../http/index.dart';
import 'storage.dart';
class WbiSign {
static Box get localCache => GStorage.localCache;
final List<int> mixinKeyEncTab = <int>[
static final Lock lock = Lock();
static final RegExp chrFilter = RegExp(r"[!\'\(\)\*]");
static const mixinKeyEncTab = <int>[
46,
47,
18,
@@ -42,106 +45,58 @@ class WbiSign {
12,
38,
41,
13,
37,
48,
7,
16,
24,
55,
40,
61,
26,
17,
0,
1,
60,
51,
30,
4,
22,
25,
54,
21,
56,
59,
6,
63,
57,
62,
11,
36,
20,
34,
44,
52
13
];
// 对 imgKey 和 subKey 进行字符顺序打乱编码
String getMixinKey(String orig) {
String temp = '';
for (int i = 0; i < mixinKeyEncTab.length; i++) {
temp += orig[mixinKeyEncTab[i]];
}
return temp.substring(0, 32);
static String getMixinKey(String orig) {
return mixinKeyEncTab.map((i) => orig[i]).join();
}
// 为请求参数进行 wbi 签名
Map<String, dynamic> encWbi(
Map<String, dynamic> params, String imgKey, String subKey) {
final String mixinKey = getMixinKey(imgKey + subKey);
final DateTime now = DateTime.now();
final int currTime = (now.millisecondsSinceEpoch / 1000).round();
final RegExp chrFilter = RegExp(r"[!\'\(\)*]");
final List<String> query = <String>[];
final Map<String, dynamic> newParams = Map.from(params)
..addAll({"wts": currTime}); // 添加 wts 字段
static void encWbi(Map<String, dynamic> params, String mixinKey) {
params['wts'] = DateTime.now().millisecondsSinceEpoch ~/ 1000;
// 按照 key 重排参数
final List<String> keys = newParams.keys.toList()..sort();
for (String i in keys) {
query.add(
'${Uri.encodeComponent(i)}=${Uri.encodeComponent(newParams[i].toString().replaceAll(chrFilter, ''))}');
}
final String queryStr = query.join('&');
final String wbiSign =
final List<String> keys = params.keys.toList()..sort();
final queryStr = keys
.map((i) =>
'${Uri.encodeComponent(i)}=${Uri.encodeComponent(params[i].toString().replaceAll(chrFilter, ''))}')
.join('&');
params['w_rid'] =
md5.convert(utf8.encode(queryStr + mixinKey)).toString(); // 计算 w_rid
return {'w_rid': wbiSign, 'wts': currTime.toString()};
}
static String getFileName(String uri) {
return uri.substring(uri.lastIndexOf('/') + 1, uri.lastIndexOf('.'));
}
// 获取最新的 img_key 和 sub_key 可以从缓存中获取
static Future<Map<String, dynamic>> getWbiKeys() async {
static Future<String> getWbiKeys() async {
final DateTime nowDate = DateTime.now();
if (localCache.get(LocalCacheKey.wbiKeys) != null &&
String? mixinKey = localCache.get(LocalCacheKey.mixinKey);
if (mixinKey != null &&
DateTime.fromMillisecondsSinceEpoch(
localCache.get(LocalCacheKey.timeStamp) as int)
.day ==
nowDate.day) {
final Map cacheWbiKeys = localCache.get('wbiKeys');
return Map<String, dynamic>.from(cacheWbiKeys);
return mixinKey;
}
var resp =
await Request().get('https://api.bilibili.com/x/web-interface/nav');
var jsonContent = resp.data['data'];
final resp = await Request().get(Api.userInfo);
final wbiUrls = resp.data['data']['wbi_img'];
final String imgUrl = jsonContent['wbi_img']['img_url'];
final String subUrl = jsonContent['wbi_img']['sub_url'];
final Map<String, dynamic> wbiKeys = {
'imgKey': imgUrl
.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length)
.split('.')[0],
'subKey': subUrl
.substring(subUrl.lastIndexOf('/') + 1, subUrl.length)
.split('.')[0]
};
localCache.put(LocalCacheKey.wbiKeys, wbiKeys);
mixinKey = getMixinKey(
getFileName(wbiUrls['img_url']) + getFileName(wbiUrls['sub_url']));
localCache.put(LocalCacheKey.mixinKey, mixinKey);
localCache.put(LocalCacheKey.timeStamp, nowDate.millisecondsSinceEpoch);
return wbiKeys;
return mixinKey;
}
Future<Map<String, dynamic>> makSign(Map<String, dynamic> params) async {
static Future<Map<String, dynamic>> makSign(
Map<String, dynamic> params) async {
// params 为需要加密的请求参数
final Map<String, dynamic> wbiKeys = await getWbiKeys();
final Map<String, dynamic> query = params
..addAll(encWbi(params, wbiKeys['imgKey'], wbiKeys['subKey']));
return query;
final String mixinKey = await lock.synchronized(getWbiKeys);
encWbi(params, mixinKey);
return params;
}
}

View File

@@ -1774,7 +1774,7 @@ packages:
source: hosted
version: "1.2.0"
synchronized:
dependency: transitive
dependency: "direct main"
description:
name: synchronized
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"

View File

@@ -182,6 +182,7 @@ dependencies:
flex_seed_scheme: ^3.4.1
live_photo_maker: ^0.0.6
fl_chart: ^0.69.2
synchronized: ^3.3.0
dependency_overrides:
screen_brightness: ^2.0.1