mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -499,4 +499,10 @@ class Api {
|
|||||||
|
|
||||||
/// 获取未读动态数
|
/// 获取未读动态数
|
||||||
static const getUnreadDynamic = '/x/web-interface/dynamic/entrance';
|
static const getUnreadDynamic = '/x/web-interface/dynamic/entrance';
|
||||||
|
|
||||||
|
/// 用户动态主页
|
||||||
|
static const dynamicSpmPrefix = 'https://space.bilibili.com/1/dynamic';
|
||||||
|
|
||||||
|
/// 激活buvid3
|
||||||
|
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
// ignore_for_file: avoid_print
|
// ignore_for_file: avoid_print
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math' show Random;
|
||||||
import 'package:cookie_jar/cookie_jar.dart';
|
import 'package:cookie_jar/cookie_jar.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio/io.dart';
|
import 'package:dio/io.dart';
|
||||||
@@ -11,6 +13,7 @@ import 'package:hive/hive.dart';
|
|||||||
import 'package:PiliPalaX/utils/id_utils.dart';
|
import 'package:PiliPalaX/utils/id_utils.dart';
|
||||||
import '../utils/storage.dart';
|
import '../utils/storage.dart';
|
||||||
import '../utils/utils.dart';
|
import '../utils/utils.dart';
|
||||||
|
import 'api.dart';
|
||||||
import 'constants.dart';
|
import 'constants.dart';
|
||||||
import 'interceptor.dart';
|
import 'interceptor.dart';
|
||||||
import 'interceptor_anonymity.dart';
|
import 'interceptor_anonymity.dart';
|
||||||
@@ -25,6 +28,7 @@ class Request {
|
|||||||
late bool enableSystemProxy;
|
late bool enableSystemProxy;
|
||||||
late String systemProxyHost;
|
late String systemProxyHost;
|
||||||
late String systemProxyPort;
|
late String systemProxyPort;
|
||||||
|
static final RegExp spmPrefixExp = RegExp(r'<meta name="spm_prefix" content="([^"]+?)">');
|
||||||
|
|
||||||
/// 设置cookie
|
/// 设置cookie
|
||||||
static setCookie() async {
|
static setCookie() async {
|
||||||
@@ -53,13 +57,12 @@ class Request {
|
|||||||
}
|
}
|
||||||
setOptionsHeaders(userInfo, userInfo != null && userInfo.mid != null);
|
setOptionsHeaders(userInfo, userInfo != null && userInfo.mid != null);
|
||||||
|
|
||||||
if (cookie.isEmpty) {
|
try {
|
||||||
try {
|
await buvidActivate();
|
||||||
await Request().get(HttpString.baseUrl);
|
} catch (e) {
|
||||||
} catch (e) {
|
log("setCookie, ${e.toString()}");
|
||||||
log("setCookie, ${e.toString()}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String cookieString = cookie
|
final String cookieString = cookie
|
||||||
.map((Cookie cookie) => '${cookie.name}=${cookie.value}')
|
.map((Cookie cookie) => '${cookie.name}=${cookie.value}')
|
||||||
.join('; ');
|
.join('; ');
|
||||||
@@ -89,6 +92,33 @@ class Request {
|
|||||||
dio.options.headers['referer'] = 'https://www.bilibili.com/';
|
dio.options.headers['referer'] = 'https://www.bilibili.com/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future buvidActivate() async {
|
||||||
|
var html = await Request().get(Api.dynamicSpmPrefix);
|
||||||
|
String spmPrefix = spmPrefixExp.firstMatch(html.data)!.group(1)!;
|
||||||
|
Random rand = Random();
|
||||||
|
String rand_png_end = base64.encode(
|
||||||
|
List<int>.generate(32, (_) => rand.nextInt(256)) +
|
||||||
|
List<int>.filled(4, 0) +
|
||||||
|
[73, 69, 78, 68] +
|
||||||
|
List<int>.generate(4, (_) => rand.nextInt(256))
|
||||||
|
);
|
||||||
|
|
||||||
|
String jsonData = json.encode({
|
||||||
|
'3064': 1,
|
||||||
|
'39c8': '${spmPrefix}.fp.risk',
|
||||||
|
'3c43': {
|
||||||
|
'adca': 'Linux',
|
||||||
|
'bfe9': rand_png_end.substring(rand_png_end.length - 50),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await Request().post(
|
||||||
|
Api.activateBuvidApi,
|
||||||
|
data: {'payload': jsonData},
|
||||||
|
options: Options(contentType: 'application/json')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* config it and create
|
* config it and create
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class MemberHttp {
|
|||||||
'dm_img_list': '[]',
|
'dm_img_list': '[]',
|
||||||
'dm_img_str': dmImgStr.substring(0, dmImgStr.length - 2),
|
'dm_img_str': dmImgStr.substring(0, dmImgStr.length - 2),
|
||||||
'dm_cover_img_str': dmCoverImgStr.substring(0, dmCoverImgStr.length - 2),
|
'dm_cover_img_str': dmCoverImgStr.substring(0, dmCoverImgStr.length - 2),
|
||||||
|
'dm_img_inter': '{"ds":[],"wh":[0,0,0],"of":[0,0,0]}',
|
||||||
});
|
});
|
||||||
var res = await Request().get(
|
var res = await Request().get(
|
||||||
Api.memberArchive,
|
Api.memberArchive,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class ReplyContent {
|
|||||||
this.vote,
|
this.vote,
|
||||||
this.richText,
|
this.richText,
|
||||||
this.isText,
|
this.isText,
|
||||||
|
this.topicsMeta,
|
||||||
});
|
});
|
||||||
|
|
||||||
String? message;
|
String? message;
|
||||||
@@ -20,6 +21,7 @@ class ReplyContent {
|
|||||||
Map? vote;
|
Map? vote;
|
||||||
Map? richText;
|
Map? richText;
|
||||||
bool? isText;
|
bool? isText;
|
||||||
|
Map? topicsMeta;
|
||||||
|
|
||||||
ReplyContent.fromJson(Map<String, dynamic> json) {
|
ReplyContent.fromJson(Map<String, dynamic> json) {
|
||||||
message = json['message']
|
message = json['message']
|
||||||
@@ -39,6 +41,7 @@ class ReplyContent {
|
|||||||
richText = json['rich_text'] ?? {};
|
richText = json['rich_text'] ?? {};
|
||||||
// 不包含@ 笔记 图片的时候,文字可折叠
|
// 不包含@ 笔记 图片的时候,文字可折叠
|
||||||
isText = atNameToMid!.isEmpty && vote!.isEmpty && pictures!.isEmpty;
|
isText = atNameToMid!.isEmpty && vote!.isEmpty && pictures!.isEmpty;
|
||||||
|
topicsMeta = json['topics_meta'] ?? {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,11 +236,26 @@ class AboutController extends GetxController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
githubRelease() {
|
||||||
|
launchUrl(
|
||||||
|
Uri.parse('https://github.com/guozhigq/pilipala/release'),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 从网盘下载
|
// 从网盘下载
|
||||||
panDownload() {
|
panDownload() {
|
||||||
launchUrl(
|
Clipboard.setData(
|
||||||
Uri.parse('https://www.123pan.com/s/9sVqVv-flu0A.html'),
|
const ClipboardData(text: 'pili'),
|
||||||
mode: LaunchMode.externalApplication,
|
);
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'已复制提取码:pili',
|
||||||
|
displayTime: const Duration(milliseconds: 500),
|
||||||
|
).then(
|
||||||
|
(value) => launchUrl(
|
||||||
|
Uri.parse('https://www.123pan.com/s/9sVqVv-flu0A.html'),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 问题反馈
|
// 问题反馈
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
late List defaultTabs;
|
late List defaultTabs;
|
||||||
late List<String> tabbarSort;
|
late List<String> tabbarSort;
|
||||||
RxString defaultSearch = ''.obs;
|
RxString defaultSearch = ''.obs;
|
||||||
|
late bool enableGradientBg;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -40,6 +41,8 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
|
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
|
||||||
searchDefault();
|
searchDefault();
|
||||||
}
|
}
|
||||||
|
enableGradientBg =
|
||||||
|
setting.get(SettingBoxKey.enableGradientBg, defaultValue: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRefresh() {
|
void onRefresh() {
|
||||||
|
|||||||
@@ -48,38 +48,48 @@ class _HomePageState extends State<HomePage>
|
|||||||
super.build(context);
|
super.build(context);
|
||||||
Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
|
Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
|
||||||
// 设置状态栏图标的亮度
|
// 设置状态栏图标的亮度
|
||||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
if (_homeController.enableGradientBg) {
|
||||||
statusBarIconBrightness: currentBrightness == Brightness.light
|
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||||
? Brightness.dark
|
statusBarIconBrightness: currentBrightness == Brightness.light
|
||||||
: Brightness.light,
|
? Brightness.dark
|
||||||
));
|
: Brightness.light,
|
||||||
|
));
|
||||||
|
}
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
extendBody: true,
|
extendBody: true,
|
||||||
extendBodyBehindAppBar: true,
|
extendBodyBehindAppBar: true,
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
// gradient background
|
// gradient background
|
||||||
Align(
|
if (_homeController.enableGradientBg) ...[
|
||||||
alignment: Alignment.topLeft,
|
Align(
|
||||||
child: Opacity(
|
alignment: Alignment.topLeft,
|
||||||
opacity: 0.6,
|
child: Opacity(
|
||||||
child: Container(
|
opacity: 0.6,
|
||||||
width: MediaQuery.of(context).size.width,
|
child: Container(
|
||||||
height: MediaQuery.of(context).size.height,
|
width: MediaQuery.of(context).size.width,
|
||||||
decoration: BoxDecoration(
|
height: MediaQuery.of(context).size.height,
|
||||||
gradient: LinearGradient(
|
decoration: BoxDecoration(
|
||||||
colors: [
|
gradient: LinearGradient(
|
||||||
Theme.of(context).colorScheme.primary.withOpacity(0.9),
|
colors: [
|
||||||
Theme.of(context).colorScheme.primary.withOpacity(0.5),
|
Theme.of(context)
|
||||||
Theme.of(context).colorScheme.surface
|
.colorScheme
|
||||||
],
|
.primary
|
||||||
begin: Alignment.topLeft,
|
.withOpacity(0.9),
|
||||||
end: Alignment.bottomRight,
|
Theme.of(context)
|
||||||
stops: const [0, 0.0034, 0.34]),
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
.withOpacity(0.5),
|
||||||
|
Theme.of(context).colorScheme.surface
|
||||||
|
],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
stops: const [0, 0.0034, 0.34]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
CustomAppBar(
|
CustomAppBar(
|
||||||
@@ -90,7 +100,37 @@ class _HomePageState extends State<HomePage>
|
|||||||
callback: showUserBottomSheet,
|
callback: showUserBottomSheet,
|
||||||
),
|
),
|
||||||
if (_homeController.tabs.length > 1) ...[
|
if (_homeController.tabs.length > 1) ...[
|
||||||
const CustomTabs(),
|
if (_homeController.enableGradientBg) ...[
|
||||||
|
const CustomTabs(),
|
||||||
|
] else ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 42,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: TabBar(
|
||||||
|
controller: _homeController.tabController,
|
||||||
|
tabs: [
|
||||||
|
for (var i in _homeController.tabs)
|
||||||
|
Tab(text: i['label'])
|
||||||
|
],
|
||||||
|
isScrollable: true,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
enableFeedback: true,
|
||||||
|
splashBorderRadius: BorderRadius.circular(10),
|
||||||
|
tabAlignment: TabAlignment.center,
|
||||||
|
onTap: (value) {
|
||||||
|
feedBack();
|
||||||
|
if (_homeController.initialIndex.value == value) {
|
||||||
|
_homeController.tabsCtrList[value]().animateToTop();
|
||||||
|
}
|
||||||
|
_homeController.initialIndex.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
] else ...[
|
] else ...[
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import 'package:PiliPalaX/http/live.dart';
|
|||||||
import 'package:PiliPalaX/models/live/room_info.dart';
|
import 'package:PiliPalaX/models/live/room_info.dart';
|
||||||
import 'package:PiliPalaX/plugin/pl_player/index.dart';
|
import 'package:PiliPalaX/plugin/pl_player/index.dart';
|
||||||
import '../../models/live/room_info_h5.dart';
|
import '../../models/live/room_info_h5.dart';
|
||||||
|
import '../../utils/storage.dart';
|
||||||
|
import '../../utils/video_utils.dart';
|
||||||
|
|
||||||
class LiveRoomController extends GetxController {
|
class LiveRoomController extends GetxController {
|
||||||
String cover = '';
|
String cover = '';
|
||||||
@@ -16,6 +18,7 @@ class LiveRoomController extends GetxController {
|
|||||||
PlPlayerController plPlayerController =
|
PlPlayerController plPlayerController =
|
||||||
PlPlayerController.getInstance(videoType: 'live');
|
PlPlayerController.getInstance(videoType: 'live');
|
||||||
Rx<RoomInfoH5Model> roomInfoH5 = RoomInfoH5Model().obs;
|
Rx<RoomInfoH5Model> roomInfoH5 = RoomInfoH5Model().obs;
|
||||||
|
late bool enableCDN;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -31,6 +34,8 @@ class LiveRoomController extends GetxController {
|
|||||||
cover = liveItem.cover;
|
cover = liveItem.cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// CDN优化
|
||||||
|
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerInit(source) async {
|
playerInit(source) async {
|
||||||
@@ -57,9 +62,11 @@ class LiveRoomController extends GetxController {
|
|||||||
List<CodecItem> codec =
|
List<CodecItem> codec =
|
||||||
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
||||||
CodecItem item = codec.first;
|
CodecItem item = codec.first;
|
||||||
String videoUrl = (item.urlInfo?.first.host)! +
|
String videoUrl = enableCDN
|
||||||
item.baseUrl! +
|
? VideoUtils.getCdnUrl(item)
|
||||||
item.urlInfo!.first.extra!;
|
: (item.urlInfo?.first.host)! +
|
||||||
|
item.baseUrl! +
|
||||||
|
item.urlInfo!.first.extra!;
|
||||||
await playerInit(videoUrl);
|
await playerInit(videoUrl);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ class _StyleSettingState extends State<StyleSetting> {
|
|||||||
defaultVal: true,
|
defaultVal: true,
|
||||||
needReboot: true,
|
needReboot: true,
|
||||||
),
|
),
|
||||||
|
const SetSwitchItem(
|
||||||
|
title: '首页底栏背景渐变',
|
||||||
|
setKey: SettingBoxKey.enableGradientBg,
|
||||||
|
defaultVal: true,
|
||||||
|
needReboot: true,
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
double? result = await showDialog(
|
double? result = await showDialog(
|
||||||
|
|||||||
@@ -507,6 +507,7 @@ InlineSpan buildContent(
|
|||||||
// 构建正则表达式
|
// 构建正则表达式
|
||||||
final List<String> specialTokens = [
|
final List<String> specialTokens = [
|
||||||
...content.emote.keys,
|
...content.emote.keys,
|
||||||
|
...content.topicsMeta?.keys?.map((e) => '#$e#') ?? [],
|
||||||
...content.atNameToMid.keys.map((e) => '@$e'),
|
...content.atNameToMid.keys.map((e) => '@$e'),
|
||||||
...content.jumpUrl.keys.map((e) =>
|
...content.jumpUrl.keys.map((e) =>
|
||||||
e.replaceAll('?', '\\?').replaceAll('+', '\\+').replaceAll('*', '\\*')),
|
e.replaceAll('?', '\\?').replaceAll('+', '\\+').replaceAll('*', '\\*')),
|
||||||
@@ -590,7 +591,7 @@ InlineSpan buildContent(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// print("matchStr=$matchStr");
|
print("matchStr=$matchStr");
|
||||||
String appUrlSchema = '';
|
String appUrlSchema = '';
|
||||||
final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe,
|
final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe,
|
||||||
defaultValue: false) as bool;
|
defaultValue: false) as bool;
|
||||||
@@ -693,6 +694,23 @@ InlineSpan buildContent(
|
|||||||
);
|
);
|
||||||
// 只显示一次
|
// 只显示一次
|
||||||
matchedStrs.add(matchStr);
|
matchedStrs.add(matchStr);
|
||||||
|
} else if (content
|
||||||
|
.topicsMeta[matchStr.substring(1, matchStr.length - 1)] !=
|
||||||
|
null) {
|
||||||
|
spanChilds.add(
|
||||||
|
TextSpan(
|
||||||
|
text: matchStr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
final String topic =
|
||||||
|
matchStr.substring(1, matchStr.length - 1);
|
||||||
|
Get.toNamed('/searchResult', parameters: {'keyword': topic});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addPlainTextSpan(matchStr);
|
addPlainTextSpan(matchStr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ class SettingBoxKey {
|
|||||||
tabbarSort = 'tabbarSort', // 首页tabbar
|
tabbarSort = 'tabbarSort', // 首页tabbar
|
||||||
dynamicBadgeMode = 'dynamicBadgeMode',
|
dynamicBadgeMode = 'dynamicBadgeMode',
|
||||||
hiddenSettingUnlocked = 'hiddenSettingUnlocked';
|
hiddenSettingUnlocked = 'hiddenSettingUnlocked';
|
||||||
|
enableGradientBg = 'enableGradientBg';
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalCacheKey {
|
class LocalCacheKey {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import '../http/index.dart';
|
|||||||
import '../models/github/latest.dart';
|
import '../models/github/latest.dart';
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
|
static final Random random = Random();
|
||||||
|
|
||||||
static Future<String> getCookiePath() async {
|
static Future<String> getCookiePath() async {
|
||||||
final Directory tempDir = await getApplicationSupportDirectory();
|
final Directory tempDir = await getApplicationSupportDirectory();
|
||||||
final String tempPath = "${tempDir.path}/.plpl/";
|
final String tempPath = "${tempDir.path}/.plpl/";
|
||||||
@@ -181,7 +183,7 @@ class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String makeHeroTag(v) {
|
static String makeHeroTag(v) {
|
||||||
return v.toString() + Random().nextInt(9999).toString();
|
return v.toString() + random.nextInt(9999).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int duration(String duration) {
|
static int duration(String duration) {
|
||||||
@@ -340,18 +342,14 @@ class Utils {
|
|||||||
return md5String;
|
return md5String;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String generateRandomString(int minLength, int maxLength) {
|
static List<int> generateRandomBytes(int minLength, int maxLength) {
|
||||||
const String printable =
|
return List<int>.generate(
|
||||||
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#\$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ';
|
random.nextInt(maxLength-minLength+1), (_) => random.nextInt(0x60) + 0x20
|
||||||
|
);
|
||||||
var random = Random();
|
|
||||||
int length = minLength + random.nextInt(maxLength - minLength + 1);
|
|
||||||
return List<String>.generate(
|
|
||||||
length, (index) => printable[random.nextInt(printable.length)]).join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String base64EncodeRandomString(int minLength, int maxLength) {
|
static String base64EncodeRandomString(int minLength, int maxLength) {
|
||||||
String randomString = generateRandomString(minLength, maxLength);
|
List<int> randomBytes = generateRandomBytes(minLength, maxLength);
|
||||||
return base64.encode(utf8.encode(randomString));
|
return base64.encode(randomBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'package:PiliPalaX/models/video/play/url.dart';
|
import 'package:PiliPalaX/models/video/play/url.dart';
|
||||||
|
|
||||||
|
import '../models/live/room_info.dart';
|
||||||
|
|
||||||
class VideoUtils {
|
class VideoUtils {
|
||||||
static String getCdnUrl(dynamic item) {
|
static String getCdnUrl(dynamic item) {
|
||||||
var backupUrl = "";
|
var backupUrl = "";
|
||||||
@@ -12,13 +14,20 @@ class VideoUtils {
|
|||||||
} else if (item is AudioItem) {
|
} else if (item is AudioItem) {
|
||||||
backupUrl = item.backupUrl ?? "";
|
backupUrl = item.backupUrl ?? "";
|
||||||
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
||||||
|
} else if (item is CodecItem) {
|
||||||
|
backupUrl = (item.urlInfo?.first.host)! +
|
||||||
|
item.baseUrl! +
|
||||||
|
item.urlInfo!.first.extra!;
|
||||||
|
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// issues #70
|
/// issues #70
|
||||||
if (videoUrl.contains(".mcdn.bilivideo") ||
|
if (videoUrl.contains(".mcdn.bilivideo")) {
|
||||||
videoUrl.contains("/upgcxcode/")) {
|
videoUrl =
|
||||||
|
'https://proxy-tf-all-ws.bilivideo.com/?url=${Uri.encodeComponent(videoUrl)}';
|
||||||
|
} else if (videoUrl.contains("/upgcxcode/")) {
|
||||||
//CDN列表
|
//CDN列表
|
||||||
var cdnList = {
|
var cdnList = {
|
||||||
'ali': 'upos-sz-mirrorali.bilivideo.com',
|
'ali': 'upos-sz-mirrorali.bilivideo.com',
|
||||||
|
|||||||
Reference in New Issue
Block a user