generalize filtering logic

This commit is contained in:
sk
2023-05-26 02:07:50 +02:00
parent 220cd35d82
commit 99f0817bdb
17 changed files with 98 additions and 77 deletions

View File

@@ -8,51 +8,53 @@ import java.time.Instant;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StatusFilterPredicate implements Predicate<Status>{
private final List<Filter> filters;
private final Filter.FilterContext context;
private final Filter.FilterAction action;
public StatusFilterPredicate(List<Filter> filters){
public StatusFilterPredicate(List<Filter> filters, Filter.FilterContext context){
this.filters=filters;
this.context = context;
this.action = Filter.FilterAction.HIDE;
}
/**
* @param context null makes the predicate pass automatically
*/
public StatusFilterPredicate(String accountID, Filter.FilterContext context){
filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(context)).collect(Collectors.toList());
this(accountID, context, Filter.FilterAction.HIDE);
}
/**
* @param context null makes the predicate pass automatically
* @param action defines what the predicate should check:
* should not be hidden or should not display with warning
*/
public StatusFilterPredicate(String accountID, Filter.FilterContext context, Filter.FilterAction action){
filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(context)).collect(Collectors.toList());
this.context = context;
this.action = action;
}
// TODO: rewrite (see testHasStatusWarning) and generalize
@Override
public boolean test(Status status){
if(status.filtered!=null){
if (status.filtered.isEmpty()){
return true;
}
boolean matches=status.filtered.stream()
.map(filterResult->filterResult.filter)
.filter(filter->filter.expiresAt==null||filter.expiresAt.isAfter(Instant.now()))
.anyMatch(filter->filter.filterAction==Filter.FilterAction.HIDE);
return !matches;
}
for(Filter filter:filters){
if(filter.matches(status))
return false;
}
return true;
}
if (context == null) return true;
// TODO: move this method elsewhere; it's not part of the actual StatusFilterPredicate
public boolean testHasStatusWarning(Status status, Filter.FilterContext context) {
if (status.filtered != null) {
// use server-provided info on whether this status was filtered
if (status.filtered.isEmpty()) return false;
return status.filtered.stream()
.map(filterResult -> filterResult.filter)
.filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now()))
.filter(filter -> filter.context.contains(context))
.anyMatch(filter -> filter.filterAction == Filter.FilterAction.WARN);
} else {
// look through local filters instead
return filters.stream().anyMatch(filter -> filter.matches(status));
}
Stream<Filter> stream = status.filtered != null
// use server-provided per-status info (status.filtered) if available
? status.filtered.stream().map(f -> f.filter)
// or fall back to cached filters
: filters.stream().filter(filter -> filter.matches(status));
return stream
// discard expired filters
.filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now()))
// only apply filters for given context
.filter(filter -> filter.context.contains(context))
// treating filterAction = null (from filters list) as FilterAction.HIDE
.noneMatch(filter -> filter.filterAction == null ? action == Filter.FilterAction.HIDE : filter.filterAction == action);
}
}