From b21def504189aa72ad9122f2da6447148503c3b9 Mon Sep 17 00:00:00 2001 From: Levi Bard Date: Mon, 15 Aug 2022 11:01:04 +0200 Subject: [PATCH] Respect filter expiration date when applying filters (#2661) * Respect filter expiration date when applying filters. #2578 * Fix typing for filter `expires_in` api points --- .../keylesspalace/tusky/FiltersActivity.kt | 4 +-- .../com/keylesspalace/tusky/entity/Filter.kt | 3 +- .../tusky/network/FilterModel.kt | 5 ++- .../tusky/network/MastodonApi.kt | 4 +-- .../com/keylesspalace/tusky/FilterTest.kt | 36 ++++++++++++++++++- 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/FiltersActivity.kt b/app/src/main/java/com/keylesspalace/tusky/FiltersActivity.kt index d6de5d8ec..9f2763101 100644 --- a/app/src/main/java/com/keylesspalace/tusky/FiltersActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/FiltersActivity.kt @@ -56,7 +56,7 @@ class FiltersActivity : BaseActivity() { } private fun updateFilter(filter: Filter, itemIndex: Int) { - api.updateFilter(filter.id, filter.phrase, filter.context, filter.irreversible, filter.wholeWord, filter.expiresAt) + api.updateFilter(filter.id, filter.phrase, filter.context, filter.irreversible, filter.wholeWord, null) .enqueue(object : Callback { override fun onFailure(call: Call, t: Throwable) { Toast.makeText(this@FiltersActivity, "Error updating filter '${filter.phrase}'", Toast.LENGTH_SHORT).show() @@ -102,7 +102,7 @@ class FiltersActivity : BaseActivity() { } private fun createFilter(phrase: String, wholeWord: Boolean) { - api.createFilter(phrase, listOf(context), false, wholeWord, "").enqueue(object : Callback { + api.createFilter(phrase, listOf(context), false, wholeWord, null).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { val filterResponse = response.body() if (response.isSuccessful && filterResponse != null) { diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Filter.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Filter.kt index 34b80e83b..af51a04b9 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Filter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Filter.kt @@ -16,12 +16,13 @@ package com.keylesspalace.tusky.entity import com.google.gson.annotations.SerializedName +import java.util.Date data class Filter( val id: String, val phrase: String, val context: List, - @SerializedName("expires_at") val expiresAt: String?, + @SerializedName("expires_at") val expiresAt: Date?, val irreversible: Boolean, @SerializedName("whole_word") val wholeWord: Boolean ) { diff --git a/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt b/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt index 062191ad0..8adad95f6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt +++ b/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt @@ -3,6 +3,7 @@ package com.keylesspalace.tusky.network import android.text.TextUtils import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.Status +import java.util.Date import java.util.regex.Pattern import javax.inject.Inject @@ -54,7 +55,9 @@ class FilterModel @Inject constructor() { private fun makeFilter(filters: List): Pattern? { if (filters.isEmpty()) return null - val tokens = filters.map { filterToRegexToken(it) } + val tokens = filters + .filter { it.expiresAt?.before(Date()) != true } + .map { filterToRegexToken(it) } return Pattern.compile(TextUtils.join("|", tokens), Pattern.CASE_INSENSITIVE) } diff --git a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt index e72800c4b..e37081c3d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt +++ b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt @@ -536,7 +536,7 @@ interface MastodonApi { @Field("context[]") context: List, @Field("irreversible") irreversible: Boolean?, @Field("whole_word") wholeWord: Boolean?, - @Field("expires_in") expiresIn: String? + @Field("expires_in") expiresIn: Int? ): Call @FormUrlEncoded @@ -547,7 +547,7 @@ interface MastodonApi { @Field("context[]") context: List, @Field("irreversible") irreversible: Boolean?, @Field("whole_word") wholeWord: Boolean?, - @Field("expires_in") expiresIn: String? + @Field("expires_in") expiresIn: Int? ): Call @DELETE("api/v1/filters/{id}") diff --git a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt index 521f01d69..bb2447dbc 100644 --- a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt +++ b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt @@ -14,6 +14,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock import org.robolectric.annotation.Config +import java.time.Instant import java.util.ArrayList import java.util.Date @@ -50,7 +51,23 @@ class FilterTest { expiresAt = null, irreversible = false, wholeWord = true - ) + ), + Filter( + id = "123", + phrase = "expired", + context = listOf(Filter.HOME), + expiresAt = Date.from(Instant.now().minusSeconds(10)), + irreversible = false, + wholeWord = true + ), + Filter( + id = "123", + phrase = "unexpired", + context = listOf(Filter.HOME), + expiresAt = Date.from(Instant.now().plusSeconds(3600)), + irreversible = false, + wholeWord = true + ), ) filterModel.initWithFilters(filters) @@ -148,6 +165,23 @@ class FilterTest { ) } + @Test + fun shouldNotFilter_whenFilterIsExpired() { + assertFalse( + filterModel.shouldFilterStatus( + mockStatus(content = "content matching expired filter should not be filtered") + ) + ) + } + + @Test + fun shouldFilter_whenFilterIsUnexpired() { + assertTrue( + filterModel.shouldFilterStatus( + mockStatus(content = "content matching unexpired filter should be filtered") + ) + ) + } private fun mockStatus( content: String = "", spoilerText: String = "",