feat(Scout): add has:poll and has:forward filters
This commit is contained in:
parent
da07f17650
commit
47ae69de2d
3 changed files with 130 additions and 0 deletions
|
|
@ -0,0 +1,9 @@
|
|||
package moe.lava.awoocord.scout
|
||||
|
||||
import com.discord.utilities.search.query.node.answer.HasAnswerOption
|
||||
|
||||
object HasAnswerOptionExtension {
|
||||
lateinit var POLL: HasAnswerOption
|
||||
lateinit var SNAPSHOT: HasAnswerOption
|
||||
lateinit var values: Array<HasAnswerOption>
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.aliucord.entities.Plugin
|
|||
import com.aliucord.patcher.PreHook
|
||||
import com.aliucord.patcher.after
|
||||
import com.aliucord.patcher.before
|
||||
import com.aliucord.patcher.instead
|
||||
import com.discord.BuildConfig
|
||||
import com.discord.restapi.RequiredHeadersInterceptor
|
||||
import com.discord.restapi.RequiredHeadersInterceptor.HeadersProvider
|
||||
|
|
@ -21,12 +22,14 @@ import com.discord.utilities.rest.RestAPI.AppHeadersProvider
|
|||
import com.discord.utilities.search.network.`SearchFetcher$getRestObservable$3`
|
||||
import com.discord.utilities.search.query.FilterType
|
||||
import com.discord.utilities.search.query.node.QueryNode
|
||||
import com.discord.utilities.search.query.node.answer.HasAnswerOption
|
||||
import com.discord.utilities.search.query.node.content.ContentNode
|
||||
import com.discord.utilities.search.query.node.filter.FilterNode
|
||||
import com.discord.utilities.search.query.parsing.QueryParser
|
||||
import com.discord.utilities.search.strings.SearchStringProvider
|
||||
import com.discord.utilities.search.suggestion.SearchSuggestionEngine
|
||||
import com.discord.utilities.search.suggestion.entries.FilterSuggestion
|
||||
import com.discord.utilities.search.suggestion.entries.HasSuggestion
|
||||
import com.discord.utilities.search.suggestion.entries.SearchSuggestion
|
||||
import com.discord.widgets.search.suggestions.WidgetSearchSuggestionsAdapter
|
||||
import com.franmontiel.persistentcookiejar.PersistentCookieJar
|
||||
|
|
@ -50,13 +53,16 @@ class Scout : Plugin() {
|
|||
ssProvider = ScoutSearchStringProvider(context)
|
||||
searchApi = buildSearchApi(context)
|
||||
extendFilterType()
|
||||
extendHasAnswerOption()
|
||||
patchQueryParser()
|
||||
patchQuery()
|
||||
patchHasAnswerOption()
|
||||
patchSearchUI(context)
|
||||
}
|
||||
|
||||
override fun stop(context: Context) {
|
||||
resetFilterType()
|
||||
resetHasAnswerOption()
|
||||
patcher.unpatchAll()
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +129,107 @@ class Scout : Plugin() {
|
|||
origFilterTypes = null
|
||||
}
|
||||
|
||||
private var origHasAnswerOptions: Array<HasAnswerOption>? = null
|
||||
// Creates new pseudo-values of the `HasAnswerOption` enum for poll and forwarded filters
|
||||
@Suppress("LocalVariableName")
|
||||
private fun extendHasAnswerOption() {
|
||||
val cls = HasAnswerOption::class.java
|
||||
val constructor = cls.declaredConstructors[0]
|
||||
constructor.isAccessible = true
|
||||
|
||||
val field = cls.getDeclaredField("\$VALUES")
|
||||
field.isAccessible = true
|
||||
val values = field.get(null) as Array<HasAnswerOption>
|
||||
origHasAnswerOptions = origHasAnswerOptions ?: values
|
||||
var nextIdx = values.size
|
||||
|
||||
val POLL = constructor.newInstance("POLL", nextIdx++, "poll") as HasAnswerOption
|
||||
val SNAPSHOT = constructor.newInstance("SNAPSHOT", nextIdx, "snapshot") as HasAnswerOption
|
||||
HasAnswerOptionExtension.POLL = POLL
|
||||
HasAnswerOptionExtension.SNAPSHOT = SNAPSHOT
|
||||
HasAnswerOptionExtension.values = arrayOf(POLL, SNAPSHOT)
|
||||
|
||||
val newValues = values.toMutableList()
|
||||
newValues.addAll(HasAnswerOptionExtension.values)
|
||||
field.set(null, newValues.toTypedArray())
|
||||
}
|
||||
|
||||
private fun resetHasAnswerOption() {
|
||||
if (origHasAnswerOptions == null)
|
||||
return logger.error("No unpatched 'has' options?", null)
|
||||
|
||||
val cls = HasAnswerOption::class.java
|
||||
val field = cls.getDeclaredField("\$VALUES")
|
||||
field.isAccessible = true
|
||||
field.set(null, origHasAnswerOptions)
|
||||
origHasAnswerOptions = null
|
||||
}
|
||||
|
||||
// Patches various methods that use HasAnswerOption to include our new options
|
||||
private fun patchHasAnswerOption() {
|
||||
patcher.before<HasAnswerOption.Companion>(
|
||||
"getOptionFromString",
|
||||
String::class.java,
|
||||
SearchStringProvider::class.java
|
||||
) { param ->
|
||||
val str = param.args[0] as String
|
||||
if (str == ssProvider.hasPollString)
|
||||
param.result = HasAnswerOptionExtension.POLL
|
||||
else if (str == ssProvider.hasForwardString)
|
||||
param.result = HasAnswerOptionExtension.SNAPSHOT
|
||||
}
|
||||
|
||||
patcher.before<HasAnswerOption>(
|
||||
"getLocalizedInputText",
|
||||
SearchStringProvider::class.java
|
||||
) { param ->
|
||||
if (this == HasAnswerOptionExtension.POLL)
|
||||
param.result = ssProvider.hasPollString
|
||||
else if (this == HasAnswerOptionExtension.SNAPSHOT)
|
||||
param.result = ssProvider.hasForwardString
|
||||
}
|
||||
|
||||
// private final String createHasAnswerRegex(SearchStringProvider searchStringProvider) {
|
||||
patcher.instead<QueryParser.Companion>(
|
||||
"createHasAnswerRegex",
|
||||
SearchStringProvider::class.java
|
||||
) { param ->
|
||||
val ossProvider = param.args[0] as SearchStringProvider
|
||||
|
||||
val matches = HasAnswerOption.values().joinToString("|") { it.getLocalizedInputText(ossProvider) }
|
||||
"^\\s*($matches)"
|
||||
}
|
||||
|
||||
// Patch to set icons
|
||||
patcher.before<WidgetSearchSuggestionsAdapter.HasViewHolder.Companion>(
|
||||
"getIconRes",
|
||||
HasAnswerOption::class.java
|
||||
) { param ->
|
||||
val type = param.args[0] as HasAnswerOption
|
||||
if (type == HasAnswerOptionExtension.POLL)
|
||||
param.result = 0x7f08032e
|
||||
else if (type == HasAnswerOptionExtension.SNAPSHOT)
|
||||
param.result = 0x7f08032e
|
||||
}
|
||||
|
||||
patcher.after<SearchSuggestionEngine>(
|
||||
"getHasSuggestions",
|
||||
CharSequence::class.java,
|
||||
FilterType::class.java,
|
||||
SearchStringProvider::class.java,
|
||||
) { param ->
|
||||
val query = param.args[0] as CharSequence
|
||||
val res = (param.result as List<SearchSuggestion>).toMutableList()
|
||||
for (type in HasAnswerOptionExtension.values) {
|
||||
val st = ssProvider.stringFor(type) + ":"
|
||||
|
||||
if (st.contains(query))
|
||||
res.add(HasSuggestion(type))
|
||||
}
|
||||
param.result = res.toList()
|
||||
}
|
||||
}
|
||||
|
||||
// Patches the search query to also insert `min_id`, required for searching "after:" and "during:"
|
||||
private fun patchQuery() {
|
||||
patcher.patch(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package moe.lava.awoocord.scout.ui
|
|||
|
||||
import android.content.Context
|
||||
import com.discord.utilities.search.query.FilterType
|
||||
import com.discord.utilities.search.query.node.answer.HasAnswerOption
|
||||
import moe.lava.awoocord.scout.FilterTypeExtension
|
||||
import moe.lava.awoocord.scout.HasAnswerOptionExtension
|
||||
|
||||
private fun String.decapitalise(context: Context) =
|
||||
this.replaceFirstChar { it.lowercase(context.resources.configuration.locales[0]) }
|
||||
|
|
@ -21,6 +23,12 @@ class ScoutSearchStringProvider(private val context: Context) {
|
|||
else -> throw IllegalArgumentException("invalid extended filter type")
|
||||
}
|
||||
|
||||
fun stringFor(type: HasAnswerOption) = when (type) {
|
||||
HasAnswerOptionExtension.POLL -> hasPollString
|
||||
HasAnswerOptionExtension.SNAPSHOT -> hasForwardString
|
||||
else -> throw IllegalArgumentException("invalid extended filter type")
|
||||
}
|
||||
|
||||
// Surprising!! Discord has localised strings of these
|
||||
val beforeFilterString: String
|
||||
get() = getString("search_filter_before")
|
||||
|
|
@ -32,4 +40,10 @@ class ScoutSearchStringProvider(private val context: Context) {
|
|||
get() = getString("sort").decapitalise(context)
|
||||
val sortOldString: String
|
||||
get() = getString("search_oldest_short").decapitalise(context)
|
||||
|
||||
// Not localised
|
||||
val hasPollString: String
|
||||
get() = "poll"
|
||||
val hasForwardString: String
|
||||
get() = "forward"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue