Merge pull request #3143 from vector-im/feature/bma/discovery_filtering
Filter some other words when navigating into the room directory
This commit is contained in:
commit
2d6fca9214
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.roomdirectory
|
||||||
|
|
||||||
|
import im.vector.app.InstrumentedTest
|
||||||
|
import im.vector.app.core.utils.AssetReader
|
||||||
|
import org.amshove.kluent.shouldBe
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
class ExplicitTermFilterTest : InstrumentedTest {
|
||||||
|
|
||||||
|
private val explicitTermFilter = ExplicitTermFilter(AssetReader(context()))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidEmptyTrue() {
|
||||||
|
explicitTermFilter.isValid("") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidTrue() {
|
||||||
|
explicitTermFilter.isValid("Hello") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidFalse() {
|
||||||
|
explicitTermFilter.isValid("nsfw") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidUpCaseFalse() {
|
||||||
|
explicitTermFilter.isValid("Nsfw") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidMultilineTrue() {
|
||||||
|
explicitTermFilter.isValid("Hello\nWorld") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidMultilineFalse() {
|
||||||
|
explicitTermFilter.isValid("Hello\nnsfw") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidMultilineFalse2() {
|
||||||
|
explicitTermFilter.isValid("nsfw\nHello") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidAnalFalse() {
|
||||||
|
explicitTermFilter.isValid("anal") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidAnal2False() {
|
||||||
|
explicitTermFilter.isValid("There is some anal in this room") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidAnalysisTrue() {
|
||||||
|
explicitTermFilter.isValid("analysis") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidAnalysis2True() {
|
||||||
|
explicitTermFilter.isValid("There is some analysis in the room") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidSpecialCharFalse() {
|
||||||
|
explicitTermFilter.isValid("18+") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidSpecialChar2False() {
|
||||||
|
explicitTermFilter.isValid("This is a room with 18+ content") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidOtherSpecialCharFalse() {
|
||||||
|
explicitTermFilter.isValid("strap-on") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidOtherSpecialChar2False() {
|
||||||
|
explicitTermFilter.isValid("This is a room with strap-on content") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValid18True() {
|
||||||
|
explicitTermFilter.isValid("18") shouldBe true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidLastFalse() {
|
||||||
|
explicitTermFilter.isValid("zoo") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun canSearchForFalse() {
|
||||||
|
explicitTermFilter.canSearchFor("zoo") shouldBe false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun canSearchForTrue() {
|
||||||
|
explicitTermFilter.canSearchFor("android") shouldBe true
|
||||||
|
}
|
||||||
|
}
|
68
vector/src/main/assets/forbidden_terms.txt
Normal file
68
vector/src/main/assets/forbidden_terms.txt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
anal
|
||||||
|
bbw
|
||||||
|
bdsm
|
||||||
|
beast
|
||||||
|
bestiality
|
||||||
|
blowjob
|
||||||
|
bondage
|
||||||
|
boobs
|
||||||
|
clit
|
||||||
|
cock
|
||||||
|
cuck
|
||||||
|
cum
|
||||||
|
cunt
|
||||||
|
daddy
|
||||||
|
dick
|
||||||
|
dildo
|
||||||
|
erotic
|
||||||
|
exhibitionism
|
||||||
|
faggot
|
||||||
|
femboy
|
||||||
|
fisting
|
||||||
|
flogging
|
||||||
|
fmf
|
||||||
|
foursome
|
||||||
|
futa
|
||||||
|
gangbang
|
||||||
|
gore
|
||||||
|
h3ntai
|
||||||
|
handjob
|
||||||
|
hentai
|
||||||
|
incest
|
||||||
|
jizz
|
||||||
|
kink
|
||||||
|
loli
|
||||||
|
m4f
|
||||||
|
masturbate
|
||||||
|
masturbation
|
||||||
|
mfm
|
||||||
|
milf
|
||||||
|
moresome
|
||||||
|
naked
|
||||||
|
neet
|
||||||
|
nsfw
|
||||||
|
nude
|
||||||
|
nudity
|
||||||
|
orgy
|
||||||
|
pedo
|
||||||
|
pegging
|
||||||
|
penis
|
||||||
|
petplay
|
||||||
|
porn
|
||||||
|
pussy
|
||||||
|
rape
|
||||||
|
rimming
|
||||||
|
sadism
|
||||||
|
sadomasochism
|
||||||
|
sexy
|
||||||
|
shota
|
||||||
|
spank
|
||||||
|
squirt
|
||||||
|
strap-on
|
||||||
|
threesome
|
||||||
|
vagina
|
||||||
|
vibrator
|
||||||
|
voyeur
|
||||||
|
watersports
|
||||||
|
xxx
|
||||||
|
zoo
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.roomdirectory
|
||||||
|
|
||||||
|
import im.vector.app.core.utils.AssetReader
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ExplicitTermFilter @Inject constructor(
|
||||||
|
assetReader: AssetReader
|
||||||
|
) {
|
||||||
|
// List of forbidden terms is in file asset forbidden_terms.txt, in lower case
|
||||||
|
private val explicitTerms = assetReader.readAssetFile("forbidden_terms.txt")
|
||||||
|
.orEmpty()
|
||||||
|
.split("\n")
|
||||||
|
.map { it.trim() }
|
||||||
|
.distinct()
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
|
|
||||||
|
private val explicitContentRegex = explicitTerms
|
||||||
|
.joinToString(prefix = ".*\\b(", separator = "|", postfix = ")\\b.*")
|
||||||
|
.toRegex(RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
|
fun canSearchFor(term: String): Boolean {
|
||||||
|
return term !in explicitTerms && term != "18+"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValid(str: String): Boolean {
|
||||||
|
return explicitContentRegex.matches(str.replace("\n", " ")).not()
|
||||||
|
// Special treatment for "18+" since word boundaries does not work here
|
||||||
|
&& str.contains("18+").not()
|
||||||
|
}
|
||||||
|
}
|
@ -42,12 +42,12 @@ import org.matrix.android.sdk.api.session.room.model.thirdparty.RoomDirectoryDat
|
|||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
class RoomDirectoryViewModel @AssistedInject constructor(
|
class RoomDirectoryViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: PublicRoomsViewState,
|
@Assisted initialState: PublicRoomsViewState,
|
||||||
vectorPreferences: VectorPreferences,
|
vectorPreferences: VectorPreferences,
|
||||||
private val session: Session
|
private val session: Session,
|
||||||
|
private val explicitTermFilter: ExplicitTermFilter
|
||||||
) : VectorViewModel<PublicRoomsViewState, RoomDirectoryAction, RoomDirectoryViewEvents>(initialState) {
|
) : VectorViewModel<PublicRoomsViewState, RoomDirectoryAction, RoomDirectoryViewEvents>(initialState) {
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
@ -58,11 +58,6 @@ class RoomDirectoryViewModel @AssistedInject constructor(
|
|||||||
companion object : MvRxViewModelFactory<RoomDirectoryViewModel, PublicRoomsViewState> {
|
companion object : MvRxViewModelFactory<RoomDirectoryViewModel, PublicRoomsViewState> {
|
||||||
private const val PUBLIC_ROOMS_LIMIT = 20
|
private const val PUBLIC_ROOMS_LIMIT = 20
|
||||||
|
|
||||||
// List of forbidden terms, in lower case
|
|
||||||
private val explicitContentTerms = listOf(
|
|
||||||
"nsfw"
|
|
||||||
)
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
override fun create(viewModelContext: ViewModelContext, state: PublicRoomsViewState): RoomDirectoryViewModel? {
|
override fun create(viewModelContext: ViewModelContext, state: PublicRoomsViewState): RoomDirectoryViewModel? {
|
||||||
val activity: RoomDirectoryActivity = (viewModelContext as ActivityViewModelContext).activity()
|
val activity: RoomDirectoryActivity = (viewModelContext as ActivityViewModelContext).activity()
|
||||||
@ -166,6 +161,17 @@ class RoomDirectoryViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun load(filter: String, roomDirectoryData: RoomDirectoryData) {
|
private fun load(filter: String, roomDirectoryData: RoomDirectoryData) {
|
||||||
|
if (!showAllRooms && !explicitTermFilter.canSearchFor(filter)) {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
asyncPublicRoomsRequest = Success(Unit),
|
||||||
|
publicRooms = emptyList(),
|
||||||
|
hasMore = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
currentJob = viewModelScope.launch {
|
currentJob = viewModelScope.launch {
|
||||||
val data = try {
|
val data = try {
|
||||||
session.getPublicRooms(roomDirectoryData.homeServer,
|
session.getPublicRooms(roomDirectoryData.homeServer,
|
||||||
@ -202,11 +208,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(
|
|||||||
// Filter
|
// Filter
|
||||||
val newPublicRooms = data.chunk.orEmpty()
|
val newPublicRooms = data.chunk.orEmpty()
|
||||||
.filter {
|
.filter {
|
||||||
showAllRooms
|
showAllRooms || explicitTermFilter.isValid("${it.name.orEmpty()} ${it.topic.orEmpty()}")
|
||||||
|| "${it.name.orEmpty()} ${it.topic.orEmpty()} ${it.canonicalAlias.orEmpty()}".toLowerCase(Locale.ROOT)
|
|
||||||
.let { str ->
|
|
||||||
explicitContentTerms.all { term -> term !in str }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user