Tracker.kt (8855B) - raw
1 package me.rhunk.snapenhance.storage 2 3 import android.content.ContentValues 4 import com.google.gson.JsonArray 5 import kotlinx.coroutines.runBlocking 6 import me.rhunk.snapenhance.common.data.TrackerRule 7 import me.rhunk.snapenhance.common.data.TrackerRuleAction 8 import me.rhunk.snapenhance.common.data.TrackerRuleActionParams 9 import me.rhunk.snapenhance.common.data.TrackerRuleEvent 10 import me.rhunk.snapenhance.common.data.TrackerScopeType 11 import me.rhunk.snapenhance.common.util.ktx.getInteger 12 import me.rhunk.snapenhance.common.util.ktx.getLongOrNull 13 import me.rhunk.snapenhance.common.util.ktx.getStringOrNull 14 import kotlin.coroutines.suspendCoroutine 15 16 17 fun AppDatabase.clearTrackerRules() { 18 runBlocking { 19 suspendCoroutine { continuation -> 20 executeAsync { 21 database.execSQL("DELETE FROM tracker_rules") 22 database.execSQL("DELETE FROM tracker_rules_events") 23 continuation.resumeWith(Result.success(Unit)) 24 } 25 } 26 } 27 } 28 29 fun AppDatabase.deleteTrackerRule(ruleId: Int) { 30 executeAsync { 31 database.execSQL("DELETE FROM tracker_rules WHERE id = ?", arrayOf(ruleId)) 32 database.execSQL("DELETE FROM tracker_rules_events WHERE rule_id = ?", arrayOf(ruleId)) 33 } 34 } 35 36 fun AppDatabase.newTrackerRule(name: String = "Custom Rule"): Int { 37 return runBlocking { 38 suspendCoroutine { continuation -> 39 executeAsync { 40 val id = database.insert("tracker_rules", null, ContentValues().apply { 41 put("name", name) 42 }) 43 continuation.resumeWith(Result.success(id.toInt())) 44 } 45 } 46 } 47 } 48 49 fun AppDatabase.addOrUpdateTrackerRuleEvent( 50 ruleEventId: Int? = null, 51 ruleId: Int? = null, 52 eventType: String? = null, 53 params: TrackerRuleActionParams, 54 actions: List<TrackerRuleAction> 55 ): Int? { 56 return runBlocking { 57 suspendCoroutine { continuation -> 58 executeAsync { 59 val id = if (ruleEventId != null) { 60 database.execSQL("UPDATE tracker_rules_events SET params = ?, actions = ? WHERE id = ?", arrayOf( 61 context.gson.toJson(params), 62 context.gson.toJson(actions.map { it.key }), 63 ruleEventId 64 )) 65 ruleEventId 66 } else { 67 database.insert("tracker_rules_events", null, ContentValues().apply { 68 put("rule_id", ruleId) 69 put("event_type", eventType) 70 put("params", context.gson.toJson(params)) 71 put("actions", context.gson.toJson(actions.map { it.key })) 72 }).toInt() 73 } 74 continuation.resumeWith(Result.success(id)) 75 } 76 } 77 } 78 } 79 80 fun AppDatabase.deleteTrackerRuleEvent(eventId: Int) { 81 executeAsync { 82 database.execSQL("DELETE FROM tracker_rules_events WHERE id = ?", arrayOf(eventId)) 83 } 84 } 85 86 fun AppDatabase.getTrackerRulesDesc(): List<TrackerRule> { 87 val rules = mutableListOf<TrackerRule>() 88 89 database.rawQuery("SELECT * FROM tracker_rules ORDER BY id DESC", null).use { cursor -> 90 while (cursor.moveToNext()) { 91 rules.add( 92 TrackerRule( 93 id = cursor.getInteger("id"), 94 enabled = cursor.getInteger("enabled") == 1, 95 name = cursor.getStringOrNull("name") ?: "", 96 ) 97 ) 98 } 99 } 100 101 return rules 102 } 103 104 fun AppDatabase.getTrackerRule(ruleId: Int): TrackerRule? { 105 return database.rawQuery("SELECT * FROM tracker_rules WHERE id = ?", arrayOf(ruleId.toString())).use { cursor -> 106 if (!cursor.moveToFirst()) return@use null 107 TrackerRule( 108 id = cursor.getInteger("id"), 109 enabled = cursor.getInteger("enabled") == 1, 110 name = cursor.getStringOrNull("name") ?: "", 111 ) 112 } 113 } 114 115 fun AppDatabase.setTrackerRuleName(ruleId: Int, name: String) { 116 executeAsync { 117 database.execSQL("UPDATE tracker_rules SET name = ? WHERE id = ?", arrayOf(name, ruleId)) 118 } 119 } 120 121 fun AppDatabase.setTrackerRuleState(ruleId: Int, enabled: Boolean) { 122 executeAsync { 123 database.execSQL("UPDATE tracker_rules SET enabled = ? WHERE id = ?", arrayOf(if (enabled) 1 else 0, ruleId)) 124 } 125 } 126 127 fun AppDatabase.getTrackerEvents(ruleId: Int): List<TrackerRuleEvent> { 128 val events = mutableListOf<TrackerRuleEvent>() 129 database.rawQuery("SELECT * FROM tracker_rules_events WHERE rule_id = ?", arrayOf(ruleId.toString())).use { cursor -> 130 while (cursor.moveToNext()) { 131 events.add( 132 TrackerRuleEvent( 133 id = cursor.getInteger("id"), 134 eventType = cursor.getStringOrNull("event_type") ?: continue, 135 enabled = cursor.getInteger("flags") == 1, 136 params = context.gson.fromJson(cursor.getStringOrNull("params") ?: "{}", TrackerRuleActionParams::class.java), 137 actions = context.gson.fromJson(cursor.getStringOrNull("actions") ?: "[]", JsonArray::class.java).mapNotNull { 138 TrackerRuleAction.fromString(it.asString) 139 } 140 ) 141 ) 142 } 143 } 144 return events 145 } 146 147 fun AppDatabase.getTrackerEvents(eventType: String): Map<TrackerRuleEvent, TrackerRule> { 148 val events = mutableMapOf<TrackerRuleEvent, TrackerRule>() 149 database.rawQuery("SELECT tracker_rules_events.id as event_id, tracker_rules_events.params as event_params," + 150 "tracker_rules_events.actions, tracker_rules_events.flags, tracker_rules_events.event_type, tracker_rules.name, tracker_rules.id as rule_id " + 151 "FROM tracker_rules_events " + 152 "INNER JOIN tracker_rules " + 153 "ON tracker_rules_events.rule_id = tracker_rules.id " + 154 "WHERE event_type = ? AND tracker_rules.enabled = 1", arrayOf(eventType) 155 ).use { cursor -> 156 while (cursor.moveToNext()) { 157 val trackerRule = TrackerRule( 158 id = cursor.getInteger("rule_id"), 159 enabled = true, 160 name = cursor.getStringOrNull("name") ?: "", 161 ) 162 val trackerRuleEvent = TrackerRuleEvent( 163 id = cursor.getInteger("event_id"), 164 eventType = cursor.getStringOrNull("event_type") ?: continue, 165 enabled = cursor.getInteger("flags") == 1, 166 params = context.gson.fromJson(cursor.getStringOrNull("event_params") ?: "{}", TrackerRuleActionParams::class.java), 167 actions = context.gson.fromJson(cursor.getStringOrNull("actions") ?: "[]", JsonArray::class.java).mapNotNull { 168 TrackerRuleAction.fromString(it.asString) 169 } 170 ) 171 events[trackerRuleEvent] = trackerRule 172 } 173 } 174 return events 175 } 176 177 fun AppDatabase.setRuleTrackerScopes(ruleId: Int, type: TrackerScopeType, scopes: List<String>) { 178 executeAsync { 179 database.execSQL("DELETE FROM tracker_scopes WHERE rule_id = ?", arrayOf(ruleId)) 180 scopes.forEach { scopeId -> 181 database.execSQL("INSERT INTO tracker_scopes (rule_id, scope_type, scope_id) VALUES (?, ?, ?)", arrayOf( 182 ruleId, 183 type.key, 184 scopeId 185 )) 186 } 187 } 188 } 189 190 fun AppDatabase.getRuleTrackerScopes(ruleId: Int, limit: Int = Int.MAX_VALUE): Map<String, TrackerScopeType> { 191 val scopes = mutableMapOf<String, TrackerScopeType>() 192 database.rawQuery("SELECT * FROM tracker_scopes WHERE rule_id = ? LIMIT ?", arrayOf(ruleId.toString(), limit.toString())).use { cursor -> 193 while (cursor.moveToNext()) { 194 scopes[cursor.getStringOrNull("scope_id") ?: continue] = TrackerScopeType.entries.find { it.key == cursor.getStringOrNull("scope_type") } ?: continue 195 } 196 } 197 return scopes 198 } 199 200 fun AppDatabase.updateFriendScore(userId: String, score: Long): Long { 201 return runBlocking { 202 suspendCoroutine { continuation -> 203 executeAsync { 204 val currentScore = database.rawQuery("SELECT score FROM friend_scores WHERE userId = ?", arrayOf(userId)).use { cursor -> 205 if (!cursor.moveToFirst()) return@use null 206 cursor.getLongOrNull("score") 207 } 208 209 if (currentScore != null) { 210 database.execSQL("UPDATE friend_scores SET score = ? WHERE userId = ?", arrayOf(score, userId)) 211 } else { 212 database.execSQL("INSERT INTO friend_scores (userId, score) VALUES (?, ?)", arrayOf(userId, score)) 213 } 214 215 continuation.resumeWith(Result.success(currentScore ?: -1)) 216 } 217 } 218 } 219 }