update libraries

* kotlinx-coroutines-android 1.5.1 -> 1.5.2
* exoplayer 2.14.2 -> 2.15.0
* jsoup 1.13.1 -> 1.14.2
* gradle agp 7.0.1 -> 7.0.2
This commit is contained in:
Jannik 2021-09-05 13:43:27 +02:00
parent 39e740cd92
commit 3935f37267
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
4 changed files with 39 additions and 42 deletions

View File

@ -11,7 +11,7 @@ android {
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 30
versionCode 4200 //00.04.200 versionCode 4200 //00.04.200
versionName "0.5.0-alpha1" versionName "0.5.0-alpha2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "build_time", buildTime() resValue "string", "build_time", buildTime()
@ -41,8 +41,8 @@ android {
dependencies { dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"]) implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
@ -55,14 +55,14 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.4.0'
implementation 'com.google.code.gson:gson:2.8.7' implementation 'com.google.code.gson:gson:2.8.8'
implementation 'com.google.android.exoplayer:exoplayer-core:2.14.2' implementation 'com.google.android.exoplayer:exoplayer-core:2.15.0'
implementation 'com.google.android.exoplayer:exoplayer-hls:2.14.2' implementation 'com.google.android.exoplayer:exoplayer-hls:2.15.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.14.2' implementation 'com.google.android.exoplayer:exoplayer-dash:2.15.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.14.2' implementation 'com.google.android.exoplayer:exoplayer-ui:2.15.0'
implementation 'com.google.android.exoplayer:extension-mediasession:2.14.2' implementation 'com.google.android.exoplayer:extension-mediasession:2.15.0'
implementation 'org.jsoup:jsoup:1.13.1' implementation 'org.jsoup:jsoup:1.14.2'
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.afollestad.material-dialogs:core:3.3.0' implementation 'com.afollestad.material-dialogs:core:3.3.0'

View File

@ -31,8 +31,10 @@ import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.util.* import org.mosad.teapod.util.*
import org.mosad.teapod.util.DataTypes.MediaType import org.mosad.teapod.util.DataTypes.MediaType
import java.io.IOException import java.io.IOException
import java.net.CookieStore
import java.util.* import java.util.*
import kotlin.random.Random import kotlin.random.Random
import kotlin.reflect.jvm.jvmName
object AoDParser { object AoDParser {
@ -43,7 +45,7 @@ object AoDParser {
private const val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0" private const val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0"
private var sessionCookies = mutableMapOf<String, String>() private lateinit var cookieStore: CookieStore
private var csrfToken: String = "" private var csrfToken: String = ""
private var loginSuccess = false private var loginSuccess = false
@ -60,23 +62,22 @@ object AoDParser {
fun login(): Boolean = runBlocking { fun login(): Boolean = runBlocking {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
// get the authenticity token // get the authenticity token and cookies
val resAuth = Jsoup.connect(baseUrl + loginPath) val conAuth = Jsoup.connect(baseUrl + loginPath)
.header("User-Agent", userAgent) .header("User-Agent", userAgent)
.execute()
val authenticityToken = resAuth.parse().select("meta[name=csrf-token]").attr("content") cookieStore = conAuth.cookieStore()
val authCookies = resAuth.cookies() csrfToken = conAuth.execute().parse().select("meta[name=csrf-token]").attr("content")
//Log.d(javaClass.name, "Received authenticity token: $authenticityToken") Log.d(AoDParser::class.jvmName, "Received authenticity token: $csrfToken")
//Log.d(javaClass.name, "Received authenticity cookies: $authCookies") Log.d(AoDParser::class.jvmName, "Received authenticity cookies: $cookieStore")
val data = mapOf( val data = mapOf(
Pair("user[login]", EncryptedPreferences.login), Pair("user[login]", EncryptedPreferences.login),
Pair("user[password]", EncryptedPreferences.password), Pair("user[password]", EncryptedPreferences.password),
Pair("user[remember_me]", "1"), Pair("user[remember_me]", "1"),
Pair("commit", "Einloggen"), Pair("commit", "Einloggen"),
Pair("authenticity_token", authenticityToken) Pair("authenticity_token", csrfToken)
) )
val resLogin = Jsoup.connect(baseUrl + loginPath) val resLogin = Jsoup.connect(baseUrl + loginPath)
@ -84,14 +85,12 @@ object AoDParser {
.timeout(60000) // login can take some time default is 60000 (60 sec) .timeout(60000) // login can take some time default is 60000 (60 sec)
.data(data) .data(data)
.postDataCharset("UTF-8") .postDataCharset("UTF-8")
.cookies(authCookies) .cookieStore(cookieStore)
.execute() .execute()
//println(resLogin.body()) //println(resLogin.body())
sessionCookies = resLogin.cookies()
loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.") loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.")
Log.i(javaClass.name, "Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess") Log.i(AoDParser::class.jvmName, "Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess")
loginSuccess loginSuccess
} }
@ -119,7 +118,7 @@ object AoDParser {
aodMediaList.add(this) aodMediaList.add(this)
} }
} catch (exn:NullPointerException) { } catch (exn:NullPointerException) {
Log.e(javaClass.name, "Error while loading media $aodId", exn) Log.e(AoDParser::class.jvmName, "Error while loading media $aodId", exn)
AoDMediaNone AoDMediaNone
} }
} }
@ -131,7 +130,7 @@ object AoDParser {
return coroutineScope { return coroutineScope {
async(Dispatchers.IO) { async(Dispatchers.IO) {
val res = Jsoup.connect(baseUrl + subscriptionPath) val res = Jsoup.connect(baseUrl + subscriptionPath)
.cookies(sessionCookies) .cookieStore(cookieStore)
.get() .get()
return@async res.select("a:contains(Anime-Abo)").text() return@async res.select("a:contains(Anime-Abo)").text()
@ -149,7 +148,7 @@ object AoDParser {
episode.watched = true episode.watched = true
sendCallback(episode.watchedCallback) sendCallback(episode.watchedCallback)
Log.d(javaClass.name, "Marked episode ${episode.mediaId} as watched") Log.d(AoDParser::class.jvmName, "Marked episode ${episode.mediaId} as watched")
} }
// TODO don't use jsoup here // TODO don't use jsoup here
@ -166,11 +165,11 @@ object AoDParser {
try { try {
Jsoup.connect(baseUrl + callbackPath) Jsoup.connect(baseUrl + callbackPath)
.ignoreContentType(true) .ignoreContentType(true)
.cookies(sessionCookies) .cookieStore(cookieStore)
.headers(headers) .headers(headers)
.execute() .execute()
} catch (ex: IOException) { } catch (ex: IOException) {
Log.e(javaClass.name, "Callback for $callbackPath failed.", ex) Log.e(AoDParser::class.jvmName, "Callback for $callbackPath failed.", ex)
} }
} }
} }
@ -199,7 +198,7 @@ object AoDParser {
} }
) )
Log.i(javaClass.name, "Total library size is: ${guiMediaList.size}") Log.i(AoDParser::class.jvmName, "Total library size is: ${guiMediaList.size}")
} }
} }
@ -284,7 +283,7 @@ object AoDParser {
} }
} }
Log.i(javaClass.name, "loaded home") Log.i(AoDParser::class.jvmName, "loaded home")
} }
} }
@ -295,27 +294,27 @@ object AoDParser {
*/ */
private suspend fun loadMediaAsync(aodId: Int): Deferred<AoDMedia> = coroutineScope { private suspend fun loadMediaAsync(aodId: Int): Deferred<AoDMedia> = coroutineScope {
return@coroutineScope async (Dispatchers.IO) { return@coroutineScope async (Dispatchers.IO) {
if (sessionCookies.isEmpty()) login() // TODO is this needed? if (cookieStore.cookies.isEmpty()) login() // TODO is this needed?
// return none object, if login wasn't successful // return none object, if login wasn't successful
if (!loginSuccess) { if (!loginSuccess) {
Log.w(javaClass.name, "Login was not successful") Log.w(AoDParser::class.jvmName, "Login was not successful")
return@async AoDMediaNone return@async AoDMediaNone
} }
// get the media page // get the media page
val res = Jsoup.connect("$baseUrl/anime/$aodId") val res = Jsoup.connect("$baseUrl/anime/$aodId")
.cookies(sessionCookies) .cookieStore(cookieStore)
.get() .get()
// println(res) // println(res)
if (csrfToken.isEmpty()) { if (csrfToken.isEmpty()) {
csrfToken = res.select("meta[name=csrf-token]").attr("content") csrfToken = res.select("meta[name=csrf-token]").attr("content")
Log.d(javaClass.name, "New csrf token is $csrfToken") Log.d(AoDParser::class.jvmName, "New csrf token is $csrfToken")
} }
// playlist parsing TODO can this be async to the general info parsing? // playlist parsing TODO can this be async to the general info parsing?
val besides = res.select("div.besides").first() val besides = res.select("div.besides").first()!!
val aodPlaylists = besides.select("input.streamstarter_html5").map { streamstarter -> val aodPlaylists = besides.select("input.streamstarter_html5").map { streamstarter ->
parsePlaylistAsync( parsePlaylistAsync(
streamstarter.attr("data-playlist"), streamstarter.attr("data-playlist"),
@ -354,7 +353,7 @@ object AoDParser {
if (mediaId != null) { if (mediaId != null) {
ItemMedia(mediaId, mediaTitle, mediaImage) ItemMedia(mediaId, mediaTitle, mediaImage)
} else { } else {
Log.i(javaClass.name, "MediaId for similar to $aodId was null") Log.i(AoDParser::class.jvmName, "MediaId for similar to $aodId was null")
null null
} }
} }
@ -376,7 +375,7 @@ object AoDParser {
AoDEpisodeInfo(mediaId, episodeShortDesc, episodeWatched, episodeWatchedCallback) AoDEpisodeInfo(mediaId, episodeShortDesc, episodeWatched, episodeWatchedCallback)
} else { } else {
Log.i(javaClass.name, "Episode info for $aodId has empty streamstarter_html5 ") Log.i(AoDParser::class.jvmName, "Episode info for $aodId has empty streamstarter_html5 ")
null null
} }
}.associateBy { it.aodMediaId } }.associateBy { it.aodMediaId }
@ -441,7 +440,7 @@ object AoDParser {
val res = Jsoup.connect(baseUrl + playlistPath) val res = Jsoup.connect(baseUrl + playlistPath)
.ignoreContentType(true) .ignoreContentType(true)
.cookies(sessionCookies) .cookieStore(cookieStore)
.headers(headers) .headers(headers)
.timeout(120000) // loading the playlist can take some time .timeout(120000) // loading the playlist can take some time
.execute() .execute()

View File

@ -16,9 +16,7 @@
android:layout_gravity="center" android:layout_gravity="center"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:foreground="@drawable/ripple_background" android:foreground="@drawable/ripple_background"
app:controller_layout_id="@layout/player_controls" app:controller_layout_id="@layout/player_controls" />
app:fastforward_increment="10000"
app:rewind_increment="10000" />
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/loading" android:id="@+id/loading"

View File

@ -6,7 +6,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.0.1' classpath 'com.android.tools.build:gradle:7.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong