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,
|
dynamic wwebid,
|
||||||
}) async {
|
}) async {
|
||||||
space(mid: mid);
|
space(mid: mid);
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'mid': mid,
|
'mid': mid,
|
||||||
'token': token,
|
'token': token,
|
||||||
'platform': 'web',
|
'platform': 'web',
|
||||||
@@ -348,7 +348,7 @@ class MemberHttp {
|
|||||||
}) async {
|
}) async {
|
||||||
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
|
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
|
||||||
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
|
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'mid': mid,
|
'mid': mid,
|
||||||
'ps': ps,
|
'ps': ps,
|
||||||
'tid': tid,
|
'tid': tid,
|
||||||
@@ -393,7 +393,7 @@ class MemberHttp {
|
|||||||
}) async {
|
}) async {
|
||||||
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
|
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
|
||||||
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
|
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'offset': offset ?? '',
|
'offset': offset ?? '',
|
||||||
'host_mid': mid,
|
'host_mid': mid,
|
||||||
'timezone_offset': '-480',
|
'timezone_offset': '-480',
|
||||||
@@ -595,7 +595,7 @@ class MemberHttp {
|
|||||||
|
|
||||||
// 最近投币
|
// 最近投币
|
||||||
static Future<LoadingState> getRecentCoinVideo({required int mid}) async {
|
static Future<LoadingState> getRecentCoinVideo({required int mid}) async {
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'mid': mid,
|
'mid': mid,
|
||||||
'gaia_source': 'main_web',
|
'gaia_source': 'main_web',
|
||||||
'web_location': 333.999,
|
'web_location': 333.999,
|
||||||
@@ -621,7 +621,7 @@ class MemberHttp {
|
|||||||
|
|
||||||
// 最近点赞
|
// 最近点赞
|
||||||
static Future<LoadingState> getRecentLikeVideo({required int mid}) async {
|
static Future<LoadingState> getRecentLikeVideo({required int mid}) async {
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'mid': mid,
|
'mid': mid,
|
||||||
'gaia_source': 'main_web',
|
'gaia_source': 'main_web',
|
||||||
'web_location': 333.999,
|
'web_location': 333.999,
|
||||||
@@ -713,7 +713,7 @@ class MemberHttp {
|
|||||||
'name': name,
|
'name': name,
|
||||||
'web_location': 333.999,
|
'web_location': 333.999,
|
||||||
};
|
};
|
||||||
Map params = await WbiSign().makSign(data);
|
Map params = await WbiSign.makSign(data);
|
||||||
var res = await Request().get(Api.followSearch, queryParameters: {
|
var res = await Request().get(Api.followSearch, queryParameters: {
|
||||||
...data,
|
...data,
|
||||||
'w_rid': params['w_rid'],
|
'w_rid': params['w_rid'],
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ class MsgHttp {
|
|||||||
String? biz,
|
String? biz,
|
||||||
}) async {
|
}) async {
|
||||||
String csrf = await Request.getCsrf();
|
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),
|
'file_up': await MultipartFile.fromFile(path),
|
||||||
if (category != null) 'category': category,
|
if (category != null) 'category': category,
|
||||||
if (biz != null) 'biz': biz,
|
if (biz != null) 'biz': biz,
|
||||||
@@ -285,7 +285,7 @@ class MsgHttp {
|
|||||||
dynamic content,
|
dynamic content,
|
||||||
) async {
|
) async {
|
||||||
String csrf = await Request.getCsrf();
|
String csrf = await Request.getCsrf();
|
||||||
Map<String, dynamic> data = await WbiSign().makSign({
|
Map<String, dynamic> data = await WbiSign.makSign({
|
||||||
'dynamic_id': 0,
|
'dynamic_id': 0,
|
||||||
'type': 4,
|
'type': 4,
|
||||||
'rid': 0,
|
'rid': 0,
|
||||||
@@ -311,7 +311,7 @@ class MsgHttp {
|
|||||||
dynamic dynamicId,
|
dynamic dynamicId,
|
||||||
) async {
|
) async {
|
||||||
String csrf = await Request.getCsrf();
|
String csrf = await Request.getCsrf();
|
||||||
Map<String, dynamic> data = await WbiSign().makSign({
|
Map<String, dynamic> data = await WbiSign.makSign({
|
||||||
'dynamic_id': dynamicId,
|
'dynamic_id': dynamicId,
|
||||||
'csrf_token': csrf,
|
'csrf_token': csrf,
|
||||||
'csrf': csrf,
|
'csrf': csrf,
|
||||||
@@ -334,7 +334,7 @@ class MsgHttp {
|
|||||||
dynamic talkerId,
|
dynamic talkerId,
|
||||||
) async {
|
) async {
|
||||||
String csrf = await Request.getCsrf();
|
String csrf = await Request.getCsrf();
|
||||||
Map<String, dynamic> data = await WbiSign().makSign({
|
Map<String, dynamic> data = await WbiSign.makSign({
|
||||||
'talker_id': talkerId,
|
'talker_id': talkerId,
|
||||||
'session_type': 1,
|
'session_type': 1,
|
||||||
'build': 0,
|
'build': 0,
|
||||||
@@ -387,7 +387,7 @@ class MsgHttp {
|
|||||||
int opType,
|
int opType,
|
||||||
) async {
|
) async {
|
||||||
String csrf = await Request.getCsrf();
|
String csrf = await Request.getCsrf();
|
||||||
Map<String, dynamic> data = await WbiSign().makSign({
|
Map<String, dynamic> data = await WbiSign.makSign({
|
||||||
'talker_id': talkerId,
|
'talker_id': talkerId,
|
||||||
'session_type': 1,
|
'session_type': 1,
|
||||||
'op_type': opType,
|
'op_type': opType,
|
||||||
@@ -422,7 +422,7 @@ class MsgHttp {
|
|||||||
params['end_ts'] = endTs;
|
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);
|
var res = await Request().get(Api.sessionList, queryParameters: signParams);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
try {
|
try {
|
||||||
@@ -475,7 +475,7 @@ class MsgHttp {
|
|||||||
static Future sessionMsg({
|
static Future sessionMsg({
|
||||||
int? talkerId,
|
int? talkerId,
|
||||||
}) async {
|
}) async {
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'talker_id': talkerId,
|
'talker_id': talkerId,
|
||||||
'session_type': 1,
|
'session_type': 1,
|
||||||
'size': 20,
|
'size': 20,
|
||||||
@@ -508,7 +508,7 @@ class MsgHttp {
|
|||||||
int? ackSeqno,
|
int? ackSeqno,
|
||||||
}) async {
|
}) async {
|
||||||
String csrf = await Request.getCsrf();
|
String csrf = await Request.getCsrf();
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'talker_id': talkerId,
|
'talker_id': talkerId,
|
||||||
'session_type': 1,
|
'session_type': 1,
|
||||||
'ack_seqno': ackSeqno,
|
'ack_seqno': ackSeqno,
|
||||||
@@ -559,7 +559,7 @@ class MsgHttp {
|
|||||||
'csrf_token': csrf,
|
'csrf_token': csrf,
|
||||||
'csrf': 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,
|
var res = await Request().post(Api.sendMsg,
|
||||||
queryParameters: <String, dynamic>{
|
queryParameters: <String, dynamic>{
|
||||||
'w_sender_uid': params['msg[sender_uid]'],
|
'w_sender_uid': params['msg[sender_uid]'],
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ class UserHttp {
|
|||||||
}
|
}
|
||||||
// // 相互关系查询
|
// // 相互关系查询
|
||||||
// static Future relationSearch(int mid) async {
|
// static Future relationSearch(int mid) async {
|
||||||
// Map params = await WbiSign().makSign({
|
// Map params = await WbiSign.makSign({
|
||||||
// 'mid': mid,
|
// 'mid': mid,
|
||||||
// 'token': '',
|
// 'token': '',
|
||||||
// 'platform': 'web',
|
// 'platform': 'web',
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ class VideoHttp {
|
|||||||
data['try_look'] = 1;
|
data['try_look'] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
...data,
|
...data,
|
||||||
'fourk': 1,
|
'fourk': 1,
|
||||||
'voice_balance': 1,
|
'voice_balance': 1,
|
||||||
@@ -976,7 +976,7 @@ class VideoHttp {
|
|||||||
int? cid,
|
int? cid,
|
||||||
int? upMid,
|
int? upMid,
|
||||||
}) async {
|
}) async {
|
||||||
Map params = await WbiSign().makSign({
|
Map params = await WbiSign.makSign({
|
||||||
'bvid': bvid,
|
'bvid': bvid,
|
||||||
'cid': cid,
|
'cid': cid,
|
||||||
'up_mid': upMid,
|
'up_mid': upMid,
|
||||||
|
|||||||
@@ -717,7 +717,7 @@ class LocalCacheKey {
|
|||||||
accessKey = 'accessKey',
|
accessKey = 'accessKey',
|
||||||
|
|
||||||
//
|
//
|
||||||
wbiKeys = 'wbiKeys',
|
mixinKey = 'mixinKey',
|
||||||
timeStamp = 'timeStamp';
|
timeStamp = 'timeStamp';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:synchronized/synchronized.dart';
|
||||||
import '../http/index.dart';
|
import '../http/index.dart';
|
||||||
import 'storage.dart';
|
import 'storage.dart';
|
||||||
|
|
||||||
class WbiSign {
|
class WbiSign {
|
||||||
static Box get localCache => GStorage.localCache;
|
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,
|
46,
|
||||||
47,
|
47,
|
||||||
18,
|
18,
|
||||||
@@ -42,106 +45,58 @@ class WbiSign {
|
|||||||
12,
|
12,
|
||||||
38,
|
38,
|
||||||
41,
|
41,
|
||||||
13,
|
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
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 对 imgKey 和 subKey 进行字符顺序打乱编码
|
// 对 imgKey 和 subKey 进行字符顺序打乱编码
|
||||||
String getMixinKey(String orig) {
|
static String getMixinKey(String orig) {
|
||||||
String temp = '';
|
return mixinKeyEncTab.map((i) => orig[i]).join();
|
||||||
for (int i = 0; i < mixinKeyEncTab.length; i++) {
|
|
||||||
temp += orig[mixinKeyEncTab[i]];
|
|
||||||
}
|
|
||||||
return temp.substring(0, 32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为请求参数进行 wbi 签名
|
// 为请求参数进行 wbi 签名
|
||||||
Map<String, dynamic> encWbi(
|
static void encWbi(Map<String, dynamic> params, String mixinKey) {
|
||||||
Map<String, dynamic> params, String imgKey, String subKey) {
|
params['wts'] = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
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 字段
|
|
||||||
// 按照 key 重排参数
|
// 按照 key 重排参数
|
||||||
final List<String> keys = newParams.keys.toList()..sort();
|
final List<String> keys = params.keys.toList()..sort();
|
||||||
for (String i in keys) {
|
final queryStr = keys
|
||||||
query.add(
|
.map((i) =>
|
||||||
'${Uri.encodeComponent(i)}=${Uri.encodeComponent(newParams[i].toString().replaceAll(chrFilter, ''))}');
|
'${Uri.encodeComponent(i)}=${Uri.encodeComponent(params[i].toString().replaceAll(chrFilter, ''))}')
|
||||||
}
|
.join('&');
|
||||||
final String queryStr = query.join('&');
|
params['w_rid'] =
|
||||||
final String wbiSign =
|
|
||||||
md5.convert(utf8.encode(queryStr + mixinKey)).toString(); // 计算 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 可以从缓存中获取
|
// 获取最新的 img_key 和 sub_key 可以从缓存中获取
|
||||||
static Future<Map<String, dynamic>> getWbiKeys() async {
|
static Future<String> getWbiKeys() async {
|
||||||
final DateTime nowDate = DateTime.now();
|
final DateTime nowDate = DateTime.now();
|
||||||
if (localCache.get(LocalCacheKey.wbiKeys) != null &&
|
String? mixinKey = localCache.get(LocalCacheKey.mixinKey);
|
||||||
|
if (mixinKey != null &&
|
||||||
DateTime.fromMillisecondsSinceEpoch(
|
DateTime.fromMillisecondsSinceEpoch(
|
||||||
localCache.get(LocalCacheKey.timeStamp) as int)
|
localCache.get(LocalCacheKey.timeStamp) as int)
|
||||||
.day ==
|
.day ==
|
||||||
nowDate.day) {
|
nowDate.day) {
|
||||||
final Map cacheWbiKeys = localCache.get('wbiKeys');
|
return mixinKey;
|
||||||
return Map<String, dynamic>.from(cacheWbiKeys);
|
|
||||||
}
|
}
|
||||||
var resp =
|
final resp = await Request().get(Api.userInfo);
|
||||||
await Request().get('https://api.bilibili.com/x/web-interface/nav');
|
final wbiUrls = resp.data['data']['wbi_img'];
|
||||||
var jsonContent = resp.data['data'];
|
|
||||||
|
|
||||||
final String imgUrl = jsonContent['wbi_img']['img_url'];
|
mixinKey = getMixinKey(
|
||||||
final String subUrl = jsonContent['wbi_img']['sub_url'];
|
getFileName(wbiUrls['img_url']) + getFileName(wbiUrls['sub_url']));
|
||||||
final Map<String, dynamic> wbiKeys = {
|
|
||||||
'imgKey': imgUrl
|
localCache.put(LocalCacheKey.mixinKey, mixinKey);
|
||||||
.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length)
|
|
||||||
.split('.')[0],
|
|
||||||
'subKey': subUrl
|
|
||||||
.substring(subUrl.lastIndexOf('/') + 1, subUrl.length)
|
|
||||||
.split('.')[0]
|
|
||||||
};
|
|
||||||
localCache.put(LocalCacheKey.wbiKeys, wbiKeys);
|
|
||||||
localCache.put(LocalCacheKey.timeStamp, nowDate.millisecondsSinceEpoch);
|
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 为需要加密的请求参数
|
// params 为需要加密的请求参数
|
||||||
final Map<String, dynamic> wbiKeys = await getWbiKeys();
|
final String mixinKey = await lock.synchronized(getWbiKeys);
|
||||||
final Map<String, dynamic> query = params
|
encWbi(params, mixinKey);
|
||||||
..addAll(encWbi(params, wbiKeys['imgKey'], wbiKeys['subKey']));
|
return params;
|
||||||
return query;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1774,7 +1774,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.0"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: synchronized
|
name: synchronized
|
||||||
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
|
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ dependencies:
|
|||||||
flex_seed_scheme: ^3.4.1
|
flex_seed_scheme: ^3.4.1
|
||||||
live_photo_maker: ^0.0.6
|
live_photo_maker: ^0.0.6
|
||||||
fl_chart: ^0.69.2
|
fl_chart: ^0.69.2
|
||||||
|
synchronized: ^3.3.0
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
screen_brightness: ^2.0.1
|
screen_brightness: ^2.0.1
|
||||||
|
|||||||
Reference in New Issue
Block a user