mod: format code
This commit is contained in:
@ -2,15 +2,14 @@ import 'package:appscheme/appscheme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/search.dart';
|
||||
import 'package:pilipala/models/common/search_type.dart';
|
||||
|
||||
import '../http/search.dart';
|
||||
import '../models/common/search_type.dart';
|
||||
import 'id_utils.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
class PiliSchame {
|
||||
static AppScheme appScheme = AppSchemeImpl.getInstance() as AppScheme;
|
||||
static void init() async {
|
||||
static AppScheme appScheme = AppSchemeImpl.getInstance()!;
|
||||
static Future<void> init() async {
|
||||
///
|
||||
final SchemeEntity? value = await appScheme.getInitScheme();
|
||||
if (value != null) {
|
||||
@ -18,14 +17,14 @@ class PiliSchame {
|
||||
}
|
||||
|
||||
/// 完整链接进入 b23.无效
|
||||
appScheme.getLatestScheme().then((value) {
|
||||
appScheme.getLatestScheme().then((SchemeEntity? value) {
|
||||
if (value != null) {
|
||||
_fullPathPush(value);
|
||||
}
|
||||
});
|
||||
|
||||
/// 注册从外部打开的Scheme监听信息 #
|
||||
appScheme.registerSchemeListener().listen((event) {
|
||||
appScheme.registerSchemeListener().listen((SchemeEntity? event) {
|
||||
if (event != null) {
|
||||
_routePush(event);
|
||||
}
|
||||
@ -41,15 +40,16 @@ class PiliSchame {
|
||||
if (scheme == 'bilibili') {
|
||||
// bilibili://root
|
||||
if (host == 'root') {
|
||||
Navigator.popUntil(Get.context!, (route) => route.isFirst);
|
||||
Navigator.popUntil(
|
||||
Get.context!, (Route<dynamic> route) => route.isFirst);
|
||||
}
|
||||
|
||||
// bilibili://space/{uid}
|
||||
else if (host == 'space') {
|
||||
var mid = path.split('/').last;
|
||||
Get.toNamed(
|
||||
final String mid = path.split('/').last;
|
||||
Get.toNamed<dynamic>(
|
||||
'/member?mid=$mid',
|
||||
arguments: {'face': null},
|
||||
arguments: <String, dynamic>{'face': null},
|
||||
);
|
||||
}
|
||||
|
||||
@ -72,15 +72,15 @@ class PiliSchame {
|
||||
|
||||
// bilibili://live/{roomid}
|
||||
else if (host == 'live') {
|
||||
var roomId = path.split('/').last;
|
||||
Get.toNamed('/liveRoom?roomid=$roomId',
|
||||
arguments: {'liveItem': null, 'heroTag': roomId.toString()});
|
||||
final String roomId = path.split('/').last;
|
||||
Get.toNamed<dynamic>('/liveRoom?roomid=$roomId',
|
||||
arguments: <String, String?>{'liveItem': null, 'heroTag': roomId});
|
||||
}
|
||||
|
||||
// bilibili://bangumi/season/${ssid}
|
||||
else if (host == 'bangumi') {
|
||||
if (path.startsWith('/season')) {
|
||||
var seasonId = path.split('/').last;
|
||||
final String seasonId = path.split('/').last;
|
||||
_bangumiPush(int.parse(seasonId));
|
||||
}
|
||||
}
|
||||
@ -104,8 +104,8 @@ class PiliSchame {
|
||||
}
|
||||
|
||||
// 投稿跳转
|
||||
static void _videoPush(int? aidVal, String? bvidVal) async {
|
||||
SmartDialog.showLoading(msg: '获取中...');
|
||||
static Future<void> _videoPush(int? aidVal, String? bvidVal) async {
|
||||
SmartDialog.showLoading<dynamic>(msg: '获取中...');
|
||||
try {
|
||||
int? aid = aidVal;
|
||||
String? bvid = bvidVal;
|
||||
@ -115,22 +115,24 @@ class PiliSchame {
|
||||
if (bvidVal == null) {
|
||||
bvid = IdUtils.av2bv(aidVal!);
|
||||
}
|
||||
int cid = await SearchHttp.ab2c(bvid: bvidVal, aid: aidVal);
|
||||
String heroTag = Utils.makeHeroTag(aid);
|
||||
SmartDialog.dismiss().then(
|
||||
(e) => Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: {
|
||||
'pic': null,
|
||||
'heroTag': heroTag,
|
||||
}),
|
||||
final int cid = await SearchHttp.ab2c(bvid: bvidVal, aid: aidVal);
|
||||
final String heroTag = Utils.makeHeroTag(aid);
|
||||
SmartDialog.dismiss<dynamic>().then(
|
||||
// ignore: always_specify_types
|
||||
(e) => Get.toNamed<dynamic>('/video?bvid=$bvid&cid=$cid',
|
||||
arguments: <String, String?>{
|
||||
'pic': null,
|
||||
'heroTag': heroTag,
|
||||
}),
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('video获取失败:${e.toString()}');
|
||||
SmartDialog.showToast('video获取失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 番剧跳转
|
||||
static void _bangumiPush(int seasonId) async {
|
||||
SmartDialog.showLoading(msg: '获取中...');
|
||||
static Future<void> _bangumiPush(int seasonId) async {
|
||||
SmartDialog.showLoading<dynamic>(msg: '获取中...');
|
||||
try {
|
||||
var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: null);
|
||||
if (result['status']) {
|
||||
@ -142,7 +144,7 @@ class PiliSchame {
|
||||
SmartDialog.dismiss().then(
|
||||
(e) => Get.toNamed(
|
||||
'/video?bvid=$bvid&cid=$cid&epId=$epId',
|
||||
arguments: {
|
||||
arguments: <String, dynamic>{
|
||||
'pic': bangumiDetail.cover,
|
||||
'heroTag': heroTag,
|
||||
'videoType': SearchType.media_bangumi,
|
||||
@ -151,14 +153,14 @@ class PiliSchame {
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('番剧获取失败:${e.toString()}');
|
||||
SmartDialog.showToast('番剧获取失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
static void _fullPathPush(value) async {
|
||||
static Future<void> _fullPathPush(SchemeEntity value) async {
|
||||
// https://m.bilibili.com/bangumi/play/ss39708
|
||||
// https | m.bilibili.com | /bangumi/play/ss39708
|
||||
final String scheme = value.scheme!;
|
||||
// final String scheme = value.scheme!;
|
||||
final String host = value.host!;
|
||||
final String? path = value.path;
|
||||
// Map<String, String> query = value.query!;
|
||||
@ -173,6 +175,7 @@ class PiliSchame {
|
||||
print('个人空间');
|
||||
return;
|
||||
}
|
||||
|
||||
if (path != null) {
|
||||
final String area = path.split('/')[1];
|
||||
switch (area) {
|
||||
@ -183,11 +186,11 @@ class PiliSchame {
|
||||
break;
|
||||
case 'video':
|
||||
// print('投稿');
|
||||
Map map = IdUtils.matchAvorBv(input: path);
|
||||
final Map<String, dynamic> map = IdUtils.matchAvorBv(input: path);
|
||||
if (map.containsKey('AV')) {
|
||||
_videoPush(map['AV'], null);
|
||||
_videoPush(map['AV']! as int, null);
|
||||
} else if (map.containsKey('BV')) {
|
||||
_videoPush(null, map['BV']);
|
||||
_videoPush(null, map['BV'] as String);
|
||||
} else {
|
||||
SmartDialog.showToast('投稿匹配失败');
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
import 'storage.dart';
|
||||
|
||||
Box setting = GStrorage.setting;
|
||||
Box<dynamic> setting = GStrorage.setting;
|
||||
void feedBack() {
|
||||
// 设置中是否开启
|
||||
bool enable = setting.get(SettingBoxKey.feedBackEnable, defaultValue: false);
|
||||
final bool enable =
|
||||
setting.get(SettingBoxKey.feedBackEnable, defaultValue: false) as bool;
|
||||
if (enable) {
|
||||
HapticFeedback.lightImpact();
|
||||
}
|
||||
|
||||
@ -48,19 +48,21 @@ class IdUtils {
|
||||
}
|
||||
|
||||
// 匹配
|
||||
static Map matchAvorBv({String? input}) {
|
||||
Map result = {};
|
||||
static Map<String, dynamic> matchAvorBv({String? input}) {
|
||||
final Map<String, dynamic> result = {'': null};
|
||||
if (input == null || input == '') {
|
||||
return result;
|
||||
}
|
||||
RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false);
|
||||
RegExp avRegex = RegExp(r'AV\d+', caseSensitive: false);
|
||||
final RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false);
|
||||
final RegExp avRegex = RegExp(r'AV\d+', caseSensitive: false);
|
||||
|
||||
Iterable<Match> bvMatches = bvRegex.allMatches(input);
|
||||
Iterable<Match> avMatches = avRegex.allMatches(input);
|
||||
final Iterable<Match> bvMatches = bvRegex.allMatches(input);
|
||||
final Iterable<Match> avMatches = avRegex.allMatches(input);
|
||||
|
||||
List<String> bvs = bvMatches.map((match) => match.group(0)!).toList();
|
||||
List<String> avs = avMatches.map((match) => match.group(0)!).toList();
|
||||
final List<String> bvs =
|
||||
bvMatches.map((Match match) => match.group(0)!).toList();
|
||||
final List<String> avs =
|
||||
avMatches.map((Match match) => match.group(0)!).toList();
|
||||
|
||||
if (bvs.isNotEmpty) {
|
||||
result['BV'] = bvs[0].substring(0, 2).toUpperCase() + bvs[0].substring(2);
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
// import 'package:hive/hive.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:pilipala/models/home/rcmd/result.dart';
|
||||
@ -7,36 +9,36 @@ import 'package:pilipala/models/search/hot.dart';
|
||||
import 'package:pilipala/models/user/info.dart';
|
||||
|
||||
class GStrorage {
|
||||
static late final Box recVideo;
|
||||
static late final Box userInfo;
|
||||
static late final Box historyword;
|
||||
static late final Box localCache;
|
||||
static late final Box setting;
|
||||
static late final Box video;
|
||||
static late final Box<dynamic> recVideo;
|
||||
static late final Box<dynamic> userInfo;
|
||||
static late final Box<dynamic> historyword;
|
||||
static late final Box<dynamic> localCache;
|
||||
static late final Box<dynamic> setting;
|
||||
static late final Box<dynamic> video;
|
||||
|
||||
static Future<void> init() async {
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
final path = dir.path;
|
||||
final Directory dir = await getApplicationSupportDirectory();
|
||||
final String path = dir.path;
|
||||
await Hive.initFlutter('$path/hive');
|
||||
regAdapter();
|
||||
// 首页推荐视频
|
||||
recVideo = await Hive.openBox(
|
||||
'recVideo',
|
||||
compactionStrategy: (entries, deletedEntries) {
|
||||
compactionStrategy: (int entries, int deletedEntries) {
|
||||
return deletedEntries > 12;
|
||||
},
|
||||
);
|
||||
// 登录用户信息
|
||||
userInfo = await Hive.openBox(
|
||||
'userInfo',
|
||||
compactionStrategy: (entries, deletedEntries) {
|
||||
compactionStrategy: (int entries, int deletedEntries) {
|
||||
return deletedEntries > 2;
|
||||
},
|
||||
);
|
||||
// 本地缓存
|
||||
localCache = await Hive.openBox(
|
||||
'localCache',
|
||||
compactionStrategy: (entries, deletedEntries) {
|
||||
compactionStrategy: (int entries, int deletedEntries) {
|
||||
return deletedEntries > 4;
|
||||
},
|
||||
);
|
||||
@ -45,13 +47,13 @@ class GStrorage {
|
||||
// 搜索历史
|
||||
historyword = await Hive.openBox(
|
||||
'historyWord',
|
||||
compactionStrategy: (entries, deletedEntries) {
|
||||
compactionStrategy: (int entries, int deletedEntries) {
|
||||
return deletedEntries > 10;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static regAdapter() {
|
||||
static void regAdapter() {
|
||||
Hive.registerAdapter(RecVideoItemAppModelAdapter());
|
||||
Hive.registerAdapter(RcmdReasonAdapter());
|
||||
Hive.registerAdapter(RcmdStatAdapter());
|
||||
@ -88,7 +90,7 @@ class GStrorage {
|
||||
|
||||
class SettingBoxKey {
|
||||
/// 播放器
|
||||
static const btmProgressBehavior = 'btmProgressBehavior',
|
||||
static const String btmProgressBehavior = 'btmProgressBehavior',
|
||||
defaultVideoSpeed = 'defaultVideoSpeed',
|
||||
autoUpgradeEnable = 'autoUpgradeEnable',
|
||||
feedBackEnable = 'feedBackEnable',
|
||||
|
||||
@ -12,16 +12,16 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get_utils/get_utils.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:pilipala/http/index.dart';
|
||||
import 'package:pilipala/models/github/latest.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import '../http/index.dart';
|
||||
import '../models/github/latest.dart';
|
||||
|
||||
class Utils {
|
||||
static Future<String> getCookiePath() async {
|
||||
Directory tempDir = await getApplicationSupportDirectory();
|
||||
String tempPath = "${tempDir.path}/.plpl/";
|
||||
Directory dir = Directory(tempPath);
|
||||
bool b = await dir.exists();
|
||||
final Directory tempDir = await getApplicationSupportDirectory();
|
||||
final String tempPath = "${tempDir.path}/.plpl/";
|
||||
final Directory dir = Directory(tempPath);
|
||||
final bool b = await dir.exists();
|
||||
if (!b) {
|
||||
dir.createSync(recursive: true);
|
||||
}
|
||||
@ -29,7 +29,7 @@ class Utils {
|
||||
}
|
||||
|
||||
static String numFormat(int number) {
|
||||
String res = (number / 10000).toString();
|
||||
final String res = (number / 10000).toString();
|
||||
if (int.parse(res.split('.')[0]) >= 1) {
|
||||
return '${(number / 10000).toPrecision(1)}万';
|
||||
} else {
|
||||
@ -43,16 +43,16 @@ class Utils {
|
||||
return time;
|
||||
}
|
||||
if (time < 3600) {
|
||||
int minute = time ~/ 60;
|
||||
double res = time / 60;
|
||||
final int minute = time ~/ 60;
|
||||
final double res = time / 60;
|
||||
if (minute != res) {
|
||||
return '${minute < 10 ? '0$minute' : minute}:${(time - minute * 60) < 10 ? '0${(time - minute * 60)}' : (time - minute * 60)}';
|
||||
} else {
|
||||
return '$minute:00';
|
||||
}
|
||||
} else {
|
||||
int hour = time ~/ 3600;
|
||||
String hourStr = hour < 10 ? '0$hour' : hour.toString();
|
||||
final int hour = time ~/ 3600;
|
||||
final String hourStr = hour < 10 ? '0$hour' : hour.toString();
|
||||
var a = timeFormat(time - hour * 3600);
|
||||
return '$hourStr:$a';
|
||||
}
|
||||
|
||||
@ -2,16 +2,15 @@
|
||||
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md
|
||||
// import md5 from 'md5'
|
||||
// import axios from 'axios'
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/http/index.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import '../http/index.dart';
|
||||
import 'storage.dart';
|
||||
|
||||
class WbiSign {
|
||||
static Box localCache = GStrorage.localCache;
|
||||
List mixinKeyEncTab = [
|
||||
static Box<dynamic> localCache = GStrorage.localCache;
|
||||
final List<int> mixinKeyEncTab = <int>[
|
||||
46,
|
||||
47,
|
||||
18,
|
||||
@ -78,52 +77,54 @@ class WbiSign {
|
||||
52
|
||||
];
|
||||
// 对 imgKey 和 subKey 进行字符顺序打乱编码
|
||||
String getMixinKey(orig) {
|
||||
String getMixinKey(String orig) {
|
||||
String temp = '';
|
||||
for (int i = 0; i < mixinKeyEncTab.length; i++) {
|
||||
temp += orig.split('')[mixinKeyEncTab[i]];
|
||||
temp += orig.split('')[mixinKeyEncTab[i] as int];
|
||||
}
|
||||
return temp.substring(0, 32);
|
||||
}
|
||||
|
||||
// 为请求参数进行 wbi 签名
|
||||
Map<String, dynamic> encWbi(params, imgKey, subKey) {
|
||||
String mixinKey = getMixinKey(imgKey + subKey);
|
||||
DateTime now = DateTime.now();
|
||||
int currTime = (now.millisecondsSinceEpoch / 1000).round();
|
||||
RegExp chrFilter = RegExp(r"[!\'\(\)*]");
|
||||
List query = [];
|
||||
Map newParams = Map.from(params)..addAll({"wts": currTime}); // 添加 wts 字段
|
||||
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 字段
|
||||
// 按照 key 重排参数
|
||||
List keys = newParams.keys.toList()..sort();
|
||||
for (var i in keys) {
|
||||
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, ''))}');
|
||||
}
|
||||
String queryStr = query.join('&');
|
||||
String wbiSign =
|
||||
final String queryStr = query.join('&');
|
||||
final String wbiSign =
|
||||
md5.convert(utf8.encode(queryStr + mixinKey)).toString(); // 计算 w_rid
|
||||
return {'wts': currTime.toString(), 'w_rid': wbiSign};
|
||||
}
|
||||
|
||||
// 获取最新的 img_key 和 sub_key 可以从缓存中获取
|
||||
static Future<Map<String, dynamic>> getWbiKeys() async {
|
||||
DateTime nowDate = DateTime.now();
|
||||
final DateTime nowDate = DateTime.now();
|
||||
if (localCache.get(LocalCacheKey.wbiKeys) != null &&
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
localCache.get(LocalCacheKey.timeStamp))
|
||||
localCache.get(LocalCacheKey.timeStamp) as int)
|
||||
.day ==
|
||||
nowDate.day) {
|
||||
Map cacheWbiKeys = localCache.get('wbiKeys');
|
||||
final Map cacheWbiKeys = localCache.get('wbiKeys');
|
||||
return Map<String, dynamic>.from(cacheWbiKeys);
|
||||
}
|
||||
var resp =
|
||||
await Request().get('https://api.bilibili.com/x/web-interface/nav');
|
||||
var jsonContent = resp.data['data'];
|
||||
|
||||
String imgUrl = jsonContent['wbi_img']['img_url'];
|
||||
String subUrl = jsonContent['wbi_img']['sub_url'];
|
||||
Map<String, dynamic> wbiKeys = {
|
||||
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],
|
||||
@ -136,10 +137,10 @@ class WbiSign {
|
||||
return wbiKeys;
|
||||
}
|
||||
|
||||
makSign(Map<String, dynamic> params) async {
|
||||
Future<Map<String, dynamic>> makSign(Map<String, dynamic> params) async {
|
||||
// params 为需要加密的请求参数
|
||||
Map<String, dynamic> wbiKeys = await getWbiKeys();
|
||||
Map<String, dynamic> query = params
|
||||
final Map<String, dynamic> wbiKeys = await getWbiKeys();
|
||||
final Map<String, dynamic> query = params
|
||||
..addAll(encWbi(params, wbiKeys['imgKey'], wbiKeys['subKey']));
|
||||
return query;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user