add crunchyroll login and browse (no parsing for now)

This commit is contained in:
Jannik 2021-12-04 19:55:26 +01:00
parent eafefd9a51
commit e7d057bfb8
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
3 changed files with 143 additions and 17 deletions

View File

@ -1,6 +1,9 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
}
android {
compileSdkVersion 30
@ -43,6 +46,7 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
@ -68,6 +72,10 @@ dependencies {
implementation 'com.afollestad.material-dialogs:core:3.3.0'
implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0'
implementation 'com.github.kittinunf.fuel:fuel:2.3.1'
implementation 'com.github.kittinunf.fuel:fuel-android:2.3.1'
implementation 'com.github.kittinunf.fuel:fuel-json:2.3.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

View File

@ -0,0 +1,105 @@
package org.mosad.teapod.parser.crunchyroll
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.json.FuelJson
import com.github.kittinunf.fuel.json.responseJson
import com.github.kittinunf.result.Result
import kotlinx.coroutines.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
private val json = Json { ignoreUnknownKeys = true }
class Cruncyroll {
private val baseUrl = "https://beta-api.crunchyroll.com"
private var accessToken = ""
private var tokenType = ""
fun login(username: String, password: String): Boolean = runBlocking {
val tokenEndpoint = "/auth/v1/token"
val formData = listOf(
"username" to username,
"password" to password,
"grant_type" to "password",
"scope" to "offline_access"
)
withContext(Dispatchers.IO) {
val (request, response, result) = Fuel.post("$baseUrl$tokenEndpoint", parameters = formData)
.header("Content-Type", "application/x-www-form-urlencoded")
.appendHeader(
"Authorization",
"Basic "
)
.responseJson()
result.component1()?.obj()?.let {
accessToken = it.get("access_token").toString()
tokenType = it.get("token_type").toString()
}
// println("request: $request")
// println("response: $response")
// println("response: $result")
println("login complete with code ${response.statusCode}")
return@withContext response.statusCode == 200
}
return@runBlocking false
}
// TODO get/post difference
private suspend fun requestA(endpoint: String): Result<FuelJson, FuelError> = coroutineScope {
return@coroutineScope (Dispatchers.IO) {
val (request, response, result) = Fuel.get("$baseUrl$endpoint")
.header("Authorization", "$tokenType $accessToken")
.responseJson()
// println("request request: $request")
// println("request response: $response")
// println("request result: $result")
result
}
}
// TESTING
@Serializable
data class Test(val total: Int, val items: List<Item>)
@Serializable
data class Item(val channel_id: String, val description: String)
// TODO sort_by, default alphabetical, n, locale de-DE
suspend fun browse() {
val browseEndpoint = "/content/v1/browse"
val result = requestA(browseEndpoint)
println("${result.component1()?.obj()?.get("total")}")
val test = json.decodeFromString<Test>(result.component1()?.obj()?.toString()!!)
println(test)
}
suspend fun search() {
val searchEndpoint = "/content/v1/search"
val result = requestA(searchEndpoint)
println("${result.component1()?.obj()?.get("total")}")
val test = json.decodeFromString<Test>(result.component1()?.obj()?.toString()!!)
println(test)
}
}

View File

@ -36,6 +36,7 @@ import kotlinx.coroutines.*
import org.mosad.teapod.R
import org.mosad.teapod.databinding.ActivityMainBinding
import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.parser.crunchyroll.Cruncyroll
import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.ui.activity.main.fragments.AccountFragment
@ -150,26 +151,38 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
EncryptedPreferences.readCredentials(this)
StorageController.load(this)
// show onboarding
// show onboarding TODO rework
if (EncryptedPreferences.password.isEmpty()) {
showOnboarding()
} else {
try {
if (!AoDParser.login()) {
showLoginDialog()
}
} catch (ex: SocketTimeoutException) {
Log.w(javaClass.name, "Timeout during login!")
val crunchy = Cruncyroll()
crunchy.login(EncryptedPreferences.login, EncryptedPreferences.password)
println("after login")
// show waring dialog before finishing
MaterialDialog(this).show {
title(R.string.dialog_timeout_head)
message(R.string.dialog_timeout_desc)
onDismiss { exitAndRemoveTask() }
}
}
runBlocking { crunchy.browse() }
}
// if (EncryptedPreferences.password.isEmpty()) {
// showOnboarding()
// } else {
// try {
// if (!AoDParser.login()) {
// showLoginDialog()
// }
// } catch (ex: SocketTimeoutException) {
// Log.w(javaClass.name, "Timeout during login!")
//
// // show waring dialog before finishing
// MaterialDialog(this).show {
// title(R.string.dialog_timeout_head)
// message(R.string.dialog_timeout_desc)
// onDismiss { exitAndRemoveTask() }
// }
// }
// }
runBlocking { loadingJob.await() } // wait for initial loading to finish
}
Log.i(javaClass.name, "loading and login in $time ms")