mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
mod: app端推荐参数补充,统一部分代码位置
This commit is contained in:
@@ -5,19 +5,27 @@ import 'package:dio/dio.dart';
|
||||
import 'package:encrypt/encrypt.dart';
|
||||
import '../common/constants.dart';
|
||||
import '../models/login/index.dart';
|
||||
import '../utils/login.dart';
|
||||
import '../utils/utils.dart';
|
||||
import 'index.dart';
|
||||
|
||||
class LoginHttp {
|
||||
static String deviceId = genDeviceId();
|
||||
static String buvid = genBuvid();
|
||||
static String deviceId = LoginUtils.genDeviceId();
|
||||
static String buvid = LoginUtils.buvid();
|
||||
static String host = 'passport.bilibili.com';
|
||||
static String traceId =
|
||||
'11111111111111111111111111111111:1111111111111111:0:0';
|
||||
static String statistics = Uri.encodeComponent(
|
||||
'{"appId": 5,"platform": 3,"version": "1.46.2","abtest": ""}');
|
||||
static String userAgent =
|
||||
'Mozilla/5.0 BiliDroid/1.46.2 (bbcallen@gmail.com) os/android model/vivo mobi_app/android_hd build/1462100 channel/yingyongbao innerVer/1462100 osVer/14 network/2';
|
||||
static Map<String, String> headers = {
|
||||
'Host': host,
|
||||
'buvid': buvid,
|
||||
'env': 'prod',
|
||||
'app-key': 'android_hd',
|
||||
'user-agent': Constants.userAgent,
|
||||
'x-bili-trace-id': Constants.traceId,
|
||||
'x-bili-aurora-eid': '',
|
||||
'x-bili-aurora-zone': '',
|
||||
'bili-http-engine': 'cronet',
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
};
|
||||
|
||||
static Future<Map<String, dynamic>> getHDcode() async {
|
||||
var params = {
|
||||
'appkey': Constants.appKey,
|
||||
@@ -117,7 +125,7 @@ class LoginHttp {
|
||||
'platform': 'android',
|
||||
if (recaptcha_token != null) 'recaptcha_token': recaptcha_token,
|
||||
's_locale': 'zh_CN',
|
||||
'statistics': statistics,
|
||||
'statistics': Constants.statistics,
|
||||
'tel': tel,
|
||||
'ts': (timestamp ~/ 1000).toString(),
|
||||
};
|
||||
@@ -126,18 +134,6 @@ class LoginHttp {
|
||||
Constants.appKey,
|
||||
Constants.appSec,
|
||||
);
|
||||
var headers = {
|
||||
'Host': host,
|
||||
'buvid': buvid,
|
||||
'env': 'prod',
|
||||
'app-key': 'android_hd',
|
||||
'user-agent': userAgent,
|
||||
'x-bili-trace-id': traceId,
|
||||
'x-bili-aurora-eid': '',
|
||||
'x-bili-aurora-zone': '',
|
||||
'bili-http-engine': 'cronet',
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
};
|
||||
|
||||
var res = await Request().post(
|
||||
Api.appSmsCode,
|
||||
@@ -177,7 +173,7 @@ class LoginHttp {
|
||||
// 'mobi_app': 'android_hd',
|
||||
// 'platform': 'android',
|
||||
// 's_locale': 'zh_CN',
|
||||
// 'statistics': statistics,
|
||||
// 'statistics': Constants.statistics,
|
||||
// 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||
// };
|
||||
// String sign = Utils.appSign(
|
||||
@@ -185,18 +181,6 @@ class LoginHttp {
|
||||
// Constants.appKey,
|
||||
// Constants.appSec,
|
||||
// );
|
||||
// var headers = {
|
||||
// 'Host': host,
|
||||
// 'buvid': buvid,
|
||||
// 'env': 'prod',
|
||||
// 'app-key': 'android_hd',
|
||||
// 'user-agent': userAgent,
|
||||
// 'x-bili-trace-id': traceId,
|
||||
// 'x-bili-aurora-eid': '',
|
||||
// 'x-bili-aurora-zone': '',
|
||||
// 'bili-http-engine': 'cronet',
|
||||
// 'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
// };
|
||||
// var res = await Request().post(Api.getGuestId,
|
||||
// queryParameters: {...params, 'sign': sign},
|
||||
// options: Options(
|
||||
@@ -211,59 +195,6 @@ class LoginHttp {
|
||||
// }
|
||||
// }
|
||||
|
||||
static String genBuvid() {
|
||||
var mac = <String>[];
|
||||
var random = Random();
|
||||
|
||||
for (var i = 0; i < 6; i++) {
|
||||
var min = 0;
|
||||
var max = 0xff;
|
||||
var num = (random.nextInt(max - min + 1) + min).toRadixString(16);
|
||||
mac.add(num);
|
||||
}
|
||||
|
||||
var md5Str = md5.convert(utf8.encode(mac.join(':'))).toString();
|
||||
var md5Arr = md5Str.split('');
|
||||
return 'XY${md5Arr[2]}${md5Arr[12]}${md5Arr[22]}$md5Str';
|
||||
}
|
||||
|
||||
static String genDeviceId() {
|
||||
// https://github.com/bilive/bilive_client/blob/2873de0532c54832f5464a4c57325ad9af8b8698/bilive/lib/app_client.ts#L62
|
||||
final String yyyyMMddHHmmss = DateTime.now()
|
||||
.toIso8601String()
|
||||
.replaceAll(RegExp(r'[-:TZ]'), '')
|
||||
.substring(0, 14);
|
||||
|
||||
final Random random = Random(); // Random.secure();
|
||||
final String randomHex32 =
|
||||
List.generate(32, (index) => random.nextInt(16).toRadixString(16))
|
||||
.join();
|
||||
final String randomHex16 =
|
||||
List.generate(16, (index) => random.nextInt(16).toRadixString(16))
|
||||
.join();
|
||||
|
||||
final String deviceID = randomHex32 + yyyyMMddHHmmss + randomHex16;
|
||||
|
||||
final List<int> bytes = RegExp(r'\w{2}')
|
||||
.allMatches(deviceID)
|
||||
.map((match) => int.parse(match.group(0)!, radix: 16))
|
||||
.toList();
|
||||
final int checksumValue = bytes.reduce((a, b) => a + b);
|
||||
final String check = checksumValue
|
||||
.toRadixString(16)
|
||||
.substring(checksumValue.toRadixString(16).length - 2);
|
||||
|
||||
return deviceID + check;
|
||||
}
|
||||
|
||||
static String generateRandomString(int length) {
|
||||
const chars =
|
||||
'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
final Random random = Random(); // Random.secure();
|
||||
return List.generate(length, (index) => chars[random.nextInt(chars.length)])
|
||||
.join();
|
||||
}
|
||||
|
||||
// app端密码登录
|
||||
static Future loginByPwd({
|
||||
required String username,
|
||||
@@ -294,7 +225,7 @@ class LoginHttp {
|
||||
'device_platform': 'Android14vivo',
|
||||
'disable_rcmd': '0',
|
||||
'dt': Uri.encodeComponent(Encrypter(RSA(publicKey: publicKey))
|
||||
.encrypt(generateRandomString(16))
|
||||
.encrypt(LoginUtils.generateRandomString(16))
|
||||
.base64),
|
||||
'from_pv': 'main.homepage.avatar-nologin.all.click',
|
||||
'from_url': Uri.encodeComponent('bilibili://pegasus/promo'),
|
||||
@@ -308,7 +239,7 @@ class LoginHttp {
|
||||
'platform': 'android',
|
||||
if (recaptcha_token != null) 'recaptcha_token': recaptcha_token,
|
||||
's_locale': 'zh_CN',
|
||||
'statistics': statistics,
|
||||
'statistics': Constants.statistics,
|
||||
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||
'username': username,
|
||||
};
|
||||
@@ -322,18 +253,6 @@ class LoginHttp {
|
||||
print('$key: $value');
|
||||
return MapEntry<String, dynamic>(key, value);
|
||||
});
|
||||
final Map<String, String> headers = {
|
||||
'Host': host,
|
||||
'buvid': buvid,
|
||||
'env': 'prod',
|
||||
'app-key': 'android_hd',
|
||||
'user-agent': userAgent,
|
||||
'x-bili-trace-id': traceId,
|
||||
'x-bili-aurora-eid': '',
|
||||
'x-bili-aurora-zone': '',
|
||||
'bili-http-engine': 'cronet',
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
};
|
||||
var res = await Request().post(
|
||||
Api.loginByPwdApi,
|
||||
data: data,
|
||||
@@ -345,7 +264,11 @@ class LoginHttp {
|
||||
);
|
||||
print(res);
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true, 'data': res.data['data']};
|
||||
return {
|
||||
'status': true,
|
||||
'data': res.data['data'],
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
@@ -383,7 +306,7 @@ class LoginHttp {
|
||||
// 'device_tourist_id': '',
|
||||
'disable_rcmd': '0',
|
||||
'dt': Uri.encodeComponent(Encrypter(RSA(publicKey: publicKey))
|
||||
.encrypt(generateRandomString(16))
|
||||
.encrypt(LoginUtils.generateRandomString(16))
|
||||
.base64),
|
||||
'from_pv': 'main.my-information.my-login.0.click',
|
||||
'from_url': Uri.encodeComponent('bilibili://user_center/mine'),
|
||||
@@ -391,7 +314,7 @@ class LoginHttp {
|
||||
'mobi_app': 'android_hd',
|
||||
'platform': 'android',
|
||||
's_locale': 'zh_CN',
|
||||
'statistics': statistics,
|
||||
'statistics': Constants.statistics,
|
||||
'tel': tel,
|
||||
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||
};
|
||||
@@ -405,18 +328,6 @@ class LoginHttp {
|
||||
print('$key: $value');
|
||||
return MapEntry<String, dynamic>(key, value);
|
||||
});
|
||||
final Map<String, String> headers = {
|
||||
'Host': host,
|
||||
'buvid': buvid,
|
||||
'env': 'prod',
|
||||
'app-key': 'android_hd',
|
||||
'user-agent': userAgent,
|
||||
'x-bili-trace-id': traceId,
|
||||
'x-bili-aurora-eid': '',
|
||||
'x-bili-aurora-zone': '',
|
||||
'bili-http-engine': 'cronet',
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
};
|
||||
var res = await Request().post(
|
||||
Api.logInByAppSms,
|
||||
data: data,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import 'dart:developer';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import '../common/constants.dart';
|
||||
@@ -13,10 +15,12 @@ import '../models/video_detail_res.dart';
|
||||
import '../utils/id_utils.dart';
|
||||
import '../utils/recommend_filter.dart';
|
||||
import '../utils/storage.dart';
|
||||
import '../utils/utils.dart';
|
||||
import '../utils/wbi_sign.dart';
|
||||
import '../pages/mine/controller.dart';
|
||||
import 'api.dart';
|
||||
import 'init.dart';
|
||||
import 'login.dart';
|
||||
|
||||
/// res.data['code'] == 0 请求正常返回结果
|
||||
/// res.data['data'] 为结果
|
||||
@@ -31,91 +35,130 @@ class VideoHttp {
|
||||
|
||||
// 首页推荐视频
|
||||
static Future rcmdVideoList({required int ps, required int freshIdx}) async {
|
||||
try {
|
||||
var res = await Request().get(
|
||||
Api.recommendListWeb,
|
||||
data: {
|
||||
'version': 1,
|
||||
'feed_version': 'V8',
|
||||
'homepage_ver': 1,
|
||||
'ps': ps,
|
||||
'fresh_idx': freshIdx,
|
||||
'brush': freshIdx,
|
||||
'fresh_type': 4
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
List<RecVideoItemModel> list = [];
|
||||
List<int> blackMidsList = localCache
|
||||
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
||||
.map<int>((e) => e as int)
|
||||
.toList();
|
||||
for (var i in res.data['data']['item']) {
|
||||
//过滤掉live与ad,以及拉黑用户
|
||||
if (i['goto'] == 'av' &&
|
||||
(i['owner'] != null &&
|
||||
!blackMidsList.contains(i['owner']['mid']))) {
|
||||
RecVideoItemModel videoItem = RecVideoItemModel.fromJson(i);
|
||||
if (!RecommendFilter.filter(videoItem)) {
|
||||
list.add(videoItem);
|
||||
}
|
||||
var res = await Request().get(
|
||||
Api.recommendListWeb,
|
||||
data: {
|
||||
'version': 1,
|
||||
'feed_version': 'V8',
|
||||
'homepage_ver': 1,
|
||||
'ps': ps,
|
||||
'fresh_idx': freshIdx,
|
||||
'brush': freshIdx,
|
||||
'fresh_type': 4
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
List<RecVideoItemModel> list = [];
|
||||
List<int> blackMidsList = localCache
|
||||
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
||||
.map<int>((e) => e as int)
|
||||
.toList();
|
||||
for (var i in res.data['data']['item']) {
|
||||
//过滤掉live与ad,以及拉黑用户
|
||||
if (i['goto'] == 'av' &&
|
||||
(i['owner'] != null &&
|
||||
!blackMidsList.contains(i['owner']['mid']))) {
|
||||
RecVideoItemModel videoItem = RecVideoItemModel.fromJson(i);
|
||||
if (!RecommendFilter.filter(videoItem)) {
|
||||
list.add(videoItem);
|
||||
}
|
||||
}
|
||||
return {'status': true, 'data': list};
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
}
|
||||
} catch (err) {
|
||||
return {'status': false, 'data': [], 'msg': err.toString()};
|
||||
return {'status': true, 'data': list};
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
|
||||
// 添加额外的loginState变量模拟未登录状态
|
||||
static Future rcmdVideoListApp(
|
||||
{bool loginStatus = true, required int freshIdx}) async {
|
||||
try {
|
||||
var res = await Request().get(
|
||||
Api.recommendListApp,
|
||||
data: {
|
||||
'idx': freshIdx,
|
||||
'flush': '5',
|
||||
'column': '4',
|
||||
'device': 'pad',
|
||||
'device_type': 0,
|
||||
'device_name': 'vivo',
|
||||
'pull': freshIdx == 0 ? 'true' : 'false',
|
||||
'appkey': Constants.appKey,
|
||||
'access_key': loginStatus
|
||||
? (localCache.get(LocalCacheKey.accessKey,
|
||||
defaultValue: {})['value'] ??
|
||||
'')
|
||||
: ''
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
List<RecVideoItemAppModel> list = [];
|
||||
List<int> blackMidsList = localCache
|
||||
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
||||
.map<int>((e) => e as int)
|
||||
.toList();
|
||||
for (var i in res.data['data']['items']) {
|
||||
// 屏蔽推广和拉黑用户
|
||||
if (i['card_goto'] != 'ad_av' &&
|
||||
(!enableRcmdDynamic ? i['card_goto'] != 'picture' : true) &&
|
||||
(i['args'] != null &&
|
||||
!blackMidsList.contains(i['args']['up_mid']))) {
|
||||
RecVideoItemAppModel videoItem = RecVideoItemAppModel.fromJson(i);
|
||||
if (!RecommendFilter.filter(videoItem)) {
|
||||
list.add(videoItem);
|
||||
}
|
||||
var data = {
|
||||
'access_key': loginStatus
|
||||
? (localCache
|
||||
.get(LocalCacheKey.accessKey, defaultValue: {})['value'] ??
|
||||
'')
|
||||
: '',
|
||||
'appkey': Constants.appKey,
|
||||
'build': '1462100',
|
||||
'c_locale': 'zh_CN',
|
||||
'channel': 'yingyongbao',
|
||||
'column': '4',
|
||||
'device': 'pad',
|
||||
'device_name': 'vivo',
|
||||
'device_type': '0',
|
||||
'disable_rcmd': '0',
|
||||
'flush': '5',
|
||||
'fnval': '976',
|
||||
'fnver': '0',
|
||||
'force_host': '2', //使用https
|
||||
'fourk': '1',
|
||||
'guidance': '0',
|
||||
'https_url_req': '0',
|
||||
'idx': freshIdx.toString(),
|
||||
'mobi_app': 'android_hd',
|
||||
'network': 'wifi',
|
||||
'platform': 'android',
|
||||
'player_net': '1',
|
||||
'pull': freshIdx == 0 ? 'true' : 'false',
|
||||
'qn': '32',
|
||||
'recsys_mode': '0',
|
||||
's_locale': 'zh_CN',
|
||||
'splash_id': '',
|
||||
'statistics': Constants.statistics,
|
||||
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||
'voice_balance': '0'
|
||||
};
|
||||
String sign = Utils.appSign(
|
||||
data,
|
||||
Constants.appKey,
|
||||
Constants.appSec,
|
||||
);
|
||||
data['sign'] = sign;
|
||||
|
||||
var res = await Request().get(
|
||||
Api.recommendListApp,
|
||||
data: data,
|
||||
options: Options(headers: {
|
||||
'Host': 'app.bilibili.com',
|
||||
'buvid': LoginHttp.buvid,
|
||||
'fp_local':
|
||||
'1111111111111111111111111111111111111111111111111111111111111111',
|
||||
'fp_remote':
|
||||
'1111111111111111111111111111111111111111111111111111111111111111',
|
||||
'session_id': '11111111',
|
||||
'env': 'prod',
|
||||
'app-key': 'android_hd',
|
||||
'User-Agent': Constants.userAgent,
|
||||
'x-bili-trace-id': Constants.traceId,
|
||||
'x-bili-aurora-eid': '',
|
||||
'x-bili-aurora-zone': '',
|
||||
'bili-http-engine': 'cronet',
|
||||
}),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
List<RecVideoItemAppModel> list = [];
|
||||
List<int> blackMidsList = localCache
|
||||
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
||||
.map<int>((e) => e as int)
|
||||
.toList();
|
||||
for (var i in res.data['data']['items']) {
|
||||
// 屏蔽推广和拉黑用户
|
||||
if (i['card_goto'] != 'ad_av' &&
|
||||
i['card_goto'] != 'ad_web_s' &&
|
||||
i['ad_info'] == null &&
|
||||
(!enableRcmdDynamic ? i['card_goto'] != 'picture' : true) &&
|
||||
(i['args'] != null &&
|
||||
!blackMidsList.contains(i['args']['up_id']))) {
|
||||
RecVideoItemAppModel videoItem = RecVideoItemAppModel.fromJson(i);
|
||||
if (!RecommendFilter.filter(videoItem)) {
|
||||
list.add(videoItem);
|
||||
}
|
||||
}
|
||||
return {'status': true, 'data': list};
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
}
|
||||
} catch (err) {
|
||||
return {'status': false, 'data': [], 'msg': err.toString()};
|
||||
return {'status': true, 'data': list};
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user