refactor(subscriptions): migrate from MMKV library to file-based storage

This commit is contained in:
zarazaex69
2026-04-07 12:19:58 +03:00
parent bddd769984
commit 420a3e4230
4 changed files with 144 additions and 84 deletions
-82
View File
@@ -1,82 +0,0 @@
import com.google.gson.Gson
import com.tencent.mmkv.MMKV
import java.util.UUID
data class SubscriptionItem(
var remarks: String = "",
var url: String = "",
var enabled: Boolean = true,
val addedTime: Long = System.currentTimeMillis(),
var lastUpdated: Long = -1,
var autoUpdate: Boolean = false,
val updateInterval: Int? = null,
var prevProfile: String? = null,
var nextProfile: String? = null,
var filter: String? = null,
var allowInsecureUrl: Boolean = false,
var userAgent: String? = null
)
class SubscriptionManager {
private val subStorage = MMKV.mmkvWithID("SUB")
private val gson = Gson()
fun addSubscription(remarks: String, url: String, autoUpdate: Boolean = true): String {
val guid = UUID.randomUUID().toString().replace("-", "")
val subItem = SubscriptionItem(
remarks = remarks,
url = url,
enabled = true,
addedTime = System.currentTimeMillis(),
lastUpdated = -1,
autoUpdate = autoUpdate,
filter = "",
allowInsecureUrl = false,
userAgent = ""
)
encodeSubscription(guid, subItem)
return guid
}
private fun encodeSubscription(guid: String, subItem: SubscriptionItem) {
val json = gson.toJson(subItem)
subStorage.encode(guid, json)
val subsList = decodeSubsList()
if (!subsList.contains(guid)) {
subsList.add(guid)
encodeSubsList(subsList)
}
}
private fun decodeSubsList(): MutableList<String> {
val json = subStorage.decodeString("SUBS_LIST") ?: return mutableListOf()
return gson.fromJson(json, Array<String>::class.java)?.toMutableList() ?: mutableListOf()
}
private fun encodeSubsList(subsList: List<String>) {
subStorage.encode("SUBS_LIST", gson.toJson(subsList))
}
}
fun main() {
MMKV.initialize("/home/zarazaex/Projects/olcng/V2rayNG/app/src/main/assets/mmkv")
val manager = SubscriptionManager()
manager.addSubscription(
remarks = "БЕЛЫЕ Z",
url = "https://raw.githubusercontent.com/zieng2/wl/refs/heads/main/vless_universal.txt",
autoUpdate = true
)
manager.addSubscription(
remarks = "БЕЛЫЕ W",
url = "https://raw.githubusercontent.com/whoahaow/rjsxrd/refs/heads/main/githubmirror/bypass/bypass-all.txt",
autoUpdate = true
)
println("Подписки успешно добавлены")
}
Binary file not shown.
-2
View File
@@ -8,12 +8,10 @@ version = "1.0"
repositories {
mavenCentral()
google()
}
dependencies {
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.tencent:mmkv:1.3.9")
}
application {
+144
View File
@@ -0,0 +1,144 @@
import com.google.gson.Gson
import java.io.File
import java.io.RandomAccessFile
import java.net.URL
import java.util.UUID
data class SubscriptionItem(
var remarks: String = "",
var url: String = "",
var enabled: Boolean = true,
val addedTime: Long = System.currentTimeMillis(),
var lastUpdated: Long = -1,
var autoUpdate: Boolean = false,
val updateInterval: Int? = null,
var prevProfile: String? = null,
var nextProfile: String? = null,
var filter: String? = null,
var allowInsecureUrl: Boolean = false,
var userAgent: String? = null
)
class MMKVWriter(private val filePath: String) {
private val gson = Gson()
fun writeEntry(key: String, json: String) {
val file = RandomAccessFile(filePath, "rw")
file.seek(file.length())
val keyBytes = key.toByteArray(Charsets.UTF_8)
val jsonBytes = json.toByteArray(Charsets.UTF_8)
file.writeInt(keyBytes.size)
file.write(keyBytes)
file.writeInt(jsonBytes.size)
file.write(jsonBytes)
file.close()
}
}
class SubscriptionManager(private val mmkvPath: String) {
private val gson = Gson()
private val writer = MMKVWriter(mmkvPath)
fun addSubscription(remarks: String, url: String, autoUpdate: Boolean = true): String {
val guid = UUID.randomUUID().toString().replace("-", "")
val subItem = SubscriptionItem(
remarks = remarks,
url = url,
enabled = true,
addedTime = System.currentTimeMillis(),
lastUpdated = -1,
autoUpdate = autoUpdate,
filter = "",
allowInsecureUrl = false,
userAgent = ""
)
val json = gson.toJson(subItem)
writer.writeEntry(guid, json)
return guid
}
fun updateSubscription(guid: String, url: String): Boolean {
return try {
println("Обновление подписки $guid...")
val content = URL(url).readText()
val lines = content.lines().filter { it.isNotBlank() }
println("Загружено ${lines.size} конфигураций")
val subItem = readSubscription(guid) ?: return false
subItem.lastUpdated = System.currentTimeMillis()
val json = gson.toJson(subItem)
writer.writeEntry(guid, json)
true
} catch (e: Exception) {
println("Ошибка обновления: ${e.message}")
false
}
}
private fun readSubscription(guid: String): SubscriptionItem? {
val file = File(mmkvPath)
if (!file.exists()) return null
val data = file.readBytes()
var pos = 0
while (pos < data.size) {
if (pos + 4 > data.size) break
val keyLen = java.nio.ByteBuffer.wrap(data, pos, 4).int
pos += 4
if (pos + keyLen > data.size) break
val key = String(data, pos, keyLen, Charsets.UTF_8)
pos += keyLen
if (pos + 4 > data.size) break
val jsonLen = java.nio.ByteBuffer.wrap(data, pos, 4).int
pos += 4
if (pos + jsonLen > data.size) break
val json = String(data, pos, jsonLen, Charsets.UTF_8)
pos += jsonLen
if (key == guid) {
return gson.fromJson(json, SubscriptionItem::class.java)
}
}
return null
}
}
fun main() {
val mmkvPath = "/home/zarazaex/Projects/olcng/V2rayNG/app/src/main/assets/mmkv/SUB"
val manager = SubscriptionManager(mmkvPath)
val guid1 = manager.addSubscription(
remarks = "БЕЛЫЕ Z",
url = "https://raw.githubusercontent.com/zieng2/wl/refs/heads/main/vless_universal.txt",
autoUpdate = true
)
println("Добавлена подписка БЕЛЫЕ Z: $guid1")
val guid2 = manager.addSubscription(
remarks = "БЕЛЫЕ W",
url = "https://raw.githubusercontent.com/whoahaow/rjsxrd/refs/heads/main/githubmirror/bypass/bypass-all.txt",
autoUpdate = true
)
println("Добавлена подписка БЕЛЫЕ W: $guid2")
println("\nОбновление подписок...")
manager.updateSubscription(guid1, "https://raw.githubusercontent.com/zieng2/wl/refs/heads/main/vless_universal.txt")
manager.updateSubscription(guid2, "https://raw.githubusercontent.com/whoahaow/rjsxrd/refs/heads/main/githubmirror/bypass/bypass-all.txt")
println("\nПодписки успешно добавлены и обновлены в $mmkvPath")
}