mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: wbiSign (#332)
This commit is contained in:
committed by
GitHub
parent
fb11208bbe
commit
1c3d77b95d
@@ -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'],
|
||||
|
||||
@@ -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]'],
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -717,7 +717,7 @@ class LocalCacheKey {
|
||||
accessKey = 'accessKey',
|
||||
|
||||
//
|
||||
wbiKeys = 'wbiKeys',
|
||||
mixinKey = 'mixinKey',
|
||||
timeStamp = 'timeStamp';
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1774,7 +1774,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user