refactor: move api request logic completely out of core
This commit is contained in:
parent
f606eb2e33
commit
0a5b0f532a
5 changed files with 74 additions and 57 deletions
|
|
@ -11,6 +11,8 @@ import io.ktor.client.plugins.plugin
|
|||
import io.ktor.client.plugins.websocket.WebSockets
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.contentType
|
||||
import io.ktor.http.userAgent
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.util.appendAll
|
||||
|
|
@ -28,7 +30,7 @@ class ApiClient {
|
|||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
val client = HttpClient {
|
||||
internal val client = HttpClient {
|
||||
expectSuccess = true
|
||||
install(ContentNegotiation) {
|
||||
json(ApiConstants.json)
|
||||
|
|
@ -37,6 +39,7 @@ class ApiClient {
|
|||
install(HttpCookies)
|
||||
defaultRequest {
|
||||
url("https://discord.com/api/v9/")
|
||||
contentType(ContentType.Application.Json)
|
||||
userAgent(ApiConstants.userAgent)
|
||||
headers.appendAll(ApiConstants.baseHeaders)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package moe.lava.neon.api.endpoints
|
||||
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import kotlinx.serialization.Serializable
|
||||
import moe.lava.neon.api.ApiClient
|
||||
|
||||
@Serializable
|
||||
data class ExperimentResponse(
|
||||
val fingerprint: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
private data class LoginRequest(
|
||||
val login: String,
|
||||
val password: String,
|
||||
val undelete: Boolean = false,
|
||||
val loginSource: String? = null,
|
||||
val giftCodeSkuId: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class LoginResponse(
|
||||
val userId: String,
|
||||
val token: String,
|
||||
val userSettings: UserSettings,
|
||||
) {
|
||||
@Serializable
|
||||
data class UserSettings(val locale: String, val theme: String)
|
||||
}
|
||||
|
||||
suspend fun ApiClient.getExperiments() = client.get("experiments") {
|
||||
parameter("with_guild_experiments", "true")
|
||||
}.body<ExperimentResponse>()
|
||||
|
||||
suspend fun ApiClient.login(email: String, password: String, fingerprint: String) = client.post("auth/login") {
|
||||
header("X-Fingerprint", fingerprint)
|
||||
setBody(LoginRequest(
|
||||
login = email,
|
||||
password = password,
|
||||
))
|
||||
}.body<LoginResponse>()
|
||||
|
|
@ -21,8 +21,6 @@ kotlin {
|
|||
implementation(project(":api:gateway"))
|
||||
implementation(project(":api:rest"))
|
||||
implementation(project(":common"))
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.serialization.kotlinx.json)
|
||||
|
||||
implementation(project.dependencies.platform(libs.koin.bom))
|
||||
implementation(libs.koin.core)
|
||||
|
|
|
|||
|
|
@ -1,43 +1,14 @@
|
|||
package moe.lava.neon.core.repository
|
||||
|
||||
import co.touchlab.kermit.Logger
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.contentType
|
||||
import kotlinx.serialization.Serializable
|
||||
import moe.lava.neon.api.ApiClient
|
||||
import moe.lava.neon.api.endpoints.getExperiments
|
||||
import moe.lava.neon.api.endpoints.login
|
||||
import moe.lava.neon.core.AppSettings
|
||||
|
||||
@Serializable
|
||||
private data class ExperimentResponse(
|
||||
val fingerprint: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
private data class LoginRequest(
|
||||
val login: String,
|
||||
val password: String,
|
||||
val undelete: Boolean = false,
|
||||
val loginSource: String? = null,
|
||||
val giftCodeSkuId: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
private data class LoginResponse(
|
||||
val userId: String,
|
||||
val token: String,
|
||||
val userSettings: UserSettings,
|
||||
) {
|
||||
@Serializable
|
||||
data class UserSettings(val locale: String, val theme: String)
|
||||
}
|
||||
|
||||
sealed class AuthResponse {
|
||||
// TODO: Specify all possible error types here
|
||||
data class Failed(val error: Throwable) : AuthResponse()
|
||||
data class Success(val token: String) : AuthResponse()
|
||||
// TODO
|
||||
// data class MFARequested() : AuthResponse()
|
||||
|
|
@ -57,24 +28,23 @@ class AuthRepository internal constructor(
|
|||
email: String,
|
||||
password: String,
|
||||
): AuthResponse {
|
||||
if (fingerprint == null) {
|
||||
fingerprint = api.client.get("experiments") {
|
||||
parameter("with_guild_experiments", "true")
|
||||
}.body<ExperimentResponse>().fingerprint
|
||||
}
|
||||
try {
|
||||
if (fingerprint == null) {
|
||||
fingerprint = api.getExperiments().fingerprint
|
||||
}
|
||||
|
||||
val res = api.client.post("auth/login") {
|
||||
header("X-Fingerprint", fingerprint)
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(LoginRequest(
|
||||
login = email,
|
||||
val login = api.login(
|
||||
email = email,
|
||||
password = password,
|
||||
))
|
||||
fingerprint = fingerprint!!,
|
||||
)
|
||||
logger.i { "Login success $login" }
|
||||
this.token = login.token
|
||||
|
||||
return AuthResponse.Success(login.token)
|
||||
} catch (e: Throwable) {
|
||||
return AuthResponse.Failed(e)
|
||||
}
|
||||
val body = res.body<LoginResponse>()
|
||||
logger.i { "Login success $body" }
|
||||
this.token = body.token
|
||||
return AuthResponse.Success(body.token)
|
||||
}
|
||||
|
||||
fun login(token: String): String {
|
||||
|
|
|
|||
|
|
@ -122,13 +122,13 @@ class LoginViewModel(
|
|||
}
|
||||
|
||||
suspend fun login(email: String, password: String): LoginResult {
|
||||
return try {
|
||||
when (val res = auth.login(email, password)) {
|
||||
is AuthResponse.Success -> LoginResult.Success
|
||||
return when (val res = auth.login(email, password)) {
|
||||
is AuthResponse.Success -> LoginResult.Success
|
||||
is AuthResponse.Failed -> {
|
||||
val e = res.error
|
||||
logger.e(e) { "Login failed" }
|
||||
LoginResult.Failed(e.toString())
|
||||
}
|
||||
} catch(e: Throwable) {
|
||||
logger.e(e) { "Login failed" }
|
||||
LoginResult.Failed(e.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue