[feat] Smart Server Selection

This commit is contained in:
acite
2025-09-07 23:04:15 +08:00
parent aacd226260
commit f6583ffcf1
3 changed files with 40 additions and 10 deletions

View File

@@ -3,6 +3,8 @@ package com.acitelight.aether.service
import android.content.Context
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import okhttp3.CertificatePinner
import okhttp3.HttpUrl
@@ -12,6 +14,9 @@ import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.ByteArrayInputStream
import java.net.HttpURLConnection
import java.net.InetAddress
import java.net.URL
import java.security.KeyStore
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
@@ -88,19 +93,43 @@ object ApiClient {
var api: ApiInterface? = null
fun apply(url: String, crt: String)
{
suspend fun apply(urls: String, crt: String): String? {
try {
domain = url.toHttpUrlOrNull()?.host !!
val urlList = urls.split(";").map { it.trim() }
var selectedUrl: String? = null
for (url in urlList) {
val host = url.toHttpUrlOrNull()?.host
if (host != null && pingHost(host)) {
selectedUrl = url
break
}
}
if (selectedUrl == null) {
throw Exception("No reachable URL found")
}
domain = selectedUrl.toHttpUrlOrNull()?.host ?: ""
cert = crt
base = url
base = selectedUrl
api = createRetrofit().create(ApiInterface::class.java)
}catch (e: Exception)
{
return base
} catch (e: Exception) {
api = null
base = ""
domain = ""
cert = ""
return null
}
}
private suspend fun pingHost(host: String): Boolean = withContext(Dispatchers.IO) {
return@withContext try {
val address = InetAddress.getByName(host)
address.isReachable(200)
} catch (e: Exception) {
false
}
}
}

View File

@@ -1,6 +1,7 @@
package com.acitelight.aether.viewModel
import android.app.Application
import android.widget.Toast
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
@@ -86,7 +87,7 @@ class HomeScreenViewModel(application: Application) : AndroidViewModel(applicati
if(u=="" || p=="" || ur=="" || c=="") return@launch
try{
ApiClient.apply(ur, c)
val usedUrl = ApiClient.apply(ur, c)
if (MediaManager.token == "null")
MediaManager.token = AuthManager.fetchToken(

View File

@@ -76,14 +76,14 @@ class MeScreenViewModel(application: Application) : AndroidViewModel(application
if (u == "" || c == "" || p == "" || us == "") return@launch
try {
ApiClient.apply(u, c)
val usedUrl = ApiClient.apply(u, c)
MediaManager.token = AuthManager.fetchToken(
us,
p
)!!
Global.loggedIn = true
Toast.makeText(context, "Server Updated", Toast.LENGTH_SHORT).show()
Toast.makeText(context, "Server Updated, Used Url: $usedUrl", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
print(e.message)
Toast.makeText(context, "Invalid Account or Server Information", Toast.LENGTH_SHORT).show()