opt: isolate parse danmaku & feat: grpc account (#1785)

* opt: isolate parse danmaku

* feat: grpc account
This commit is contained in:
My-Responsitories
2025-12-18 22:27:40 +08:00
committed by GitHub
parent 1e0e2d2d6e
commit b4a5d985f5
9 changed files with 274 additions and 262 deletions

View File

@@ -18,6 +18,7 @@ abstract final class DmGrpc {
type: type, type: type,
), ),
DmSegMobileReply.fromBuffer, DmSegMobileReply.fromBuffer,
isolate: true,
); );
} }
} }

View File

@@ -1,120 +1,19 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/grpc/bilibili/metadata.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/device.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/fawkes.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/locale.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/network.pb.dart' as network;
import 'package:PiliPlus/grpc/bilibili/rpc.pb.dart'; import 'package:PiliPlus/grpc/bilibili/rpc.pb.dart';
import 'package:PiliPlus/http/constants.dart'; import 'package:PiliPlus/http/constants.dart';
import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/init.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/login_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:archive/archive.dart'; import 'package:archive/archive.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/foundation.dart' show kDebugMode, compute;
import 'package:protobuf/protobuf.dart' show GeneratedMessage; import 'package:protobuf/protobuf.dart' show GeneratedMessage;
abstract final class GrpcReq { abstract final class GrpcReq {
static String? _accessKey = Accounts.main.accessKey; static const _isolateSize = 256 * 1024;
static const _build = 2001100;
static const _versionName = '2.0.1';
static const _biliChannel = 'master';
static const _mobiApp = 'android_hd';
static const _device = 'android';
static final _buvid = LoginUtils.buvid; static final options = Options(responseType: ResponseType.bytes);
static final _traceId = IdUtils.genTraceId();
static final _sessionId = Utils.generateRandomString(8);
static void updateHeaders(String? accessKey) {
_accessKey = accessKey;
if (_accessKey != null) {
headers['authorization'] = 'identify_v1 $_accessKey';
} else {
headers.remove('authorization');
}
headers['x-bili-metadata-bin'] = base64Encode(
Metadata(
accessKey: _accessKey ?? '',
mobiApp: _mobiApp,
device: _device,
build: _build,
channel: _biliChannel,
buvid: _buvid,
platform: _device,
).writeToBuffer(),
);
}
static final Map<String, String> headers = {
Headers.contentTypeHeader: 'application/grpc',
'grpc-encoding': 'gzip',
'gzip-accept-encoding': 'gzip,identity',
'user-agent': Constants.userAgent,
'x-bili-gaia-vtoken': '',
'x-bili-aurora-zone': '',
'x-bili-trace-id': _traceId,
if (_accessKey != null) 'authorization': 'identify_v1 $_accessKey',
'buvid': _buvid,
'bili-http-engine': 'cronet',
'te': 'trailers',
'x-bili-fawkes-req-bin': base64Encode(
FawkesReq(
appkey: _mobiApp,
env: 'prod',
sessionId: _sessionId,
).writeToBuffer(),
),
'x-bili-metadata-bin': base64Encode(
Metadata(
accessKey: _accessKey ?? '',
mobiApp: _mobiApp,
device: _device,
build: _build,
channel: _biliChannel,
buvid: _buvid,
platform: _device,
).writeToBuffer(),
),
'x-bili-device-bin': base64Encode(
Device(
appId: 5,
build: _build,
buvid: _buvid,
mobiApp: _mobiApp,
platform: _device,
channel: _biliChannel,
brand: _device,
model: _device,
osver: '15',
versionName: _versionName,
).writeToBuffer(),
),
'x-bili-network-bin': base64Encode(
network.Network(
type: network.NetworkType.WIFI,
).writeToBuffer(),
),
'x-bili-locale-bin': base64Encode(
Locale(
cLocale: LocaleIds(language: 'zh', region: 'CN', script: 'Hans'),
sLocale: LocaleIds(language: 'zh', region: 'CN', script: 'Hans'),
timezone: 'Asia/Shanghai',
).writeToBuffer(),
),
'x-bili-exps-bin': '',
};
static final Options options = Options(
headers: headers,
responseType: ResponseType.bytes,
);
static Uint8List compressProtobuf(Uint8List proto) { static Uint8List compressProtobuf(Uint8List proto) {
proto = const GZipEncoder().encodeBytes(proto); proto = const GZipEncoder().encodeBytes(proto);
@@ -136,11 +35,22 @@ abstract final class GrpcReq {
} }
} }
static LoadingState<T> _parse<T>((Uint8List, T Function(Uint8List)) args) {
try {
final data = decompressProtobuf(args.$1);
final grpcResponse = args.$2(data);
return Success(grpcResponse);
} catch (e) {
return Error(e.toString());
}
}
static Future<LoadingState<T>> request<T>( static Future<LoadingState<T>> request<T>(
String url, String url,
GeneratedMessage request, GeneratedMessage request,
T Function(Uint8List) grpcParser, T Function(Uint8List) grpcParser, {
) async { bool isolate = false,
}) async {
final response = await Request().post<Uint8List>( final response = await Request().post<Uint8List>(
HttpString.appBaseUrl + url, HttpString.appBaseUrl + url,
data: compressProtobuf(request.writeToBuffer()), data: compressProtobuf(request.writeToBuffer()),
@@ -152,13 +62,13 @@ abstract final class GrpcReq {
} }
if (response.headers.value('Grpc-Status') == '0') { if (response.headers.value('Grpc-Status') == '0') {
try { final data = response.data;
Uint8List data = response.data; if (data is Uint8List) {
data = decompressProtobuf(data); return isolate && data.length > _isolateSize
final grpcResponse = grpcParser(data); ? compute(_parse, (data, grpcParser))
return Success(grpcResponse); : _parse((data, grpcParser));
} catch (e) { } else {
return Error(e.toString()); return Error('grpc: ${data.runtimeType} is not Uint8List');
} }
} else { } else {
try { try {

View File

@@ -2,7 +2,7 @@ import 'package:PiliPlus/models/common/account_type.dart';
import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart';
import 'package:PiliPlus/pages/setting/models/model.dart'; import 'package:PiliPlus/pages/setting/models/model.dart';
import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/accounts/account_manager/account_mgr.dart'; import 'package:PiliPlus/utils/accounts/api_type.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -61,7 +61,7 @@ Widget _getAccountDetail(BuildContext context) {
final slivers = <Widget>[]; final slivers = <Widget>[];
final theme = TextTheme.of(context); final theme = TextTheme.of(context);
for (var i in AccountType.values) { for (var i in AccountType.values) {
final url = AccountManager.apiTypeSet[i]; final url = ApiType.apiTypeSet[i];
if (url == null) continue; if (url == null) continue;
slivers slivers

View File

@@ -1,6 +1,7 @@
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/models/common/account_type.dart'; import 'package:PiliPlus/models/common/account_type.dart';
import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/accounts/grpc_headers.dart';
import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart';
import 'package:cookie_jar/cookie_jar.dart'; import 'package:cookie_jar/cookie_jar.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
@@ -26,6 +27,8 @@ sealed class Account {
Map<String, String> get headers => throw UnimplementedError(); Map<String, String> get headers => throw UnimplementedError();
Map<String, String> get grpcHeaders => throw UnimplementedError();
bool get isLogin => throw UnimplementedError(); bool get isLogin => throw UnimplementedError();
int get mid => throw UnimplementedError(); int get mid => throw UnimplementedError();
@@ -65,6 +68,11 @@ class LoginAccount extends Account {
'x-bili-aurora-eid': IdUtils.genAuroraEid(mid), 'x-bili-aurora-eid': IdUtils.genAuroraEid(mid),
}; };
@override
late final Map<String, String> grpcHeaders = GrpcHeaders.newHeaders(
accessKey,
);
@override @override
late final String csrf = late final String csrf =
cookieJar.domainCookies['bilibili.com']!['/']!['bili_jct']!.cookie.value; cookieJar.domainCookies['bilibili.com']!['/']!['bili_jct']!.cookie.value;
@@ -140,12 +148,17 @@ class AnonymousAccount extends Account {
@override @override
final Map<String, String> headers = Constants.baseHeaders; final Map<String, String> headers = Constants.baseHeaders;
@override
final Map<String, String> grpcHeaders = GrpcHeaders.newHeaders();
@override @override
bool activated = false; bool activated = false;
@override @override
Future<void> delete() => Future<void> delete() {
cookieJar.deleteAll().whenComplete(cookieJar.setBuvid3); grpcHeaders['x-bili-fawkes-req-bin'] = GrpcHeaders.fawkes;
return cookieJar.deleteAll().whenComplete(cookieJar.setBuvid3);
}
static final _instance = AnonymousAccount._(); static final _instance = AnonymousAccount._();

View File

@@ -7,6 +7,7 @@ import 'package:PiliPlus/http/constants.dart';
import 'package:PiliPlus/models/common/account_type.dart'; import 'package:PiliPlus/models/common/account_type.dart';
import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/accounts/account.dart'; import 'package:PiliPlus/utils/accounts/account.dart';
import 'package:PiliPlus/utils/accounts/api_type.dart';
import 'package:PiliPlus/utils/app_sign.dart'; import 'package:PiliPlus/utils/app_sign.dart';
import 'package:PiliPlus/utils/extension/string_ext.dart'; import 'package:PiliPlus/utils/extension/string_ext.dart';
import 'package:PiliPlus/utils/platform_utils.dart'; import 'package:PiliPlus/utils/platform_utils.dart';
@@ -20,115 +21,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
final _setCookieReg = RegExp('(?<=)(,)(?=[^;]+?=)'); final _setCookieReg = RegExp('(?<=)(,)(?=[^;]+?=)');
class AccountManager extends Interceptor { class AccountManager extends Interceptor {
static const Map<AccountType, Set<String>> apiTypeSet = {
AccountType.heartbeat: {
Api.videoIntro,
Api.replyList,
Api.replyReplyList,
// history
Api.heartBeat,
Api.historyReport,
Api.roomEntryAction,
Api.liveLikeReport,
Api.mediaListHistory,
// Api.historyList,
// Api.pauseHistory,
// Api.clearHistory,
// Api.delHistory,
// Api.searchHistory,
// Api.historyStatus,
// progress
Api.pgcInfo,
Api.pugvInfo,
Api.ab2c,
Api.liveRoomInfo,
Api.liveRoomInfoH5,
Api.onlineTotal,
Api.dynamicDetail,
Api.aiConclusion,
Api.getSeasonDetailApi,
Api.liveRoomDmToken,
Api.liveRoomDmPrefetch,
Api.superChatMsg,
Api.searchByType,
Api.dynSearch,
Api.searchArchive,
// Api.memberInfo,
// Api.bgmDetail,
// Api.space,
// Api.spaceAudio,
// Api.spaceComic,
// Api.spaceArchive,
// Api.spaceChargingArchive,
// Api.spaceSeason,
// Api.spaceSeries,
// Api.spaceBangumi,
// Api.spaceOpus,
// Api.spaceFav,
// Api.seasonSeries,
// Api.matchInfo,
// Api.articleList,
// Api.opusDetail,
// Api.articleView,
// Api.articleInfo,
},
AccountType.recommend: {
Api.recommendListWeb,
Api.recommendListApp,
Api.feedDislike,
Api.feedDislikeCancel,
Api.hotList,
Api.relatedList,
Api.hotSearchList, // 不同账号搜索结果可能不一样
Api.searchDefault,
Api.searchSuggest,
Api.liveList,
Api.searchTrending,
Api.searchRecommend,
Api.getRankApi,
Api.pgcRank,
Api.pgcSeasonRank,
Api.pgcIndexResult,
Api.popularSeriesOne,
Api.popularSeriesList,
Api.popularPrecious,
Api.liveAreaList,
Api.liveFeedIndex,
Api.liveSecondList,
Api.liveRoomAreaList,
Api.liveSearch,
Api.bgmRecommend,
Api.dynTopicRcmd,
Api.topicFeed,
Api.topicTop,
},
// progress
AccountType.video: {
Api.ugcUrl,
Api.pgcUrl,
Api.pugvUrl,
Api.tvPlayUrl,
},
};
static const loginApi = {
Api.getTVCode,
Api.qrcodePoll,
Api.getCaptcha,
Api.getWebKey,
Api.appSmsCode,
Api.loginByPwdApi,
Api.logInByAppSms,
Api.safeCenterGetInfo,
Api.preCapture,
Api.safeCenterSmsCode,
Api.safeCenterSmsVerify,
Api.oauth2AccessToken,
};
AccountManager(); AccountManager();
String blockServer = Pref.blockServer; String blockServer = Pref.blockServer;
@@ -164,29 +56,31 @@ class AccountManager extends Interceptor {
); );
} }
final isApp = path.startsWith(HttpString.appBaseUrl);
if (isApp && options.responseType == ResponseType.bytes) {
options.headers.addAll(account.grpcHeaders);
return handler.next(options);
}
options.headers options.headers
..addAll(account.headers) ..addAll(account.headers)
..['referer'] ??= HttpString.baseUrl; ..['referer'] ??= HttpString.baseUrl;
// app端不需要管理cookie // app端不需要管理cookie
if (path.startsWith(HttpString.appBaseUrl)) { if (isApp) {
// if (kDebugMode) debugPrint('is app: ${options.path}'); // if (kDebugMode) debugPrint('is app: ${options.path}');
// bytes是grpc响应 final dataPtr = (options.method == 'POST' && options.data is Map
if (options.responseType != ResponseType.bytes) { ? (options.data as Map).cast<String, dynamic>()
final dataPtr = : options.queryParameters);
(options.method == 'POST' && options.data is Map if (dataPtr.isNotEmpty) {
? options.data as Map if (!account.accessKey.isNullOrEmpty) {
: options.queryParameters) dataPtr['access_key'] = account.accessKey!;
.cast<String, dynamic>();
if (dataPtr.isNotEmpty) {
if (!account.accessKey.isNullOrEmpty) {
dataPtr['access_key'] = account.accessKey!;
}
dataPtr['ts'] ??= (DateTime.now().millisecondsSinceEpoch ~/ 1000)
.toString();
AppSign.appSign(dataPtr);
// if (kDebugMode) debugPrint(dataPtr.toString());
} }
dataPtr['ts'] ??= (DateTime.now().millisecondsSinceEpoch ~/ 1000)
.toString();
AppSign.appSign(dataPtr);
// if (kDebugMode) debugPrint(dataPtr.toString());
} }
return handler.next(options); return handler.next(options);
} else { } else {
@@ -222,9 +116,9 @@ class AccountManager extends Interceptor {
void onResponse(Response response, ResponseInterceptorHandler handler) { void onResponse(Response response, ResponseInterceptorHandler handler) {
final options = response.requestOptions; final options = response.requestOptions;
final path = options.path; final path = options.path;
if (path.startsWith(HttpString.appBaseUrl) || if (options.extra['account'] is NoAccount ||
_skipCookie(path) || path.startsWith(HttpString.appBaseUrl) ||
options.extra['account'] is NoAccount) { _skipCookie(path)) {
return handler.next(response); return handler.next(response);
} else { } else {
final future = _saveCookies( final future = _saveCookies(
@@ -309,7 +203,7 @@ class AccountManager extends Interceptor {
.map(Cookie.fromSetCookieValue) .map(Cookie.fromSetCookieValue)
.toList(); .toList();
final statusCode = response.statusCode ?? 0; final statusCode = response.statusCode ?? 0;
final locations = response.headers[HttpHeaders.locationHeader] ?? []; final locations = response.headers[HttpHeaders.locationHeader] ?? const [];
final isRedirectRequest = statusCode >= 300 && statusCode < 400; final isRedirectRequest = statusCode >= 300 && statusCode < 400;
final originalUri = response.requestOptions.uri; final originalUri = response.requestOptions.uri;
final realUri = originalUri.resolveUri(response.realUri); final realUri = originalUri.resolveUri(response.realUri);
@@ -335,11 +229,11 @@ class AccountManager extends Interceptor {
path.contains('biliimg.com'); path.contains('biliimg.com');
} }
Account _findAccount(String path) => loginApi.contains(path) Account _findAccount(String path) => ApiType.loginApi.contains(path)
? AnonymousAccount() ? AnonymousAccount()
: Accounts.get( : Accounts.get(
AccountType.values.firstWhere( AccountType.values.firstWhere(
(i) => apiTypeSet[i]?.contains(path) == true, (i) => ApiType.apiTypeSet[i]?.contains(path) == true,
orElse: () => AccountType.main, orElse: () => AccountType.main,
), ),
); );

View File

@@ -0,0 +1,114 @@
import 'package:PiliPlus/http/api.dart';
import 'package:PiliPlus/models/common/account_type.dart';
abstract final class ApiType {
// TODO: grpc api type
static const Map<AccountType, Set<String>> apiTypeSet = {
AccountType.heartbeat: {
Api.videoIntro,
Api.replyList,
Api.replyReplyList,
// history
Api.heartBeat,
Api.historyReport,
Api.roomEntryAction,
Api.liveLikeReport,
Api.mediaListHistory,
// Api.historyList,
// Api.pauseHistory,
// Api.clearHistory,
// Api.delHistory,
// Api.searchHistory,
// Api.historyStatus,
// progress
Api.pgcInfo,
Api.pugvInfo,
Api.ab2c,
Api.liveRoomInfo,
Api.liveRoomInfoH5,
Api.onlineTotal,
Api.dynamicDetail,
Api.aiConclusion,
Api.getSeasonDetailApi,
Api.liveRoomDmToken,
Api.liveRoomDmPrefetch,
Api.superChatMsg,
Api.searchByType,
Api.dynSearch,
Api.searchArchive,
// Api.memberInfo,
// Api.bgmDetail,
// Api.space,
// Api.spaceAudio,
// Api.spaceComic,
// Api.spaceArchive,
// Api.spaceChargingArchive,
// Api.spaceSeason,
// Api.spaceSeries,
// Api.spaceBangumi,
// Api.spaceOpus,
// Api.spaceFav,
// Api.seasonSeries,
// Api.matchInfo,
// Api.articleList,
// Api.opusDetail,
// Api.articleView,
// Api.articleInfo,
},
AccountType.recommend: {
Api.recommendListWeb,
Api.recommendListApp,
Api.feedDislike,
Api.feedDislikeCancel,
Api.hotList,
Api.relatedList,
Api.hotSearchList, // 不同账号搜索结果可能不一样
Api.searchDefault,
Api.searchSuggest,
Api.liveList,
Api.searchTrending,
Api.searchRecommend,
Api.getRankApi,
Api.pgcRank,
Api.pgcSeasonRank,
Api.pgcIndexResult,
Api.popularSeriesOne,
Api.popularSeriesList,
Api.popularPrecious,
Api.liveAreaList,
Api.liveFeedIndex,
Api.liveSecondList,
Api.liveRoomAreaList,
Api.liveSearch,
Api.bgmRecommend,
Api.dynTopicRcmd,
Api.topicFeed,
Api.topicTop,
},
// progress
AccountType.video: {
Api.ugcUrl,
Api.pgcUrl,
Api.pugvUrl,
Api.tvPlayUrl,
},
};
static const loginApi = {
Api.getTVCode,
Api.qrcodePoll,
Api.getCaptcha,
Api.getWebKey,
Api.appSmsCode,
Api.loginByPwdApi,
Api.logInByAppSms,
Api.safeCenterGetInfo,
Api.preCapture,
Api.safeCenterSmsCode,
Api.safeCenterSmsVerify,
Api.oauth2AccessToken,
};
}

View File

@@ -0,0 +1,88 @@
import 'dart:convert';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/grpc/bilibili/metadata.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/device.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/fawkes.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/locale.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/network.pb.dart' as network;
import 'package:PiliPlus/utils/login_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:dio/dio.dart';
abstract final class GrpcHeaders {
static const _build = 2001100;
static const _versionName = '2.0.1';
static const _biliChannel = 'master';
static const _mobiApp = 'android_hd';
static const _device = 'android';
static String get _buvid => LoginUtils.buvid;
static String get _traceId => Constants.traceId;
static String get _sessionId => Utils.generateRandomString(8);
static final Map<String, String> _base = {
Headers.contentTypeHeader: 'application/grpc',
'grpc-encoding': 'gzip',
'gzip-accept-encoding': 'gzip,identity',
'user-agent': Constants.userAgent,
'x-bili-gaia-vtoken': '',
'x-bili-aurora-zone': '',
'x-bili-trace-id': _traceId,
'buvid': _buvid,
'bili-http-engine': 'cronet',
// 'te': 'trailers', // dio not supported
'x-bili-device-bin': base64Encode(
Device(
appId: 5,
build: _build,
buvid: _buvid,
mobiApp: _mobiApp,
platform: _device,
channel: _biliChannel,
brand: _device,
model: _device,
osver: '15',
versionName: _versionName,
).writeToBuffer(),
),
'x-bili-network-bin': base64Encode(
network.Network(type: network.NetworkType.WIFI).writeToBuffer(),
),
'x-bili-locale-bin': base64Encode(
Locale(
cLocale: LocaleIds(language: 'zh', region: 'CN', script: 'Hans'),
sLocale: LocaleIds(language: 'zh', region: 'CN', script: 'Hans'),
timezone: 'Asia/Shanghai',
).writeToBuffer(),
),
'x-bili-exps-bin': '',
};
static String get fawkes => base64Encode(
FawkesReq(
appkey: _mobiApp,
env: 'prod',
sessionId: _sessionId,
).writeToBuffer(),
);
static Map<String, String> newHeaders([String? accessKey]) {
return {
..._base,
if (accessKey != null) 'authorization': 'identify_v1 $accessKey',
'x-bili-fawkes-req-bin': fawkes,
'x-bili-metadata-bin': base64Encode(
Metadata(
accessKey: accessKey,
mobiApp: _mobiApp,
device: _device,
build: _build,
channel: _biliChannel,
buvid: _buvid,
platform: _device,
).writeToBuffer(),
),
};
}
}

View File

@@ -96,19 +96,15 @@ abstract final class IdUtils {
return base64Encoded; return base64Encoded;
} }
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/grpc_api/readme.md#x-bili-trace-id-生成算法
static String genTraceId() { static String genTraceId() {
String randomId = Utils.generateRandomString(32); final randomTraceId = StringBuffer(Utils.generateRandomString(24));
StringBuffer randomTraceId = StringBuffer(randomId.substring(0, 24)); final ts = (DateTime.now().millisecondsSinceEpoch ~/ 1000) >> 8;
int ts = DateTime.now().millisecondsSinceEpoch ~/ 1000; randomTraceId
..write((ts & 0xFFFFFF).toRadixString(16).padLeft(6, '0'))
for (int i = 2; i >= 0; i--) { ..write(Utils.generateRandomString(2));
ts >>= 8;
randomTraceId.write((ts & 0xFF).toRadixString(16).padLeft(2, '0'));
}
randomTraceId.write(randomId.substring(30, 32));
return '${randomTraceId.toString()}:${randomTraceId.toString().substring(16, 32)}:0:0'; return '${randomTraceId.toString()}:${randomTraceId.toString().substring(16, 32)}:0:0';
} }

View File

@@ -1,7 +1,6 @@
import 'dart:async' show FutureOr; import 'dart:async' show FutureOr;
import 'dart:io' show Platform; import 'dart:io' show Platform;
import 'package:PiliPlus/grpc/grpc_req.dart';
import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/main.dart';
import 'package:PiliPlus/models/user/info.dart'; import 'package:PiliPlus/models/user/info.dart';
@@ -49,7 +48,6 @@ abstract final class LoginUtils {
final account = Accounts.main; final account = Accounts.main;
final result = await UserHttp.userInfo(); final result = await UserHttp.userInfo();
if (result.isSuccess) { if (result.isSuccess) {
GrpcReq.updateHeaders(account.accessKey);
setWebCookie(account); setWebCookie(account);
RequestUtils.syncHistoryStatus(); RequestUtils.syncHistoryStatus();
final UserInfoData data = result.data; final UserInfoData data = result.data;
@@ -83,8 +81,6 @@ abstract final class LoginUtils {
..face.value = '' ..face.value = ''
..isLogin.value = false; ..isLogin.value = false;
GrpcReq.updateHeaders(null);
return Future.wait([ return Future.wait([
if (!Platform.isLinux) if (!Platform.isLinux)
web.CookieManager.instance( web.CookieManager.instance(