Skip to content

Commit

Permalink
Merge branch 'main' into pr/tiann/402
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Dec 26, 2023
2 parents 24a0b36 + 396a914 commit e5d96dc
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 389 deletions.
30 changes: 6 additions & 24 deletions app/src/main/kotlin/li/songe/gkd/data/AppRule.kt
Original file line number Diff line number Diff line change
@@ -1,43 +1,25 @@
package li.songe.gkd.data

import li.songe.gkd.service.TopActivity
import li.songe.selector.Selector

class AppRule(
matches: List<Selector>,
excludeMatches: List<Selector>,
actionDelay: Long,
quickFind: Boolean,
matchDelay: Long,
matchTime: Long?,
resetMatch: String?,
key: Int?,
preKeys: Set<Int>,
index: Int,
rule: RawSubscription.RawAppRule,
subsItem: SubsItem,
group: RawSubscription.RawAppGroup,
rawSubs: RawSubscription,
val appId: String,
val activityIds: List<String>,
val excludeActivityIds: List<String>,
val app: RawSubscription.RawApp,
) : ResolvedRule(
matches = matches,
excludeMatches = excludeMatches,
actionDelay = actionDelay,
quickFind = quickFind,
matchDelay = matchDelay,
matchTime = matchTime,
resetMatch = resetMatch,
key = key,
preKeys = preKeys,
index = index,
rule = rule,
group = group,
subsItem = subsItem,
rawSubs = rawSubs,
) {
val appId = app.id
val activityIds = getFixActivityIds(app.id, rule.activityIds ?: group.activityIds)
val excludeActivityIds =
getFixActivityIds(app.id, rule.excludeActivityIds ?: group.excludeActivityIds)

override val type = "app"
override fun matchActivity(topActivity: TopActivity?): Boolean {
topActivity ?: return false
topActivity.activityId ?: return true
Expand Down
38 changes: 15 additions & 23 deletions app/src/main/kotlin/li/songe/gkd/data/GlobalRule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package li.songe.gkd.data

import li.songe.gkd.service.TopActivity
import li.songe.selector.Selector

data class GlobalApp(
val id: String,
Expand All @@ -11,38 +10,31 @@ data class GlobalApp(
)

class GlobalRule(
matches: List<Selector>,
excludeMatches: List<Selector>,
actionDelay: Long,
quickFind: Boolean,
matchDelay: Long,
matchTime: Long?,
resetMatch: String?,
key: Int?,
preKeys: Set<Int>,
index: Int,
subsItem: SubsItem,
rule: RawSubscription.RawGlobalRule,
group: RawSubscription.RawGlobalGroup,
rawSubs: RawSubscription,
val apps: Map<String, GlobalApp>,
val matchAnyApp: Boolean,
) : ResolvedRule(
matches = matches,
excludeMatches = excludeMatches,
actionDelay = actionDelay,
quickFind = quickFind,
matchDelay = matchDelay,
matchTime = matchTime,
resetMatch = resetMatch,
key = key,
preKeys = preKeys,
index = index,
rule = rule,
group = group,
subsItem = subsItem,
rawSubs = rawSubs,
) {

val matchAnyApp = rule.matchAnyApp ?: group.matchAnyApp ?: true
val apps = mutableMapOf<String, GlobalApp>().apply {
(rule.apps ?: group.apps ?: emptyList()).forEach { a ->
this[a.id] = GlobalApp(
id = a.id,
enable = a.enable ?: true,
activityIds = getFixActivityIds(a.id, a.activityIds),
excludeActivityIds = getFixActivityIds(a.id, a.excludeActivityIds)
)
}
}

override val type = "global"

private val excludeAppIds = apps.filter { e -> !e.value.enable }.keys
override fun matchActivity(topActivity: TopActivity?): Boolean {
topActivity ?: return false
Expand Down
33 changes: 26 additions & 7 deletions app/src/main/kotlin/li/songe/gkd/data/RawSubscription.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ data class RawSubscription(
val updateUrl: String? = null,
val supportUri: String? = null,
val checkUpdateUrl: String? = null,
val apps: List<RawApp> = emptyList(),
val categories: List<RawCategory> = emptyList(),
val globalGroups: List<RawGlobalGroup> = emptyList(),
val categories: List<RawCategory> = emptyList(),
val apps: List<RawApp> = emptyList(),
) {

@IgnoredOnParcel
Expand Down Expand Up @@ -57,8 +57,27 @@ data class RawSubscription(
}

@IgnoredOnParcel
val allGroupSize by lazy {
globalGroups.size + appGroups.size
val numText by lazy {
val appsSize = apps.size
val appGroupsSize = appGroups.size
val globalGroupSize = globalGroups.size
if (appGroupsSize + globalGroupSize > 0) {
if (globalGroupSize > 0) {
"${globalGroupSize}全局" + if (appGroupsSize > 0) {
"/"
} else {
""
}
} else {
""
} + if (appGroupsSize > 0) {
"${appsSize}应用/${appGroupsSize}规则组"
} else {
""
}
} else {
"暂无规则"
}
}

@Serializable
Expand Down Expand Up @@ -118,9 +137,9 @@ data class RawSubscription(
data class RawGlobalApp(
val id: String,
val enable: Boolean?,
val activityIds: List<String>?,
val excludeActivityIds: List<String>?,
)
override val activityIds: List<String>?,
override val excludeActivityIds: List<String>?,
) : RawAppRuleProps


@Serializable
Expand Down
131 changes: 91 additions & 40 deletions app/src/main/kotlin/li/songe/gkd/data/ResolvedRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,63 @@ import li.songe.gkd.service.querySelector
import li.songe.selector.Selector

sealed class ResolvedRule(
val matches: List<Selector>,
val excludeMatches: List<Selector>,

val actionDelay: Long,
val quickFind: Boolean,

val matchDelay: Long,
val matchTime: Long?,
val resetMatch: String?,

val key: Int?,
val preKeys: Set<Int>,

val index: Int,
val rule: RawSubscription.RawRuleProps,
val group: RawSubscription.RawGroupProps,
val rawSubs: RawSubscription,
val subsItem: SubsItem,
) {
var preAppRules: Set<ResolvedRule> = emptySet()
val key = rule.key
val index = group.rules.indexOf(rule)
val preKeys = (rule.preKeys ?: emptyList()).toSet()
val resetMatch = rule.resetMatch ?: group.resetMatch
val matches = rule.matches.map { s -> Selector.parse(s) }
val excludeMatches = (rule.excludeMatches ?: emptyList()).map { s -> Selector.parse(s) }
val matchDelay = rule.matchDelay ?: group.matchDelay ?: 0L
val actionDelay = rule.actionDelay ?: group.actionDelay ?: 0L
val matchTime = rule.matchTime ?: group.matchTime
val quickFind = rule.quickFind ?: group.quickFind ?: false

val actionCdKey = rule.actionCdKey ?: group.actionCdKey
val actionCd = rule.actionCd ?: if (actionCdKey != null) {
group.rules.find { r -> r.key == actionCdKey }?.actionCd
} else {
null
} ?: group.actionCd ?: 1000L

val actionMaximumKey = rule.actionMaximumKey ?: group.actionMaximumKey
val actionMaximum = rule.actionMaximum ?: if (actionMaximumKey != null) {
group.rules.find { r -> r.key == actionMaximumKey }?.actionMaximum
} else {
null
} ?: group.actionMaximum

var groupRules: List<ResolvedRule> = emptyList()
set(value) {
field = value
// 共享次数
if (actionMaximumKey != null) {
val otherRule = field.find { r -> r.key == actionMaximumKey }
if (otherRule != null) {
actionCount = otherRule.actionCount
}
}
// 共享 cd
if (actionCdKey != null) {
val otherRule = field.find { r -> r.key == actionCdKey }
if (otherRule != null) {
actionTriggerTime = otherRule.actionTriggerTime
}
}
preRules = field.filter { otherRule ->
(otherRule.key != null) && preKeys.contains(
otherRule.key
)
}.toSet()
}

var preRules = emptySet<ResolvedRule>()
val hasNext = group.rules.any { r -> r.preKeys?.any { k -> k == rule.key } == true }

var actionDelayTriggerTime = 0L
var actionDelayJob: Job? = null
fun checkDelay(): Boolean {
Expand All @@ -39,12 +76,6 @@ sealed class ResolvedRule(
return false
}

val actionCd = (if (rule.actionCdKey != null) {
group.rules.find { r -> r.key == rule.actionCdKey }?.actionCd ?: group.actionCd
} else {
null
} ?: rule.actionCd ?: group.actionCd ?: 1000L)

var actionTriggerTime = Value(0L)
fun trigger() {
actionTriggerTime.value = System.currentTimeMillis()
Expand All @@ -55,13 +86,6 @@ sealed class ResolvedRule(
lastTriggerRule = this
}

val actionMaximum = ((if (rule.actionMaximumKey != null) {
group.rules.find { r -> r.key == rule.actionMaximumKey }?.actionMaximum
?: group.actionMaximum
} else {
null
}) ?: rule.actionMaximum ?: group.actionMaximum)

var actionCount = Value(0)

var matchChangedTime = 0L
Expand Down Expand Up @@ -90,42 +114,69 @@ sealed class ResolvedRule(

var matchDelayJob: Job? = null

val statusCode: Int
val status: RuleStatus
get() {
if (actionMaximum != null) {
if (actionCount.value >= actionMaximum) {
return 1 // 达到最大执行次数
return RuleStatus.Status1 // 达到最大执行次数
}
}
if (preAppRules.isNotEmpty()) { // 需要提前点击某个规则
lastTriggerRule ?: return 2
return if (preAppRules.any { it === lastTriggerRule }) {
0
if (preRules.isNotEmpty()) { // 需要提前点击某个规则
return if (preRules.any { it === lastTriggerRule }) {
RuleStatus.StatusOk
} else {
3 // 上一个点击的规则不在当前需要点击的列表
RuleStatus.Status2
}
}
val t = System.currentTimeMillis()
if (matchDelay > 0 && t - matchChangedTime < matchDelay) {
return 4 // 处于匹配延迟中
return RuleStatus.Status3 // 处于匹配延迟中
}
if (matchTime != null && t - matchChangedTime > matchLimitTime) {
return 5 // 超出匹配时间
return RuleStatus.Status4 // 超出匹配时间
}
if (actionTriggerTime.value + actionCd > t) {
return 6 // 处于冷却时间
return RuleStatus.Status5 // 处于冷却时间
}
if (actionDelayTriggerTime > 0) {
if (actionDelayTriggerTime + actionDelay > t) {
return 7 // 处于点击延迟中
return RuleStatus.Status6 // 处于点击延迟中
}
}
return 0
return RuleStatus.StatusOk
}

fun statusText(): String {
return "id:${subsItem.id}, v:${rawSubs.version}, type:${type}, gKey=${group.key}, gName:${group.name}, index:${index}, key:${key}, status:${status.name}"
}

abstract val type: String
abstract fun matchActivity(topActivity: TopActivity?): Boolean

}

sealed class RuleStatus(val name: String) {
data object StatusOk : RuleStatus("ok")
data object Status1 : RuleStatus("达到最大执行次数")
data object Status2 : RuleStatus("需要提前点击某个规则")
data object Status3 : RuleStatus("处于匹配延迟")
data object Status4 : RuleStatus("超出匹配时间")
data object Status5 : RuleStatus("处于冷却时间")
data object Status6 : RuleStatus("处于点击延迟")
}

fun getFixActivityIds(
appId: String,
activityIds: List<String>?,
): List<String> {
activityIds ?: return emptyList()
return activityIds.map { activityId ->
if (activityId.startsWith('.')) { // .a.b.c -> com.x.y.x.a.b.c
appId + activityId
} else {
activityId
}
}
}


6 changes: 4 additions & 2 deletions app/src/main/kotlin/li/songe/gkd/debug/KtorErrorPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import io.ktor.http.HttpStatusCode
import io.ktor.server.application.createApplicationPlugin
import io.ktor.server.application.hooks.CallFailed
import io.ktor.server.request.uri
import io.ktor.server.response.header
import io.ktor.server.response.respond
import li.songe.gkd.data.RpcError

val KtorErrorPlugin = createApplicationPlugin(name = "KtorErrorPlugin") {
onCall { call ->
Log.d("Ktor", "onCall: ${call.request.uri}")
// TODO 在局域网会被扫描工具批量请求多个路径
if (call.request.uri == "/" || call.request.uri.startsWith("/api/")) {
Log.d("Ktor", "onCall: ${call.request.uri}")
}
}
on(CallFailed) { call, cause ->
when (cause) {
Expand Down
13 changes: 9 additions & 4 deletions app/src/main/kotlin/li/songe/gkd/service/AbExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,15 @@ private val getAttr: (AccessibilityNodeInfo, String) -> Any? = { node, name ->
when (name) {
"id" -> node.viewIdResourceName
"vid" -> node.viewIdResourceName?.let { id ->
id.subSequence(
(node.packageName?.length ?: 0) + ":id/".length,
id.length
)
val appId = node.packageName
if (appId != null && id.startsWith(appId) && id.startsWith(":id/", appId.length)) {
id.subSequence(
appId.length + ":id/".length,
id.length
)
} else {
null
}
}

"name" -> node.className
Expand Down
Loading

0 comments on commit e5d96dc

Please sign in to comment.