import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'; import 'package:PiliPlus/grpc/bilibili/pagination.pb.dart'; import 'package:PiliPlus/grpc/grpc_req.dart'; import 'package:PiliPlus/grpc/url.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:fixnum/fixnum.dart'; class ReplyGrpc { static bool antiGoodsReply = Pref.antiGoodsReply; static RegExp replyRegExp = RegExp( Pref.banWordForReply, caseSensitive: false, ); static bool enableFilter = replyRegExp.pattern.isNotEmpty; // static Future replyInfo({required int rpid}) { // return _request( // GrpcUrl.replyInfo, // ReplyInfoReq(rpid: Int64(rpid)), // ReplyInfoReply.fromBuffer, // onSuccess: (response) => response.reply, // ); // } // ref BiliRoamingX static bool needRemoveGoodGrpc(ReplyInfo reply) { return (reply.content.urls.isNotEmpty && reply.content.urls.values.any((url) { return url.hasExtra() && (url.extra.goodsCmControl == Int64.ONE || url.extra.goodsItemId != Int64.ZERO || url.extra.goodsPrefetchedCache.isNotEmpty); })) || reply.content.message.contains(Constants.goodsUrlPrefix); } static bool needRemoveGrpc(ReplyInfo reply) { return (enableFilter && replyRegExp.hasMatch(reply.content.message)) || (antiGoodsReply && needRemoveGoodGrpc(reply)); } static Future> mainList({ int type = 1, required int oid, required Mode mode, required String? offset, required Int64? cursorNext, }) async { final res = await GrpcReq.request( GrpcUrl.mainList, MainListReq( oid: Int64(oid), type: Int64(type), rpid: Int64.ZERO, cursor: CursorReq( mode: mode, next: cursorNext, ), // pagination: FeedPagination(offset: offset ?? ''), ), MainListReply.fromBuffer, ); if (res.isSuccess) { final mainListReply = res.data; // keyword filter if (mainListReply.hasUpTop() && needRemoveGrpc(mainListReply.upTop)) { mainListReply.clearUpTop(); } if (mainListReply.replies.isNotEmpty) { mainListReply.replies.removeWhere((item) { final hasMatch = needRemoveGrpc(item); if (!hasMatch && item.replies.isNotEmpty) { item.replies.removeWhere((i) => needRemoveGrpc(i)); } return hasMatch; }); } } return res; } static Future> detailList({ int type = 1, required int oid, required int root, required int rpid, required Mode mode, required String? offset, }) async { final res = await GrpcReq.request( GrpcUrl.detailList, DetailListReq( oid: Int64(oid), type: Int64(type), root: Int64(root), rpid: Int64(rpid), scene: DetailListScene.REPLY, mode: mode, pagination: FeedPagination(offset: offset ?? ''), ), DetailListReply.fromBuffer, ); return res ..dataOrNull?.root.replies.removeWhere((item) => needRemoveGrpc(item)); } static Future> dialogList({ int type = 1, required int oid, required int root, required int dialog, required String? offset, }) async { final res = await GrpcReq.request( GrpcUrl.dialogList, DialogListReq( oid: Int64(oid), type: Int64(type), root: Int64(root), dialog: Int64(dialog), pagination: FeedPagination(offset: offset ?? ''), ), DialogListReply.fromBuffer, ); return res..dataOrNull?.replies.removeWhere((item) => needRemoveGrpc(item)); } static Future> searchItem({ required int page, required SearchItemType itemType, required int oid, int type = 1, String? keyword, }) { return GrpcReq.request( GrpcUrl.searchItem, SearchItemReq( cursor: SearchItemCursorReq( next: Int64(page), itemType: itemType, ), oid: Int64(oid), type: Int64(type), keyword: keyword, ), SearchItemReply.fromBuffer, ); } }