mirror of
https://github.com/openlibrecommunity/olcng.git
synced 2026-07-03 14:05:17 +02:00
refactor(subscriptions): migrate from MMKV library to file-based storage
This commit is contained in:
@@ -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.
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
Reference in New Issue
Block a user