mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: filter reply
Closes #118 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
||||||
import 'package:PiliPlus/grpc/grpc_repo.dart';
|
import 'package:PiliPlus/grpc/grpc_repo.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
@@ -49,7 +50,44 @@ class ReplyHttp {
|
|||||||
options: options,
|
options: options,
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return LoadingState.success(ReplyData.fromJson(res.data['data']));
|
ReplyData replyData = ReplyData.fromJson(res.data['data']);
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
if (banWordForReply.isNotEmpty) {
|
||||||
|
// topReplies
|
||||||
|
if (replyData.topReplies?.isNotEmpty == true) {
|
||||||
|
replyData.topReplies!.removeWhere((item) {
|
||||||
|
bool hasMatch = RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content?.message ?? '');
|
||||||
|
// remove subreplies
|
||||||
|
if (hasMatch.not) {
|
||||||
|
if (item.replies?.isNotEmpty == true) {
|
||||||
|
item.replies!.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content?.message ?? ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasMatch;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// replies
|
||||||
|
if (replyData.replies?.isNotEmpty == true) {
|
||||||
|
replyData.replies!.removeWhere((item) {
|
||||||
|
bool hasMatch = RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content?.message ?? '');
|
||||||
|
// remove subreplies
|
||||||
|
if (hasMatch.not) {
|
||||||
|
if (item.replies?.isNotEmpty == true) {
|
||||||
|
item.replies!.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content?.message ?? ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasMatch;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LoadingState.success(replyData);
|
||||||
} else {
|
} else {
|
||||||
return LoadingState.error(res.data['message']);
|
return LoadingState.error(res.data['message']);
|
||||||
}
|
}
|
||||||
@@ -62,7 +100,33 @@ class ReplyHttp {
|
|||||||
}) async {
|
}) async {
|
||||||
dynamic res = await GrpcRepo.mainList(type: type, oid: oid, cursor: cursor);
|
dynamic res = await GrpcRepo.mainList(type: type, oid: oid, cursor: cursor);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
return LoadingState.success(res['data']);
|
MainListReply mainListReply = res['data'];
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
if (banWordForReply.isNotEmpty) {
|
||||||
|
// upTop
|
||||||
|
if (mainListReply.hasUpTop() &&
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(mainListReply.upTop.content.message)) {
|
||||||
|
mainListReply.clearUpTop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// replies
|
||||||
|
if (mainListReply.replies.isNotEmpty) {
|
||||||
|
mainListReply.replies.removeWhere((item) {
|
||||||
|
bool hasMatch = RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content.message);
|
||||||
|
// remove subreplies
|
||||||
|
if (hasMatch.not) {
|
||||||
|
if (item.replies.isNotEmpty) {
|
||||||
|
item.replies.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasMatch;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return LoadingState.success(mainListReply);
|
||||||
} else {
|
} else {
|
||||||
return LoadingState.error(
|
return LoadingState.error(
|
||||||
'${res['msg'].startsWith('gRPC Error') ? '如无法加载评论:\n关闭代理\n或设置中关闭使用gRPC加载评论\n\n' : ''}${res['msg']}');
|
'${res['msg'].startsWith('gRPC Error') ? '如无法加载评论:\n关闭代理\n或设置中关闭使用gRPC加载评论\n\n' : ''}${res['msg']}');
|
||||||
@@ -93,33 +157,21 @@ class ReplyHttp {
|
|||||||
options: options,
|
options: options,
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return LoadingState.success(ReplyReplyData.fromJson(res.data['data']));
|
ReplyReplyData replyData = ReplyReplyData.fromJson(res.data['data']);
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
if (banWordForReply.isNotEmpty) {
|
||||||
|
if (replyData.replies?.isNotEmpty == true) {
|
||||||
|
replyData.replies!.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content?.message ?? ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LoadingState.success(replyData);
|
||||||
} else {
|
} else {
|
||||||
return LoadingState.error(res.data['message']);
|
return LoadingState.error(res.data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<LoadingState> dialogListGrpc({
|
|
||||||
int type = 1,
|
|
||||||
required int oid,
|
|
||||||
required int root,
|
|
||||||
required int rpid,
|
|
||||||
required CursorReq cursor,
|
|
||||||
}) async {
|
|
||||||
dynamic res = await GrpcRepo.dialogList(
|
|
||||||
type: type,
|
|
||||||
oid: oid,
|
|
||||||
root: root,
|
|
||||||
rpid: rpid,
|
|
||||||
cursor: cursor,
|
|
||||||
);
|
|
||||||
if (res['status']) {
|
|
||||||
return LoadingState.success(res['data']);
|
|
||||||
} else {
|
|
||||||
return LoadingState.error(res['msg']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<LoadingState> replyReplyListGrpc({
|
static Future<LoadingState> replyReplyListGrpc({
|
||||||
int type = 1,
|
int type = 1,
|
||||||
required int oid,
|
required int oid,
|
||||||
@@ -135,7 +187,46 @@ class ReplyHttp {
|
|||||||
cursor: cursor,
|
cursor: cursor,
|
||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
return LoadingState.success(res['data']);
|
DetailListReply detailListReply = res['data'];
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
if (banWordForReply.isNotEmpty) {
|
||||||
|
if (detailListReply.root.replies.isNotEmpty) {
|
||||||
|
detailListReply.root.replies.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LoadingState.success(detailListReply);
|
||||||
|
} else {
|
||||||
|
return LoadingState.error(res['msg']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<LoadingState> dialogListGrpc({
|
||||||
|
int type = 1,
|
||||||
|
required int oid,
|
||||||
|
required int root,
|
||||||
|
required int rpid,
|
||||||
|
required CursorReq cursor,
|
||||||
|
}) async {
|
||||||
|
dynamic res = await GrpcRepo.dialogList(
|
||||||
|
type: type,
|
||||||
|
oid: oid,
|
||||||
|
root: root,
|
||||||
|
rpid: rpid,
|
||||||
|
cursor: cursor,
|
||||||
|
);
|
||||||
|
if (res['status']) {
|
||||||
|
DialogListReply dialogListReply = res['data'];
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
if (banWordForReply.isNotEmpty) {
|
||||||
|
if (dialogListReply.replies.isNotEmpty) {
|
||||||
|
dialogListReply.replies.removeWhere((item) =>
|
||||||
|
RegExp(banWordForReply, caseSensitive: false)
|
||||||
|
.hasMatch(item.content.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LoadingState.success(dialogListReply);
|
||||||
} else {
|
} else {
|
||||||
return LoadingState.error(res['msg']);
|
return LoadingState.error(res['msg']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ class PlDanmakuController {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (RegExp(filter['filter']).hasMatch(elem.content)) {
|
if (RegExp(filter['filter'], caseSensitive: false)
|
||||||
|
.hasMatch(elem.content)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1155,8 +1155,7 @@ List<SettingsModel> get recommendSettings => [
|
|||||||
return banWordForRecommend.isEmpty ? "点击添加" : banWordForRecommend;
|
return banWordForRecommend.isEmpty ? "点击添加" : banWordForRecommend;
|
||||||
},
|
},
|
||||||
onTap: (setState) async {
|
onTap: (setState) async {
|
||||||
final TextEditingController textController =
|
String banWordForRecommend = GStorage.banWordForRecommend;
|
||||||
TextEditingController(text: GStorage.banWordForRecommend);
|
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: Get.context!,
|
context: Get.context!,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
@@ -1170,16 +1169,17 @@ List<SettingsModel> get recommendSettings => [
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('使用|隔开,如:尝试|测试'),
|
const Text('使用|隔开,如:尝试|测试'),
|
||||||
TextField(
|
TextFormField(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
controller: textController,
|
initialValue: banWordForRecommend,
|
||||||
textInputAction: TextInputAction.newline,
|
textInputAction: TextInputAction.newline,
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
|
onChanged: (value) => banWordForRecommend = value,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: Get.back,
|
onPressed: Get.back,
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -1192,9 +1192,9 @@ List<SettingsModel> get recommendSettings => [
|
|||||||
child: const Text('保存'),
|
child: const Text('保存'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Get.back();
|
Get.back();
|
||||||
GStorage.setting.put(
|
await GStorage.setting.put(
|
||||||
SettingBoxKey.banWordForRecommend,
|
SettingBoxKey.banWordForRecommend,
|
||||||
textController.text,
|
banWordForRecommend,
|
||||||
);
|
);
|
||||||
setState();
|
setState();
|
||||||
RecommendFilter.update();
|
RecommendFilter.update();
|
||||||
@@ -1662,6 +1662,66 @@ List<SettingsModel> get extraSettings => [
|
|||||||
setKey: SettingBoxKey.horizontalPreview,
|
setKey: SettingBoxKey.horizontalPreview,
|
||||||
defaultVal: false,
|
defaultVal: false,
|
||||||
),
|
),
|
||||||
|
SettingsModel(
|
||||||
|
settingsType: SettingsType.normal,
|
||||||
|
leading: const Icon(Icons.filter_alt_outlined),
|
||||||
|
title: '评论关键词过滤',
|
||||||
|
getSubtitle: () {
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
return banWordForReply.isEmpty ? "点击添加" : banWordForReply;
|
||||||
|
},
|
||||||
|
onTap: (setState) async {
|
||||||
|
String banWordForReply = GStorage.banWordForReply;
|
||||||
|
await showDialog(
|
||||||
|
context: Get.context!,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text(
|
||||||
|
'评论关键词过滤',
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('使用|隔开,如:尝试|测试'),
|
||||||
|
TextFormField(
|
||||||
|
autofocus: true,
|
||||||
|
initialValue: banWordForReply,
|
||||||
|
textInputAction: TextInputAction.newline,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: 4,
|
||||||
|
onChanged: (value) => banWordForReply = value,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: Get.back,
|
||||||
|
child: Text(
|
||||||
|
'取消',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('保存'),
|
||||||
|
onPressed: () async {
|
||||||
|
Get.back();
|
||||||
|
await GStorage.setting.put(
|
||||||
|
SettingBoxKey.banWordForReply,
|
||||||
|
banWordForReply,
|
||||||
|
);
|
||||||
|
setState();
|
||||||
|
SmartDialog.showToast('已保存');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
SettingsModel(
|
SettingsModel(
|
||||||
settingsType: SettingsType.sw1tch,
|
settingsType: SettingsType.sw1tch,
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ class RecommendFilter {
|
|||||||
if (exemptFilterForFollowed && isFollowed == true) {
|
if (exemptFilterForFollowed && isFollowed == true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (banWords.isNotEmpty && RegExp(banWords).hasMatch(title)) {
|
if (banWords.isNotEmpty &&
|
||||||
|
RegExp(banWords, caseSensitive: false).hasMatch(title)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ class GStorage {
|
|||||||
static String get banWordForRecommend =>
|
static String get banWordForRecommend =>
|
||||||
setting.get(SettingBoxKey.banWordForRecommend, defaultValue: '');
|
setting.get(SettingBoxKey.banWordForRecommend, defaultValue: '');
|
||||||
|
|
||||||
|
static String get banWordForReply =>
|
||||||
|
setting.get(SettingBoxKey.banWordForReply, defaultValue: '');
|
||||||
|
|
||||||
static int get minLikeRatioForRecommend =>
|
static int get minLikeRatioForRecommend =>
|
||||||
setting.get(SettingBoxKey.minLikeRatioForRecommend, defaultValue: 0);
|
setting.get(SettingBoxKey.minLikeRatioForRecommend, defaultValue: 0);
|
||||||
|
|
||||||
@@ -517,6 +520,7 @@ class SettingBoxKey {
|
|||||||
continuePlayingPart = 'continuePlayingPart',
|
continuePlayingPart = 'continuePlayingPart',
|
||||||
cdnSpeedTest = 'cdnSpeedTest',
|
cdnSpeedTest = 'cdnSpeedTest',
|
||||||
horizontalPreview = 'horizontalPreview',
|
horizontalPreview = 'horizontalPreview',
|
||||||
|
banWordForReply = 'banWordForReply',
|
||||||
|
|
||||||
// Sponsor Block
|
// Sponsor Block
|
||||||
enableSponsorBlock = 'enableSponsorBlock',
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
|||||||
Reference in New Issue
Block a user