add OnItemClickListener

This commit is contained in:
Jannik 2020-10-09 15:18:52 +02:00
parent b94b86b866
commit c473fce19a
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
5 changed files with 101 additions and 31 deletions

View File

@ -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())
}
} }
} }

View File

@ -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")
}
} }

View File

@ -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
} }

View File

@ -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)

View File

@ -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"