opt: type & grpc message (#842)

* opt: grpc type

* opt: grpc message

* opt: http type
This commit is contained in:
My-Responsitories
2025-05-10 12:40:27 +08:00
committed by GitHub
parent 7b4f08bb05
commit 024e74115e
21 changed files with 556 additions and 246 deletions

View File

@@ -8,8 +8,8 @@ class DmGrpc {
required int cid,
required int segmentIndex,
int type = 1,
}) async {
final res = await GrpcRepo.request(
}) {
return GrpcRepo.request(
GrpcUrl.dmSegMobile,
DmSegMobileReq(
oid: Int64(cid),
@@ -18,10 +18,5 @@ class DmGrpc {
),
DmSegMobileReply.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return const Error('');
}
}
}

View File

@@ -18,12 +18,12 @@ class DynGrpc {
// );
// }
static Future dynRed() {
return GrpcRepo.request(
static Future<int?> dynRed() async {
final res = await GrpcRepo.request(
GrpcUrl.dynRed,
DynRedReq(tabOffset: [TabOffset(tab: 1)]),
DynRedReply.fromBuffer,
onSuccess: (response) => response.dynRedItem.count.toInt(),
);
return res.dataOrNull?.dynRedItem.count.toInt();
}
}

View File

@@ -0,0 +1,232 @@
//
// Generated code. Do not modify.
// source: status.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import 'status.pbenum.dart';
export 'status.pbenum.dart';
class BiliStatus extends $pb.GeneratedMessage {
factory BiliStatus({
$core.int? code,
$core.String? message,
}) {
final $result = create();
if (code != null) {
$result.code = code;
}
if (message != null) {
$result.message = message;
}
return $result;
}
BiliStatus._() : super();
factory BiliStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory BiliStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BiliStatus', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create)
..a<$core.int>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.O3)
..aOS(2, _omitFieldNames ? '' : 'message')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
BiliStatus clone() => BiliStatus()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
BiliStatus copyWith(void Function(BiliStatus) updates) => super.copyWith((message) => updates(message as BiliStatus)) as BiliStatus;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static BiliStatus create() => BiliStatus._();
BiliStatus createEmptyInstance() => create();
static $pb.PbList<BiliStatus> createRepeated() => $pb.PbList<BiliStatus>();
@$core.pragma('dart2js:noInline')
static BiliStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BiliStatus>(create);
static BiliStatus? _defaultInstance;
@$pb.TagNumber(1)
$core.int get code => $_getIZ(0);
@$pb.TagNumber(1)
set code($core.int v) { $_setSignedInt32(0, v); }
@$pb.TagNumber(1)
$core.bool hasCode() => $_has(0);
@$pb.TagNumber(1)
void clearCode() => clearField(1);
@$pb.TagNumber(2)
$core.String get message => $_getSZ(1);
@$pb.TagNumber(2)
set message($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasMessage() => $_has(1);
@$pb.TagNumber(2)
void clearMessage() => clearField(2);
}
class GrpcDetail extends $pb.GeneratedMessage {
factory GrpcDetail({
$core.String? grpcType,
BiliStatus? status,
}) {
final $result = create();
if (grpcType != null) {
$result.grpcType = grpcType;
}
if (status != null) {
$result.status = status;
}
return $result;
}
GrpcDetail._() : super();
factory GrpcDetail.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory GrpcDetail.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GrpcDetail', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'grpcType')
..aOM<BiliStatus>(2, _omitFieldNames ? '' : 'status', subBuilder: BiliStatus.create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
GrpcDetail clone() => GrpcDetail()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
GrpcDetail copyWith(void Function(GrpcDetail) updates) => super.copyWith((message) => updates(message as GrpcDetail)) as GrpcDetail;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GrpcDetail create() => GrpcDetail._();
GrpcDetail createEmptyInstance() => create();
static $pb.PbList<GrpcDetail> createRepeated() => $pb.PbList<GrpcDetail>();
@$core.pragma('dart2js:noInline')
static GrpcDetail getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GrpcDetail>(create);
static GrpcDetail? _defaultInstance;
@$pb.TagNumber(1)
$core.String get grpcType => $_getSZ(0);
@$pb.TagNumber(1)
set grpcType($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasGrpcType() => $_has(0);
@$pb.TagNumber(1)
void clearGrpcType() => clearField(1);
@$pb.TagNumber(2)
BiliStatus get status => $_getN(1);
@$pb.TagNumber(2)
set status(BiliStatus v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasStatus() => $_has(1);
@$pb.TagNumber(2)
void clearStatus() => clearField(2);
@$pb.TagNumber(2)
BiliStatus ensureStatus() => $_ensure(1);
}
class Status extends $pb.GeneratedMessage {
factory Status({
Code? code,
$core.String? message,
$core.Iterable<GrpcDetail>? details,
}) {
final $result = create();
if (code != null) {
$result.code = code;
}
if (message != null) {
$result.message = message;
}
if (details != null) {
$result.details.addAll(details);
}
return $result;
}
Status._() : super();
factory Status.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Status.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Status', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create)
..e<Code>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: Code.OK, valueOf: Code.valueOf, enumValues: Code.values)
..aOS(2, _omitFieldNames ? '' : 'message')
..pc<GrpcDetail>(3, _omitFieldNames ? '' : 'details', $pb.PbFieldType.PM, subBuilder: GrpcDetail.create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Status clone() => Status()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Status copyWith(void Function(Status) updates) => super.copyWith((message) => updates(message as Status)) as Status;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Status create() => Status._();
Status createEmptyInstance() => create();
static $pb.PbList<Status> createRepeated() => $pb.PbList<Status>();
@$core.pragma('dart2js:noInline')
static Status getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Status>(create);
static Status? _defaultInstance;
/// The status code, which should be an enum value of
/// [google.rpc.Code][google.rpc.Code].
@$pb.TagNumber(1)
Code get code => $_getN(0);
@$pb.TagNumber(1)
set code(Code v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasCode() => $_has(0);
@$pb.TagNumber(1)
void clearCode() => clearField(1);
/// A developer-facing error message, which should be in English. Any
/// user-facing error message should be localized and sent in the
/// [google.rpc.Status.details][google.rpc.Status.details] field, or localized
/// by the client.
@$pb.TagNumber(2)
$core.String get message => $_getSZ(1);
@$pb.TagNumber(2)
set message($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasMessage() => $_has(1);
@$pb.TagNumber(2)
void clearMessage() => clearField(2);
/// A list of messages that carry the error details. There is a common set of
/// message types for APIs to use.
@$pb.TagNumber(3)
$core.List<GrpcDetail> get details => $_getList(2);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -0,0 +1,62 @@
//
// Generated code. Do not modify.
// source: status.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class Code extends $pb.ProtobufEnum {
static const Code OK = Code._(0, _omitEnumNames ? '' : 'OK');
static const Code CANCELLED = Code._(1, _omitEnumNames ? '' : 'CANCELLED');
static const Code UNKNOWN = Code._(2, _omitEnumNames ? '' : 'UNKNOWN');
static const Code INVALID_ARGUMENT = Code._(3, _omitEnumNames ? '' : 'INVALID_ARGUMENT');
static const Code DEADLINE_EXCEEDED = Code._(4, _omitEnumNames ? '' : 'DEADLINE_EXCEEDED');
static const Code NOT_FOUND = Code._(5, _omitEnumNames ? '' : 'NOT_FOUND');
static const Code ALREADY_EXISTS = Code._(6, _omitEnumNames ? '' : 'ALREADY_EXISTS');
static const Code PERMISSION_DENIED = Code._(7, _omitEnumNames ? '' : 'PERMISSION_DENIED');
static const Code UNAUTHENTICATED = Code._(16, _omitEnumNames ? '' : 'UNAUTHENTICATED');
static const Code RESOURCE_EXHAUSTED = Code._(8, _omitEnumNames ? '' : 'RESOURCE_EXHAUSTED');
static const Code FAILED_PRECONDITION = Code._(9, _omitEnumNames ? '' : 'FAILED_PRECONDITION');
static const Code ABORTED = Code._(10, _omitEnumNames ? '' : 'ABORTED');
static const Code OUT_OF_RANGE = Code._(11, _omitEnumNames ? '' : 'OUT_OF_RANGE');
static const Code UNIMPLEMENTED = Code._(12, _omitEnumNames ? '' : 'UNIMPLEMENTED');
static const Code INTERNAL = Code._(13, _omitEnumNames ? '' : 'INTERNAL');
static const Code UNAVAILABLE = Code._(14, _omitEnumNames ? '' : 'UNAVAILABLE');
static const Code DATA_LOSS = Code._(15, _omitEnumNames ? '' : 'DATA_LOSS');
static const $core.List<Code> values = <Code> [
OK,
CANCELLED,
UNKNOWN,
INVALID_ARGUMENT,
DEADLINE_EXCEEDED,
NOT_FOUND,
ALREADY_EXISTS,
PERMISSION_DENIED,
UNAUTHENTICATED,
RESOURCE_EXHAUSTED,
FAILED_PRECONDITION,
ABORTED,
OUT_OF_RANGE,
UNIMPLEMENTED,
INTERNAL,
UNAVAILABLE,
DATA_LOSS,
];
static final $core.Map<$core.int, Code> _byValue = $pb.ProtobufEnum.initByValue(values);
static Code? valueOf($core.int value) => _byValue[value];
const Code._($core.int v, $core.String n) : super(v, n);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');

View File

@@ -0,0 +1,92 @@
//
// Generated code. Do not modify.
// source: status.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use codeDescriptor instead')
const Code$json = {
'1': 'Code',
'2': [
{'1': 'OK', '2': 0},
{'1': 'CANCELLED', '2': 1},
{'1': 'UNKNOWN', '2': 2},
{'1': 'INVALID_ARGUMENT', '2': 3},
{'1': 'DEADLINE_EXCEEDED', '2': 4},
{'1': 'NOT_FOUND', '2': 5},
{'1': 'ALREADY_EXISTS', '2': 6},
{'1': 'PERMISSION_DENIED', '2': 7},
{'1': 'UNAUTHENTICATED', '2': 16},
{'1': 'RESOURCE_EXHAUSTED', '2': 8},
{'1': 'FAILED_PRECONDITION', '2': 9},
{'1': 'ABORTED', '2': 10},
{'1': 'OUT_OF_RANGE', '2': 11},
{'1': 'UNIMPLEMENTED', '2': 12},
{'1': 'INTERNAL', '2': 13},
{'1': 'UNAVAILABLE', '2': 14},
{'1': 'DATA_LOSS', '2': 15},
],
};
/// Descriptor for `Code`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List codeDescriptor = $convert.base64Decode(
'CgRDb2RlEgYKAk9LEAASDQoJQ0FOQ0VMTEVEEAESCwoHVU5LTk9XThACEhQKEElOVkFMSURfQV'
'JHVU1FTlQQAxIVChFERUFETElORV9FWENFRURFRBAEEg0KCU5PVF9GT1VORBAFEhIKDkFMUkVB'
'RFlfRVhJU1RTEAYSFQoRUEVSTUlTU0lPTl9ERU5JRUQQBxITCg9VTkFVVEhFTlRJQ0FURUQQEB'
'IWChJSRVNPVVJDRV9FWEhBVVNURUQQCBIXChNGQUlMRURfUFJFQ09ORElUSU9OEAkSCwoHQUJP'
'UlRFRBAKEhAKDE9VVF9PRl9SQU5HRRALEhEKDVVOSU1QTEVNRU5URUQQDBIMCghJTlRFUk5BTB'
'ANEg8KC1VOQVZBSUxBQkxFEA4SDQoJREFUQV9MT1NTEA8=');
@$core.Deprecated('Use biliStatusDescriptor instead')
const BiliStatus$json = {
'1': 'BiliStatus',
'2': [
{'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'},
{'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'},
],
};
/// Descriptor for `BiliStatus`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List biliStatusDescriptor = $convert.base64Decode(
'CgpCaWxpU3RhdHVzEhIKBGNvZGUYASABKAVSBGNvZGUSGAoHbWVzc2FnZRgCIAEoCVIHbWVzc2'
'FnZQ==');
@$core.Deprecated('Use grpcDetailDescriptor instead')
const GrpcDetail$json = {
'1': 'GrpcDetail',
'2': [
{'1': 'grpc_type', '3': 1, '4': 1, '5': 9, '10': 'grpcType'},
{'1': 'status', '3': 2, '4': 1, '5': 11, '6': '.google.rpc.BiliStatus', '10': 'status'},
],
};
/// Descriptor for `GrpcDetail`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List grpcDetailDescriptor = $convert.base64Decode(
'CgpHcnBjRGV0YWlsEhsKCWdycGNfdHlwZRgBIAEoCVIIZ3JwY1R5cGUSLgoGc3RhdHVzGAIgAS'
'gLMhYuZ29vZ2xlLnJwYy5CaWxpU3RhdHVzUgZzdGF0dXM=');
@$core.Deprecated('Use statusDescriptor instead')
const Status$json = {
'1': 'Status',
'2': [
{'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.google.rpc.Code', '10': 'code'},
{'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'},
{'1': 'details', '3': 3, '4': 3, '5': 11, '6': '.google.rpc.GrpcDetail', '10': 'details'},
],
};
/// Descriptor for `Status`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List statusDescriptor = $convert.base64Decode(
'CgZTdGF0dXMSJAoEY29kZRgBIAEoDjIQLmdvb2dsZS5ycGMuQ29kZVIEY29kZRIYCgdtZXNzYW'
'dlGAIgASgJUgdtZXNzYWdlEjAKB2RldGFpbHMYAyADKAsyFi5nb29nbGUucnBjLkdycGNEZXRh'
'aWxSB2RldGFpbHM=');

View File

@@ -8,8 +8,10 @@ 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/metadata/restriction.pb.dart';
import 'package:PiliPlus/grpc/google/rpc/status.pb.dart';
import 'package:PiliPlus/http/constants.dart';
import 'package:PiliPlus/http/init.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/utils/login_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/utils.dart';
@@ -152,7 +154,7 @@ class GrpcRepo {
'x-bili-exps-bin': '',
};
static final unprintableRegExp = RegExp(r"[^\u4e00-\u9fa5UP]");
static final _unprintableRegExp = RegExp(r"[^\u4e00-\u9fa5UP]");
static Uint8List compressProtobuf(Uint8List proto) {
proto = const GZipEncoder().encodeBytes(proto);
@@ -173,15 +175,14 @@ class GrpcRepo {
}
}
static Future<Map<String, dynamic>> request(
url, GeneratedMessage request, Function grpcParser,
{Function? onSuccess}) async {
static Future<LoadingState<T>> request<T>(String url,
GeneratedMessage request, T Function(Uint8List) grpcParser) async {
final response = await Request().post(HttpString.appBaseUrl + url,
data: compressProtobuf(request.writeToBuffer()),
options: Options(headers: headers, responseType: ResponseType.bytes));
if (response.data is Map) {
return {'status': false, 'msg': response.data['message']};
return LoadingState.error(response.data['message']);
}
if (response.headers.value('Grpc-Status') == '0') {
@@ -189,27 +190,32 @@ class GrpcRepo {
Uint8List data = response.data;
data = decompressProtobuf(data);
final grpcResponse = grpcParser(data);
return {
'status': true,
'data': onSuccess == null ? grpcResponse : onSuccess(grpcResponse),
};
return LoadingState.success(grpcResponse);
} catch (e) {
return {'status': false, 'msg': e.toString()};
return LoadingState.error(e.toString());
}
} else {
try {
String msg = response.headers.value('Grpc-Status-Details-Bin') ?? '';
if (msg != '') {
if (msg.isNotEmpty) {
while (msg.length % 4 != 0) {
msg += '=';
}
msg = utf8
.decode(base64Decode(msg), allowMalformed: true)
.replaceAll(unprintableRegExp, '');
final msgBytes = base64Decode(msg);
try {
final grpcMsg = Status.fromBuffer(msgBytes);
// UNKNOWN : -400 : msg
msg =
'${grpcMsg.code} : ${grpcMsg.message} : ${grpcMsg.details.firstOrNull?.status.message}';
} catch (e) {
msg = utf8
.decode(msgBytes, allowMalformed: true)
.replaceAll(_unprintableRegExp, '');
}
}
return {'status': false, 'msg': msg};
return LoadingState.error(msg);
} catch (e) {
return {'status': false, 'msg': e.toString()};
return LoadingState.error(e.toString());
}
}
}

View File

@@ -8,13 +8,12 @@ import 'package:protobuf/protobuf.dart' show PbMap;
import 'package:uuid/uuid.dart';
class ImGrpc {
static Future sendMsg({
static Future<LoadingState<RspSendMsg>> sendMsg({
required int senderUid,
required int receiverId,
required String content,
MsgType msgType = MsgType.EN_MSG_TYPE_TEXT,
}) {
final devId = const Uuid().v4();
return GrpcRepo.request(
GrpcUrl.sendMsg,
ReqSendMsg(
@@ -28,13 +27,13 @@ class ImGrpc {
msgStatus: 0,
newFaceVersion: 1,
),
devId: devId,
devId: const Uuid().v4(),
),
RspSendMsg.fromBuffer,
);
}
static Future shareList({int size = 10}) {
static Future<LoadingState<RspShareList>> shareList({int size = 10}) {
return GrpcRepo.request(
GrpcUrl.shareList,
ReqShareList(size: size),
@@ -42,28 +41,22 @@ class ImGrpc {
);
}
static Future<LoadingState<SessionMainReply>> sessionMain({
PbMap<int, Offset>? offset,
}) async {
final res = await GrpcRepo.request(
static Future<LoadingState<SessionMainReply>> sessionMain(
{PbMap<int, Offset>? offset}) {
return GrpcRepo.request(
GrpcUrl.sessionMain,
SessionMainReq(
paginationParams: PaginationParams(offsets: offset),
),
SessionMainReply.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return LoadingState.error(res['msg']);
}
}
static Future<LoadingState<SessionSecondaryReply>> sessionSecondary({
PbMap<int, Offset>? offset,
SessionPageType? pageType,
}) async {
final res = await GrpcRepo.request(
}) {
return GrpcRepo.request(
GrpcUrl.sessionSecondary,
SessionSecondaryReq(
paginationParams: PaginationParams(offsets: offset),
@@ -71,14 +64,9 @@ class ImGrpc {
),
SessionSecondaryReply.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return LoadingState.error(res['msg']);
}
}
static Future clearUnread({
static Future<LoadingState<ClearUnreadReply>> clearUnread({
SessionPageType? pageType,
SessionId? sessionId,
}) {
@@ -92,7 +80,7 @@ class ImGrpc {
);
}
static Future sessionUpdate({
static Future<LoadingState<SessionUpdateReply>> sessionUpdate({
SessionPageType? pageType,
SessionId? sessionId,
}) {
@@ -106,7 +94,7 @@ class ImGrpc {
);
}
static Future pinSession({
static Future<LoadingState<PinSessionReply>> pinSession({
SessionId? sessionId,
Int64? topTimeMicros,
}) {
@@ -120,7 +108,7 @@ class ImGrpc {
);
}
static Future unpinSession({
static Future<LoadingState<UnPinSessionReply>> unpinSession({
SessionId? sessionId,
}) {
return GrpcRepo.request(
@@ -132,7 +120,7 @@ class ImGrpc {
);
}
static Future deleteSessionList({
static Future<LoadingState<DeleteSessionListReply>> deleteSessionList({
SessionPageType? pageType,
}) {
return GrpcRepo.request(
@@ -145,22 +133,18 @@ class ImGrpc {
}
static Future<LoadingState<GetImSettingsReply>> getImSettings(
{IMSettingType? type}) async {
var res = await GrpcRepo.request(
{IMSettingType? type}) {
return GrpcRepo.request(
GrpcUrl.getImSettings,
GetImSettingsReq(
type: type,
),
GetImSettingsReply.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return LoadingState.error(res['msg']);
}
}
static Future setImSettings({PbMap<int, Setting>? settings}) {
static Future<LoadingState<SetImSettingsReply>> setImSettings(
{PbMap<int, Setting>? settings}) {
return GrpcRepo.request(
GrpcUrl.setImSettings,
SetImSettingsReq(
@@ -170,21 +154,16 @@ class ImGrpc {
);
}
static Future<LoadingState<KeywordBlockingListReply>>
keywordBlockingList() async {
var res = await GrpcRepo.request(
static Future<LoadingState<KeywordBlockingListReply>> keywordBlockingList() {
return GrpcRepo.request(
GrpcUrl.keywordBlockingList,
KeywordBlockingListReq(),
KeywordBlockingListReply.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return LoadingState.error(res['msg']);
}
}
static Future keywordBlockingAdd(String keyword) {
static Future<LoadingState<KeywordBlockingAddReply>> keywordBlockingAdd(
String keyword) {
return GrpcRepo.request(
GrpcUrl.keywordBlockingAdd,
KeywordBlockingAddReq(keyword: keyword),
@@ -192,7 +171,8 @@ class ImGrpc {
);
}
static Future keywordBlockingDelete(String keyword) {
static Future<LoadingState<KeywordBlockingDeleteReply>> keywordBlockingDelete(
String keyword) {
return GrpcRepo.request(
GrpcUrl.keywordBlockingDelete,
KeywordBlockingDeleteReq(keyword: keyword),

View File

@@ -17,18 +17,21 @@ class ReplyGrpc {
// }
// ref BiliRoamingX
static bool needRemoveGrpc(ReplyInfo reply) {
if ((reply.content.urls.isNotEmpty &&
static bool needRemoveGoodGrpc(ReplyInfo reply) {
return (reply.content.urls.isNotEmpty &&
reply.content.urls.values.any((url) {
return url.hasExtra() &&
(url.extra.goodsCmControl == 1 ||
url.extra.goodsItemId != 0 ||
(url.extra.goodsCmControl == Int64.ONE ||
url.extra.goodsItemId != Int64.ZERO ||
url.extra.goodsPrefetchedCache.isNotEmpty);
})) ||
reply.content.message.contains(Constants.goodsUrlPrefix)) {
return true;
}
return false;
reply.content.message.contains(Constants.goodsUrlPrefix);
}
static bool needRemoveGrpc(ReplyInfo reply, final bool antiGoodsReply) {
return (ReplyHttp.replyRegExp.pattern.isNotEmpty &&
ReplyHttp.replyRegExp.hasMatch(reply.content.message)) ||
(antiGoodsReply && needRemoveGoodGrpc(reply));
}
static Future<LoadingState<MainListReply>> mainList({
@@ -37,14 +40,14 @@ class ReplyGrpc {
required Mode mode,
required String? offset,
required Int64? cursorNext,
required bool antiGoodsReply,
required final bool antiGoodsReply,
}) async {
dynamic res = await GrpcRepo.request(
final res = await GrpcRepo.request(
GrpcUrl.mainList,
MainListReq(
oid: Int64(oid),
type: Int64(type),
rpid: Int64(0),
rpid: Int64.ZERO,
cursor: CursorReq(
mode: mode,
next: cursorNext,
@@ -53,59 +56,25 @@ class ReplyGrpc {
),
MainListReply.fromBuffer,
);
if (res['status']) {
MainListReply mainListReply = res['data'];
if (res.isSuccess) {
final mainListReply = res.data;
// keyword filter
if (ReplyHttp.replyRegExp.pattern.isNotEmpty) {
// upTop
if (mainListReply.hasUpTop() &&
ReplyHttp.replyRegExp
.hasMatch(mainListReply.upTop.content.message)) {
mainListReply.clearUpTop();
}
// replies
if (mainListReply.replies.isNotEmpty) {
mainListReply.replies.removeWhere((item) {
bool hasMatch =
ReplyHttp.replyRegExp.hasMatch(item.content.message);
// remove subreplies
if (!hasMatch) {
if (item.replies.isNotEmpty) {
item.replies.removeWhere((item) =>
ReplyHttp.replyRegExp.hasMatch(item.content.message));
}
}
return hasMatch;
});
}
if (mainListReply.hasUpTop() &&
needRemoveGrpc(mainListReply.upTop, antiGoodsReply)) {
mainListReply.clearUpTop();
}
// antiGoodsReply
if (antiGoodsReply) {
// upTop
if (mainListReply.hasUpTop() && needRemoveGrpc(mainListReply.upTop)) {
mainListReply.clearUpTop();
}
// replies
if (mainListReply.replies.isNotEmpty) {
mainListReply.replies.removeWhere((item) {
bool hasMatch = needRemoveGrpc(item);
// remove subreplies
if (!hasMatch) {
if (item.replies.isNotEmpty) {
item.replies.removeWhere(needRemoveGrpc);
}
}
return hasMatch;
});
}
if (mainListReply.replies.isNotEmpty) {
mainListReply.replies.removeWhere((item) {
final hasMatch = needRemoveGrpc(item, antiGoodsReply);
if (!hasMatch && item.replies.isNotEmpty) {
item.replies.removeWhere((i) => needRemoveGrpc(i, antiGoodsReply));
}
return hasMatch;
});
}
return LoadingState.success(mainListReply);
} else {
return LoadingState.error(res['msg']);
}
return res;
}
static Future<LoadingState<DetailListReply>> detailList({
@@ -115,9 +84,9 @@ class ReplyGrpc {
required int rpid,
required Mode mode,
required String? offset,
required bool antiGoodsReply,
required final bool antiGoodsReply,
}) async {
dynamic res = await GrpcRepo.request(
final res = await GrpcRepo.request(
GrpcUrl.detailList,
DetailListReq(
oid: Int64(oid),
@@ -130,23 +99,11 @@ class ReplyGrpc {
),
DetailListReply.fromBuffer,
);
if (res['status']) {
DetailListReply detailListReply = res['data'];
if (ReplyHttp.replyRegExp.pattern.isNotEmpty) {
if (detailListReply.root.replies.isNotEmpty) {
detailListReply.root.replies.removeWhere(
(item) => ReplyHttp.replyRegExp.hasMatch(item.content.message));
}
}
if (antiGoodsReply) {
if (detailListReply.root.replies.isNotEmpty) {
detailListReply.root.replies.removeWhere(needRemoveGrpc);
}
}
return LoadingState.success(detailListReply);
} else {
return LoadingState.error(res['msg']);
}
return res
..dataOrNull
?.root
.replies
.removeWhere((item) => needRemoveGrpc(item, antiGoodsReply));
}
static Future<LoadingState<DialogListReply>> dialogList({
@@ -155,9 +112,9 @@ class ReplyGrpc {
required int root,
required int dialog,
required String? offset,
required bool antiGoodsReply,
required final bool antiGoodsReply,
}) async {
dynamic res = await GrpcRepo.request(
final res = await GrpcRepo.request(
GrpcUrl.dialogList,
DialogListReq(
oid: Int64(oid),
@@ -168,22 +125,9 @@ class ReplyGrpc {
),
DialogListReply.fromBuffer,
);
if (res['status']) {
DialogListReply dialogListReply = res['data'];
if (ReplyHttp.replyRegExp.pattern.isNotEmpty) {
if (dialogListReply.replies.isNotEmpty) {
dialogListReply.replies.removeWhere(
(item) => ReplyHttp.replyRegExp.hasMatch(item.content.message));
}
}
if (antiGoodsReply) {
if (dialogListReply.replies.isNotEmpty) {
dialogListReply.replies.removeWhere(needRemoveGrpc);
}
}
return LoadingState.success(dialogListReply);
} else {
return LoadingState.error(res['msg']);
}
return res
..dataOrNull
?.replies
.removeWhere((item) => needRemoveGrpc(item, antiGoodsReply));
}
}

View File

@@ -9,8 +9,8 @@ class SpaceGrpc {
required int hostMid,
String? next,
required String filterType,
}) async {
final res = await GrpcRepo.request(
}) {
return GrpcRepo.request(
GrpcUrl.opusSpaceFlow,
OpusSpaceFlowReq(
hostMid: Int64(hostMid),
@@ -22,10 +22,5 @@ class SpaceGrpc {
),
OpusSpaceFlowResp.fromBuffer,
);
if (res['status']) {
return LoadingState.success(res['data']);
} else {
return LoadingState.error(res['msg']);
}
}
}

View File

@@ -187,73 +187,75 @@ class Request {
/*
* get请求
*/
Future<Response> get(url,
{queryParameters, options, cancelToken, extra}) async {
Response response;
if (extra != null) {
if (extra['ua'] != null) {
options ??= Options();
options.headers ??= <String, dynamic>{};
options.headers!['user-agent'] = headerUa(type: extra['ua']);
}
Future<Response> get<T>(
String url, {
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
String? uaType,
}) async {
if (uaType != null) {
options ??= Options();
options.headers ??= <String, dynamic>{};
options.headers!['user-agent'] = headerUa(type: uaType);
}
try {
response = await dio.get(
return await dio.get<T>(
url,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
);
return response;
} on DioException catch (e) {
Response errResponse = Response(
return Response(
data: {
'message': await AccountManager.dioError(e)
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
statusCode: e.response?.statusCode ?? -1,
requestOptions: RequestOptions(),
requestOptions: e.requestOptions,
);
return errResponse;
}
}
/*
* post请求
*/
Future<Response> post(url,
{data, queryParameters, options, cancelToken}) async {
Future<Response> post<T>(
String url, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
}) async {
// debugPrint('post-data: $data');
Response response;
try {
response = await dio.post(
return await dio.post<T>(
url,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
);
// debugPrint('post success: ${response.data}');
return response;
} on DioException catch (e) {
AccountManager.toast(e);
Response errResponse = Response(
return Response(
data: {
'message': await AccountManager.dioError(e)
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
statusCode: e.response?.statusCode ?? -1,
requestOptions: RequestOptions(),
requestOptions: e.requestOptions,
);
return errResponse;
}
}
/*
* 下载文件
*/
Future<Response> downloadFile(urlPath, savePath, {cancelToken}) async {
Future<Response> downloadFile(String urlPath, String savePath,
{CancelToken? cancelToken}) async {
try {
Response response = await dio.download(
final response = await dio.download(
urlPath,
savePath,
cancelToken: cancelToken,
@@ -271,7 +273,7 @@ class Request {
'message': await AccountManager.dioError(e),
},
statusCode: e.response?.statusCode ?? -1,
requestOptions: RequestOptions(),
requestOptions: e.requestOptions,
);
}
}
@@ -286,7 +288,7 @@ class Request {
token.cancel("cancelled");
}
static String headerUa({type = 'mob'}) {
static String headerUa({String type = 'mob'}) {
return switch (type) {
'mob' =>
'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36',

View File

@@ -1,5 +1,7 @@
import 'dart:core' hide Error;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
sealed class LoadingState<T> {
const LoadingState();
@@ -11,14 +13,15 @@ sealed class LoadingState<T> {
T get data => switch (this) {
Success(response: final res) => res,
Error() => throw this,
Loading() => throw Exception('ApiException: loading'),
_ => throw this,
};
T? get dataOrNull => switch (this) {
Success(response: final res) => res,
_ => null,
};
void toast() => SmartDialog.showToast(toString());
}
class Loading extends LoadingState<Never> {
@@ -27,6 +30,11 @@ class Loading extends LoadingState<Never> {
static const Loading _instance = Loading._internal();
factory Loading() => _instance;
@override
String toString() {
return 'ApiException: loading';
}
}
class Success<T> extends LoadingState<T> {

View File

@@ -266,7 +266,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'mid': mid,
'token': token,
'platform': 'web',
@@ -332,7 +332,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'mid': mid,
'ps': ps,
'tid': tid,
@@ -383,7 +383,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'mid': mid,
'ps': ps,
'tid': tid,
@@ -426,7 +426,7 @@ class MemberHttp {
}) async {
String dmImgStr = Utils.base64EncodeRandomString(16, 64);
String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128);
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'offset': offset ?? '',
'host_mid': mid,
'timezone_offset': '-480',

View File

@@ -457,7 +457,7 @@ class MsgHttp {
beginSeqno,
endSeqno,
}) async {
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'size': 20,
@@ -486,7 +486,7 @@ class MsgHttp {
int? ackSeqno,
}) async {
String csrf = Accounts.main.csrf;
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'talker_id': talkerId,
'session_type': 1,
'ack_seqno': ackSeqno,

View File

@@ -182,7 +182,7 @@ class VideoHttp {
dynamic seasonId,
bool? forcePgcApi,
}) async {
Map<String, dynamic> data = {
final params = await WbiSign.makSign({
if (avid != null) 'avid': avid,
if (bvid != null) 'bvid': bvid,
if (epid != null) 'ep_id': epid,
@@ -197,15 +197,11 @@ class VideoHttp {
'gaia_source': 'pre-load',
'isGaiaAvoided': true,
'web_location': 1315873,
};
// 免登录查看1080p
if (!Accounts.get(AccountType.video).isLogin &&
GStorage.setting.get(SettingBoxKey.p1080, defaultValue: true)) {
data['try_look'] = 1;
}
Map params = await WbiSign.makSign(data);
// 免登录查看1080p
if (!Accounts.get(AccountType.video).isLogin &&
GStorage.setting.get(SettingBoxKey.p1080, defaultValue: true))
'try_look': 1,
});
late final usePgcApi =
forcePgcApi == true || Accounts.get(AccountType.video).isLogin;
@@ -880,7 +876,7 @@ class VideoHttp {
int? cid,
int? upMid,
}) async {
Map params = await WbiSign.makSign({
final params = await WbiSign.makSign({
'bvid': bvid,
'cid': cid,
'up_mid': upMid,

View File

@@ -26,7 +26,7 @@ abstract class CommonWhisperController<R>
? await ImGrpc.unpinSession(sessionId: sessionId)
: await ImGrpc.pinSession(sessionId: sessionId);
if (res['status']) {
if (res.isSuccess) {
List<Session> list = loadingState.value.data!;
list[index].isPinned = isTop ? false : true;
if (!isTop) {
@@ -35,14 +35,14 @@ abstract class CommonWhisperController<R>
loadingState.refresh();
SmartDialog.showToast('${isTop ? '移除' : ''}置顶成功');
} else {
SmartDialog.showToast(res['msg']);
res.toast();
}
}
Future<void> onClearUnread() async {
final res = await ImGrpc.clearUnread(pageType: sessionPageType);
if (res['status']) {
if (loadingState.value is Success) {
if (res.isSuccess) {
if (loadingState.value.isSuccess) {
List<Session>? list = loadingState.value.data;
if (list?.isNotEmpty == true) {
for (var item in list!) {
@@ -55,16 +55,16 @@ abstract class CommonWhisperController<R>
}
SmartDialog.showToast('已标记为已读');
} else {
SmartDialog.showToast(res['msg']);
res.toast();
}
}
Future<void> onDeleteList() async {
var res = await ImGrpc.deleteSessionList(pageType: sessionPageType);
if (res['status']) {
if (res.isSuccess) {
loadingState.value = LoadingState.success(null);
} else {
SmartDialog.showToast(res['msg']);
res.toast();
}
}
}

View File

@@ -176,8 +176,8 @@ class MainController extends GetxController {
return;
}
DynGrpc.dynRed().then((res) {
if (res['status']) {
setCount(res['data']);
if (res != null) {
setCount(res);
}
});
}

View File

@@ -30,8 +30,8 @@ class WhisperBlockController extends CommonListController<
ImGrpc.keywordBlockingList();
Future<void> onAdd(String keyword) async {
var res = await ImGrpc.keywordBlockingAdd(keyword);
if (res['status']) {
final res = await ImGrpc.keywordBlockingAdd(keyword);
if (res.isSuccess) {
Get.back();
loadingState
..value.data!.add(KeywordBlockingItem(keyword: keyword))
@@ -39,20 +39,20 @@ class WhisperBlockController extends CommonListController<
count.value += 1;
SmartDialog.showToast('添加成功');
} else {
SmartDialog.showToast(res['msg']);
res.toast();
}
}
Future<void> onRemove(KeywordBlockingItem item) async {
var res = await ImGrpc.keywordBlockingDelete(item.keyword);
if (res['status']) {
final res = await ImGrpc.keywordBlockingDelete(item.keyword);
if (res.isSuccess) {
loadingState
..value.data!.remove(item)
..refresh();
count.value -= 1;
SmartDialog.showToast('删除成功');
} else {
SmartDialog.showToast(res['msg']);
res.toast();
}
}
}

View File

@@ -3,7 +3,6 @@ import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart'
import 'package:PiliPlus/grpc/im.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/pages/common/common_data_controller.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:protobuf/protobuf.dart' show PbMap;
@@ -36,10 +35,10 @@ class WhisperSettingsController
ImGrpc.getImSettings(type: imSettingType);
Future<bool> onSet(PbMap<int, Setting> settings) async {
var res = await ImGrpc.setImSettings(settings: settings);
if (!res['status']) {
SmartDialog.showToast('err: ${res['msg']}');
final res = await ImGrpc.setImSettings(settings: settings);
if (!res.isSuccess) {
res.toast();
}
return res['status'];
return res.isSuccess;
}
}

View File

@@ -37,9 +37,8 @@ class PageUtils {
List<UserModel> userList = <UserModel>[];
final shareListRes = await ImGrpc.shareList(size: 3);
if (shareListRes['status'] && shareListRes['data'].sessionList.isNotEmpty) {
userList.addAll(shareListRes['data']
.sessionList
if (shareListRes.isSuccess && shareListRes.data.sessionList.isNotEmpty) {
userList.addAll(shareListRes.data.sessionList
.map<UserModel>((item) => UserModel(
mid: item.talkerId.toInt(),
name: item.talkerUname,

View File

@@ -62,7 +62,7 @@ class RequestUtils {
: MsgType.EN_MSG_TYPE_SHARE_V2,
);
if (contentRes['status']) {
if (contentRes.isSuccess) {
if (message?.isNotEmpty == true) {
var msgRes = await MsgHttp.sendMsg(
senderUid: ownerMid,
@@ -81,7 +81,7 @@ class RequestUtils {
SmartDialog.showToast('分享成功');
}
} else {
SmartDialog.showToast('分享失败: ${contentRes['msg']}');
SmartDialog.showToast('分享失败: ${(contentRes as Error).errMsg}');
}
SmartDialog.dismiss();
}

View File

@@ -500,8 +500,8 @@ class Utils {
if (BuildConfig.isDebug) return;
SmartDialog.dismiss();
try {
dynamic res = await Request().get(Api.latestApp, extra: {'ua': 'mob'});
if (res.data.isEmpty) {
final res = await Request().get(Api.latestApp, uaType: 'mob');
if (res.data is Map || res.data.isEmpty) {
if (isAuto.not) {
SmartDialog.showToast('检查更新失败GitHub接口未返回数据请检查网络');
}