add OnItemClickListener
This commit is contained in:
parent
b94b86b866
commit
c473fce19a
|
@ -1,8 +1,7 @@
|
||||||
package org.mosad.teapod.parser
|
package org.mosad.teapod.parser
|
||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import org.json.JSONObject
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.jsoup.Connection
|
import org.jsoup.Connection
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.mosad.teapod.util.GUIMedia
|
import org.mosad.teapod.util.GUIMedia
|
||||||
|
@ -12,20 +11,20 @@ class AoDParser {
|
||||||
private val baseURL = "https://www.anime-on-demand.de"
|
private val baseURL = "https://www.anime-on-demand.de"
|
||||||
private val loginPath = "/users/sign_in"
|
private val loginPath = "/users/sign_in"
|
||||||
|
|
||||||
|
// TODO
|
||||||
private val login = ""
|
private val login = ""
|
||||||
private val pwd = ""
|
private val pwd = ""
|
||||||
|
|
||||||
private fun login(): MutableMap<String, String> = runBlocking {
|
private var sessionCookies = mutableMapOf<String, String>()
|
||||||
|
private var loginSuccess = false
|
||||||
|
|
||||||
|
private fun login() = runBlocking {
|
||||||
|
|
||||||
val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
|
val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val con = Jsoup.connect(baseURL)
|
|
||||||
|
|
||||||
|
|
||||||
// get the authenticity token
|
// get the authenticity token
|
||||||
val resAuth = con.url(baseURL + loginPath)//Jsoup.connect(baseURL + loginPath)
|
val resAuth = Jsoup.connect(baseURL + loginPath)
|
||||||
.header("User-Agent", userAgent)
|
.header("User-Agent", userAgent)
|
||||||
.execute()
|
.execute()
|
||||||
|
|
||||||
|
@ -52,40 +51,99 @@ class AoDParser {
|
||||||
|
|
||||||
//println(resLogin.body())
|
//println(resLogin.body())
|
||||||
|
|
||||||
val loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.")
|
loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.")
|
||||||
println("Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess")
|
println("Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess")
|
||||||
|
|
||||||
return@withContext resLogin.cookies()
|
sessionCookies = resLogin.cookies()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.anime-on-demand.de/animes
|
// https://www.anime-on-demand.de/animes
|
||||||
fun listAnime(): ArrayList<GUIMedia> = runBlocking {
|
fun listAnimes(): ArrayList<GUIMedia> = runBlocking {
|
||||||
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val cookies = login()
|
|
||||||
|
|
||||||
|
|
||||||
val res = Jsoup.connect("$baseURL/animes")
|
val res = Jsoup.connect("$baseURL/animes")
|
||||||
.cookies(cookies)
|
.cookies(sessionCookies)
|
||||||
.get()
|
.get()
|
||||||
|
|
||||||
//println(res)
|
//println(res)
|
||||||
|
|
||||||
val anime = arrayListOf<GUIMedia>()
|
val animes = arrayListOf<GUIMedia>()
|
||||||
res.select("div.animebox").forEach {
|
res.select("div.animebox").forEach {
|
||||||
val media = GUIMedia(
|
val media = GUIMedia(
|
||||||
it.select("h3.animebox-title").text(),
|
it.select("h3.animebox-title").text(),
|
||||||
it.select("p.animebox-image").select("img").attr("src"),
|
it.select("p.animebox-image").select("img").attr("src"),
|
||||||
it.select("p.animebox-link").select("a").attr("href"),
|
it.select("p.animebox-shorttext").text(),
|
||||||
it.select("p.animebox-shorttext").text()
|
it.select("p.animebox-link").select("a").attr("href")
|
||||||
)
|
)
|
||||||
|
|
||||||
anime.add(media)
|
animes.add(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
println("got ${anime.size} anime")
|
println("got ${animes.size} anime")
|
||||||
|
|
||||||
return@withContext anime
|
return@withContext animes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadDetails(mediaPath: String) = runBlocking {
|
||||||
|
if (sessionCookies.isEmpty()) login()
|
||||||
|
|
||||||
|
if (!loginSuccess) {
|
||||||
|
println("please log in")
|
||||||
|
return@runBlocking
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
println(baseURL + mediaPath)
|
||||||
|
|
||||||
|
val res = Jsoup.connect(baseURL + mediaPath)
|
||||||
|
.cookies(sessionCookies)
|
||||||
|
.get()
|
||||||
|
|
||||||
|
//println(res)
|
||||||
|
|
||||||
|
val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist")
|
||||||
|
println(playlists.first())
|
||||||
|
|
||||||
|
val csrfToken = res.select("meta[name=csrf-token]").attr("content")
|
||||||
|
println("csrf token is: $csrfToken")
|
||||||
|
|
||||||
|
loadStreamInfo(playlists.first(), csrfToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadStreamInfo(playlistPath: String, csrfToken: String) = runBlocking {
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
println(baseURL + playlistPath)
|
||||||
|
|
||||||
|
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"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val res = Jsoup.connect(baseURL + playlistPath)
|
||||||
|
.ignoreContentType(true)
|
||||||
|
.cookies(sessionCookies)
|
||||||
|
.headers(headers)
|
||||||
|
.execute()
|
||||||
|
|
||||||
|
//println(res.body())
|
||||||
|
|
||||||
|
// TODO replace with gson
|
||||||
|
val jsonObject = JSONObject(res.body())
|
||||||
|
val sourcesObject = jsonObject.getJSONArray("playlist").get(0).toString()
|
||||||
|
|
||||||
|
val sourcesArray = JSONObject(sourcesObject).getJSONArray("sources")
|
||||||
|
|
||||||
|
for (i in 0 until sourcesArray.length()) {
|
||||||
|
println(sourcesArray[i].toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ import org.mosad.teapod.util.GUIMedia
|
||||||
|
|
||||||
class LibraryFragment : Fragment() {
|
class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
|
private val parser = AoDParser()
|
||||||
|
|
||||||
private var mediaList = arrayListOf<GUIMedia>()
|
private var mediaList = arrayListOf<GUIMedia>()
|
||||||
private lateinit var adapter : CustomAdapter
|
private lateinit var adapter : CustomAdapter
|
||||||
|
|
||||||
|
@ -24,19 +26,31 @@ class LibraryFragment : Fragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val parser = AoDParser()
|
mediaList = parser.listAnimes()
|
||||||
mediaList = parser.listAnime()
|
|
||||||
|
|
||||||
// create and set the adapter, needs context
|
// create and set the adapter, needs context
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
adapter = CustomAdapter(requireContext(), mediaList)//ArrayAdapter(requireContext(), R.layout.linear_media, R.id.text_title, mediaList)
|
adapter = CustomAdapter(requireContext(), mediaList)
|
||||||
list_library.adapter = adapter
|
list_library.adapter = adapter
|
||||||
//adapter.notifyDataSetChanged()
|
//adapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initActions()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initActions() {
|
||||||
|
list_library.setOnItemClickListener { parent, view, position, id ->
|
||||||
|
println("selected item is: ${mediaList[position]}")
|
||||||
|
showDetailFragment(mediaList[position])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showDetailFragment(media: GUIMedia) {
|
||||||
|
parser.loadDetails(media.link)
|
||||||
|
|
||||||
|
println("done")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,7 +7,6 @@ import android.view.ViewGroup
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import org.mosad.teapod.R
|
import org.mosad.teapod.R
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ class CustomAdapter(context: Context, private val media: ArrayList<GUIMedia>) :
|
||||||
val imagePoster = view.findViewById<ImageView>(R.id.image_poster)
|
val imagePoster = view.findViewById<ImageView>(R.id.image_poster)
|
||||||
|
|
||||||
textTitle.text = media[position].title
|
textTitle.text = media[position].title
|
||||||
Glide.with(context).load(media[position].imageLink).into(imagePoster)
|
Glide.with(context).load(media[position].posterLink).into(imagePoster)
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package org.mosad.teapod.util
|
package org.mosad.teapod.util
|
||||||
|
|
||||||
data class GUIMedia(val title: String, val imageLink: String, val shortDesc : String, val link: String)
|
data class GUIMedia(val title: String, val posterLink: String, val shortDesc : String, val link: String)
|
|
@ -3,8 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:paddingTop="?attr/actionBarSize">
|
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/nav_view"
|
android:id="@+id/nav_view"
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
android:id="@+id/nav_host_fragment"
|
android:id="@+id/nav_host_fragment"
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
app:defaultNavHost="true"
|
app:defaultNavHost="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/nav_view"
|
app:layout_constraintBottom_toTopOf="@id/nav_view"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
|
Loading…
Reference in New Issue