Skip to content

Commit

Permalink
MediaListFilterContext: 增加剧集 ep 和名称判定, 进而增加匹配准确性
Browse files Browse the repository at this point in the history
  • Loading branch information
Him188 committed Sep 28, 2024
1 parent f65cb06 commit 0524930
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ import me.him188.ani.datasources.api.EpisodeSort
open class MediaListFilterContext(
val subjectNames: Set<String>, // faster
val episodeSort: EpisodeSort,
val episodeEp: EpisodeSort?,
val episodeName: String?,
) {
val subjectNamesWithoutSpecial: Set<String> by lazy {
subjectNames.mapTo(HashSet(subjectNames.size)) {
it.replace(MediaListFilters.specialCharRegex, "")
}
}
val episodeNameWithoutSpecial: String? by lazy {
episodeName?.replace(MediaListFilters.specialCharRegex, "")
}

/**
* 返回 `true` 表示该 [Candidate] 符合过滤条件.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import me.him188.ani.datasources.api.topic.contains
*/
object MediaListFilters {
val specialCharRegex = Regex("""[ ~!@#$%^&*()_+{}\[\]\\|;':",.<>/?【】]""")

val ContainsSubjectName = BasicMediaListFilter { media ->
subjectNamesWithoutSpecial.any { subjectName ->
media.originalTitle.replace(specialCharRegex, "")
Expand All @@ -30,4 +30,17 @@ object MediaListFilters {
val range = media.episodeRange ?: return@BasicMediaListFilter false
range.contains(episodeSort)
}
val ContainsEpisodeEp = BasicMediaListFilter { media ->
val range = media.episodeRange ?: return@BasicMediaListFilter false
episodeEp != null && range.contains(episodeEp)
}
val ContainsEpisodeName = BasicMediaListFilter { media ->
episodeName ?: return@BasicMediaListFilter false
val name = episodeNameWithoutSpecial
checkNotNull(name)
if (name.isBlank()) return@BasicMediaListFilter false
media.originalTitle.replace(specialCharRegex, "").contains(name)
}

val ContainsAnyEpisodeInfo = ContainsEpisodeSort or ContainsEpisodeName or ContainsEpisodeEp
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ class RssMediaSource(
subjectName = name,
episodeSort = query.episodeSort,
allSubjectNames = query.subjectNames,
episodeEp = query.episodeEp,
episodeName = query.episodeName,
),
).map {
MediaMatch(it, MatchKind.FUZZY)
Expand All @@ -178,9 +180,13 @@ data class RssSearchQuery(
val subjectName: String,
val allSubjectNames: Set<String>,
val episodeSort: EpisodeSort,
val episodeEp: EpisodeSort?,
val episodeName: String?,
)

fun RssSearchQuery.toFilterContext() = MediaListFilterContext(
subjectNames = allSubjectNames,
episodeSort = episodeSort,
episodeEp = episodeSort,
episodeName = episodeName,
)
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ data class RssSearchConfig(
*/
fun RssSearchConfig.createFilters() = buildList {
if (filterBySubjectName) add(MediaListFilters.ContainsSubjectName)
if (filterByEpisodeSort) add(MediaListFilters.ContainsEpisodeSort)
if (filterByEpisodeSort) add(MediaListFilters.ContainsAnyEpisodeInfo)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ class SelectorMediaSource(
subjectName = name,
episodeSort = query.episodeSort,
allSubjectNames = query.subjectNames,
episodeEp = query.episodeEp,
episodeName = query.episodeName,
),
mediaSourceId,
).getOrThrow().asFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@ data class SelectorSearchQuery(
val subjectName: String,
val allSubjectNames: Set<String>,
val episodeSort: EpisodeSort,
val episodeEp: EpisodeSort?,
val episodeName: String?,
)

fun SelectorSearchQuery.toFilterContext() = MediaListFilterContext(
subjectNames = allSubjectNames,
episodeSort = episodeSort,
episodeEp = episodeEp,
episodeName = episodeName,
)

/**
Expand Down Expand Up @@ -300,7 +304,7 @@ internal fun SelectorSearchConfig.createFiltersForSubject() = buildList {

internal fun SelectorSearchConfig.createFiltersForEpisode() = buildList {
// 不使用 filterBySubjectName, 因为 web 的剧集名称通常为 "第x集", 不包含 subject
if (filterByEpisodeSort) add(MediaListFilters.ContainsEpisodeSort)
if (filterByEpisodeSort) add(MediaListFilters.ContainsAnyEpisodeInfo)
}

class DefaultSelectorMediaSourceEngine(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* Copyright (C) 2024 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

@file:Suppress("unused", "UNUSED_VARIABLE")

package me.him188.ani.app.data.source.media.source
Expand All @@ -16,10 +25,14 @@ fun applyingFilters(mediaList: List<Media>) {
if (enableFilterBySubjectName) {
add(MediaListFilters.ContainsSubjectName)
}
add(MediaListFilters.ContainsEpisodeSort)
add(MediaListFilters.ContainsAnyEpisodeInfo)
}

val newList: List<Media> = with(MediaListFilterContext(setOf("条目名称"), EpisodeSort(1))) {
val context = MediaListFilterContext(
setOf("条目名称"), EpisodeSort(1), EpisodeSort(1),
"第1集",
)
val newList: List<Media> = with(context) {
mediaList.filter { media ->
filters.applyOn(media.asCandidate())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class RssItemPresentation(
} else {
emit(
episodeRange.toString(),
isMatch = MediaListFilters.ContainsEpisodeSort.applyOn(candidate),
isMatch = MediaListFilters.ContainsAnyEpisodeInfo.applyOn(candidate),
)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class RssTestPaneState(
subjectName = testData.keyword,
episodeSort = EpisodeSort(sort),
allSubjectNames = setOf(testData.keyword),
episodeName = null,
episodeEp = null,
)
viewingItem = null
launchRequestInBackground {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class SelectorTestState(
subjectName = searchKeyword,
episodeSort = EpisodeSort(sort),
allSubjectNames = setOf(searchKeyword),
episodeName = null,
episodeEp = null,
)
}
}
Expand Down

0 comments on commit 0524930

Please sign in to comment.