made AoDParser an object
This commit is contained in:
parent
a25ec81f6b
commit
4c274eb062
|
@ -32,18 +32,11 @@ import androidx.fragment.app.commit
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import org.mosad.teapod.parser.AoDParser
|
import org.mosad.teapod.parser.AoDParser
|
||||||
import org.mosad.teapod.preferences.EncryptedPreferences
|
import org.mosad.teapod.preferences.EncryptedPreferences
|
||||||
import org.mosad.teapod.ui.fragments.MediaFragment
|
|
||||||
import org.mosad.teapod.ui.fragments.AccountFragment
|
|
||||||
import org.mosad.teapod.ui.components.LoginDialog
|
import org.mosad.teapod.ui.components.LoginDialog
|
||||||
import org.mosad.teapod.ui.fragments.HomeFragment
|
import org.mosad.teapod.ui.fragments.*
|
||||||
import org.mosad.teapod.ui.fragments.LibraryFragment
|
|
||||||
import org.mosad.teapod.ui.fragments.SearchFragment
|
|
||||||
import org.mosad.teapod.ui.fragments.LoadingFragment
|
|
||||||
import org.mosad.teapod.util.StorageController
|
import org.mosad.teapod.util.StorageController
|
||||||
import org.mosad.teapod.util.TMDBApiController
|
import org.mosad.teapod.util.TMDBApiController
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
@ -117,27 +110,11 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
||||||
showLoginDialog(true)
|
showLoginDialog(true)
|
||||||
} else {
|
} else {
|
||||||
// try to login in, as most sites can only bee loaded once loged in
|
// try to login in, as most sites can only bee loaded once loged in
|
||||||
if (!AoDParser().login()) showLoginDialog(false)
|
if (!AoDParser.login()) showLoginDialog(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageController.load(this)
|
StorageController.load(this)
|
||||||
|
AoDParser.initialLoading()
|
||||||
// move to AoDParser
|
|
||||||
val newEPJob = GlobalScope.async {
|
|
||||||
AoDParser().listNewEpisodes()
|
|
||||||
}
|
|
||||||
|
|
||||||
val listJob = GlobalScope.async {
|
|
||||||
AoDParser().listAnimes() // initially load all media
|
|
||||||
}
|
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
newEPJob.await()
|
|
||||||
listJob.await()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO load home screen, can be parallel to listAnimes
|
|
||||||
}
|
}
|
||||||
Log.i(javaClass.name, "login and list in $time ms")
|
Log.i(javaClass.name, "login and list in $time ms")
|
||||||
}
|
}
|
||||||
|
@ -156,7 +133,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the streams for the selected media
|
// load the streams for the selected media
|
||||||
val media = AoDParser().getMediaById(mediaId)
|
val media = AoDParser.getMediaById(mediaId)
|
||||||
val tmdb = TMDBApiController().search(media.info.title, media.type)
|
val tmdb = TMDBApiController().search(media.info.title, media.type)
|
||||||
|
|
||||||
val mediaFragment = MediaFragment(media, tmdb)
|
val mediaFragment = MediaFragment(media, tmdb)
|
||||||
|
@ -182,7 +159,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
||||||
LoginDialog(this, firstTry).positiveButton {
|
LoginDialog(this, firstTry).positiveButton {
|
||||||
EncryptedPreferences.saveCredentials(login, password, context)
|
EncryptedPreferences.saveCredentials(login, password, context)
|
||||||
|
|
||||||
if (!AoDParser().login()) {
|
if (!AoDParser.login()) {
|
||||||
showLoginDialog(false)
|
showLoginDialog(false)
|
||||||
Log.w(javaClass.name, "Login failed, please try again.")
|
Log.w(javaClass.name, "Login failed, please try again.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Teapod
|
||||||
|
*
|
||||||
|
* Copyright 2020 <seil0@mosad.xyz>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
package org.mosad.teapod.parser
|
package org.mosad.teapod.parser
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -13,26 +35,21 @@ import org.mosad.teapod.util.Media
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
object AoDParser {
|
||||||
* maybe AoDParser as object would be useful
|
|
||||||
*/
|
|
||||||
class AoDParser {
|
|
||||||
|
|
||||||
private val baseUrl = "https://www.anime-on-demand.de"
|
private const val baseUrl = "https://www.anime-on-demand.de"
|
||||||
private val loginPath = "/users/sign_in"
|
private const val loginPath = "/users/sign_in"
|
||||||
private val libraryPath = "/animes"
|
private const val libraryPath = "/animes"
|
||||||
|
|
||||||
private val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
|
private const val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
|
||||||
|
|
||||||
companion object {
|
private var sessionCookies = mutableMapOf<String, String>()
|
||||||
private var csrfToken: String = ""
|
private var csrfToken: String = ""
|
||||||
private var sessionCookies = mutableMapOf<String, String>()
|
private var loginSuccess = false
|
||||||
private var loginSuccess = false
|
|
||||||
|
|
||||||
val mediaList = arrayListOf<Media>()
|
val mediaList = arrayListOf<Media>()
|
||||||
val itemMediaList = arrayListOf<ItemMedia>()
|
val itemMediaList = arrayListOf<ItemMedia>()
|
||||||
val newEpisodesList = arrayListOf<ItemMedia>()
|
val newEpisodesList = arrayListOf<ItemMedia>()
|
||||||
}
|
|
||||||
|
|
||||||
fun login(): Boolean = runBlocking {
|
fun login(): Boolean = runBlocking {
|
||||||
|
|
||||||
|
@ -74,9 +91,64 @@ class AoDParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list all animes from the website
|
* initially load all media and home screen data
|
||||||
|
* -> blocking
|
||||||
*/
|
*/
|
||||||
fun listAnimes(): ArrayList<Media> = runBlocking {
|
fun initialLoading() = runBlocking {
|
||||||
|
val newEPJob = GlobalScope.async {
|
||||||
|
listNewEpisodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
val listJob = GlobalScope.async {
|
||||||
|
listAnimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
newEPJob.await()
|
||||||
|
listJob.await()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a media by it's ID (int)
|
||||||
|
* @return Media
|
||||||
|
*/
|
||||||
|
fun getMediaById(mediaId: Int): Media {
|
||||||
|
val media = mediaList.first { it.id == mediaId }
|
||||||
|
|
||||||
|
if (media.episodes.isEmpty()) {
|
||||||
|
loadStreams(media)
|
||||||
|
}
|
||||||
|
|
||||||
|
return media
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO don't use jsoup here
|
||||||
|
fun sendCallback(callbackPath: String) = GlobalScope.launch {
|
||||||
|
val headers = mutableMapOf(
|
||||||
|
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
|
||||||
|
Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"),
|
||||||
|
Pair("Accept-Encoding", "gzip, deflate, br"),
|
||||||
|
Pair("X-CSRF-Token", csrfToken),
|
||||||
|
Pair("X-Requested-With", "XMLHttpRequest"),
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
Jsoup.connect(baseUrl + callbackPath)
|
||||||
|
.ignoreContentType(true)
|
||||||
|
.cookies(sessionCookies)
|
||||||
|
.headers(headers)
|
||||||
|
.execute()
|
||||||
|
}
|
||||||
|
} catch (ex: IOException) {
|
||||||
|
Log.e(javaClass.name, "Callback for $callbackPath failed.", ex)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load all media from aod into itemMediaList and mediaList
|
||||||
|
*/
|
||||||
|
private fun listAnimes() = runBlocking {
|
||||||
if (sessionCookies.isEmpty()) login()
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
|
@ -109,12 +181,13 @@ class AoDParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(javaClass.name, "Total library size is: ${mediaList.size}")
|
Log.i(javaClass.name, "Total library size is: ${mediaList.size}")
|
||||||
|
|
||||||
return@withContext mediaList
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun listNewEpisodes() = runBlocking {
|
/**
|
||||||
|
* load all new episodes from AoD into newEpisodesList
|
||||||
|
*/
|
||||||
|
private fun listNewEpisodes() = runBlocking {
|
||||||
if (sessionCookies.isEmpty()) login()
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
|
@ -137,16 +210,6 @@ class AoDParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMediaById(mediaId: Int): Media {
|
|
||||||
val media = mediaList.first { it.id == mediaId }
|
|
||||||
|
|
||||||
if (media.episodes.isEmpty()) {
|
|
||||||
loadStreams(media)
|
|
||||||
}
|
|
||||||
|
|
||||||
return media
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load streams for the media path, movies have one episode
|
* load streams for the media path, movies have one episode
|
||||||
* @param media is used as call ba reference
|
* @param media is used as call ba reference
|
||||||
|
@ -283,27 +346,4 @@ class AoDParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendCallback(callbackPath: String) = GlobalScope.launch {
|
|
||||||
val headers = mutableMapOf(
|
|
||||||
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
|
|
||||||
Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"),
|
|
||||||
Pair("Accept-Encoding", "gzip, deflate, br"),
|
|
||||||
Pair("X-CSRF-Token", csrfToken),
|
|
||||||
Pair("X-Requested-With", "XMLHttpRequest"),
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
Jsoup.connect(baseUrl + callbackPath)
|
|
||||||
.ignoreContentType(true)
|
|
||||||
.cookies(sessionCookies)
|
|
||||||
.headers(headers)
|
|
||||||
.execute()
|
|
||||||
}
|
|
||||||
} catch (ex: IOException) {
|
|
||||||
Log.e(javaClass.name, "Callback for $callbackPath failed.", ex)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class AccountFragment : Fragment() {
|
||||||
LoginDialog(requireContext(), firstTry).positiveButton {
|
LoginDialog(requireContext(), firstTry).positiveButton {
|
||||||
EncryptedPreferences.saveCredentials(login, password, context)
|
EncryptedPreferences.saveCredentials(login, password, context)
|
||||||
|
|
||||||
if (!AoDParser().login()) {
|
if (!AoDParser.login()) {
|
||||||
showLoginDialog(false)
|
showLoginDialog(false)
|
||||||
Log.w(javaClass.name, "Login failed, please try again.")
|
Log.w(javaClass.name, "Login failed, please try again.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
|
||||||
playStream(media.episodes[position].streamUrl)
|
playStream(media.episodes[position].streamUrl)
|
||||||
|
|
||||||
// update watched state
|
// update watched state
|
||||||
AoDParser().sendCallback(media.episodes[position].watchedCallback)
|
AoDParser.sendCallback(media.episodes[position].watchedCallback)
|
||||||
adapterRecEpisodes.updateWatchedState(true, position)
|
adapterRecEpisodes.updateWatchedState(true, position)
|
||||||
adapterRecEpisodes.notifyDataSetChanged()
|
adapterRecEpisodes.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue