add media fragment, add stream parsing

This commit is contained in:
2020-10-11 10:02:00 +02:00
parent c473fce19a
commit 818981190d
12 changed files with 265 additions and 70 deletions

View File

@ -1,35 +1,88 @@
package org.mosad.teapod
import android.os.Bundle
import android.view.MenuItem
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import kotlinx.android.synthetic.main.activity_main.*
import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.ui.MediaFragment
import org.mosad.teapod.ui.account.AccountFragment
import org.mosad.teapod.ui.home.HomeFragment
import org.mosad.teapod.ui.library.LibraryFragment
import org.mosad.teapod.ui.search.SearchFragment
import org.mosad.teapod.util.GUIMedia
class MainActivity : AppCompatActivity() {
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_library, R.id.navigation_search))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
navView.setOnNavigationItemSelectedListener(this)
load()
}
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStack()
} else {
if (activeFragment !is HomeFragment) {
nav_view.selectedItemId = R.id.navigation_home
} else {
super.onBackPressed()
}
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val ret = when (item.itemId) {
R.id.navigation_home -> {
activeFragment = HomeFragment()
true
}
R.id.navigation_library -> {
activeFragment = LibraryFragment()
true
}
R.id.navigation_search -> {
activeFragment = SearchFragment()
true
}
R.id.navigation_account -> {
activeFragment = AccountFragment()
true
}
else -> false
}
supportFragmentManager.commit {
replace(R.id.nav_host_fragment, activeFragment)
}
return ret
}
private fun load() {
// TODO
}
fun showDetailFragment(media: GUIMedia) {
val streams = AoDParser().loadStreams(media.link) // load the streams for the selected media
val mediaFragment = MediaFragment(media, streams)
supportFragmentManager.commit {
add(R.id.nav_host_fragment, mediaFragment, "MediaFragment")
addToBackStack(null)
show(mediaFragment)
}
println("visible !!!: " + mediaFragment.isVisible)
println(supportFragmentManager.backStackEntryCount)
}
}

View File

@ -1,7 +1,7 @@
package org.mosad.teapod.parser
import com.google.gson.JsonParser
import kotlinx.coroutines.*
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import org.mosad.teapod.util.GUIMedia
@ -15,8 +15,12 @@ class AoDParser {
private val login = ""
private val pwd = ""
private var sessionCookies = mutableMapOf<String, String>()
private var loginSuccess = false
companion object {
private var sessionCookies = mutableMapOf<String, String>()
private var loginSuccess = false
val mediaList = arrayListOf<GUIMedia>()
}
private fun login() = runBlocking {
@ -63,14 +67,14 @@ class AoDParser {
if (sessionCookies.isEmpty()) login()
withContext(Dispatchers.Default) {
val res = Jsoup.connect("$baseURL/animes")
val resAnimes = Jsoup.connect("$baseURL/animes")
.cookies(sessionCookies)
.get()
//println(res)
//println(resAnimes)
val animes = arrayListOf<GUIMedia>()
res.select("div.animebox").forEach {
mediaList.clear()
resAnimes.select("div.animebox").forEach {
val media = GUIMedia(
it.select("h3.animebox-title").text(),
it.select("p.animebox-image").select("img").attr("src"),
@ -78,25 +82,27 @@ class AoDParser {
it.select("p.animebox-link").select("a").attr("href")
)
animes.add(media)
mediaList.add(media)
}
println("got ${animes.size} anime")
println("got ${mediaList.size} anime")
return@withContext animes
return@withContext mediaList
}
}
fun loadDetails(mediaPath: String) = runBlocking {
/**
* load streams for the media path
*/
fun loadStreams(mediaPath: String): List<String> = runBlocking {
if (sessionCookies.isEmpty()) login()
if (!loginSuccess) {
println("please log in")
return@runBlocking
println("please log in") // TODO
return@runBlocking listOf()
}
withContext(Dispatchers.Default) {
println(baseURL + mediaPath)
val res = Jsoup.connect(baseURL + mediaPath)
.cookies(sessionCookies)
@ -105,19 +111,20 @@ class AoDParser {
//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)
//println("first entry: ${playlists.first()}")
//println("csrf token is: $csrfToken")
return@withContext loadStreamInfo(playlists.first(), csrfToken)
}
}
private fun loadStreamInfo(playlistPath: String, csrfToken: String) = runBlocking {
/**
* load the playlist path and parse it, read the stream info from json
*/
private fun loadStreamInfo(playlistPath: String, csrfToken: String): List<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"),
@ -126,7 +133,6 @@ class AoDParser {
Pair("X-Requested-With", "XMLHttpRequest"),
)
val res = Jsoup.connect(baseURL + playlistPath)
.ignoreContentType(true)
.cookies(sessionCookies)
@ -135,16 +141,15 @@ class AoDParser {
//println(res.body())
// TODO replace with gson
val jsonObject = JSONObject(res.body())
val sourcesObject = jsonObject.getJSONArray("playlist").get(0).toString()
// TODO if it's a series there sources for each episode
val sources = JsonParser.parseString(res.body()).asJsonObject
.get("playlist").asJsonArray.first().asJsonObject
.get("sources").asJsonArray
val sourcesArray = JSONObject(sourcesObject).getJSONArray("sources")
for (i in 0 until sourcesArray.length()) {
println(sourcesArray[i].toString())
return@withContext sources.toList().map {
it.asJsonObject.get("file").toString()
}
}
}
}
}

View File

@ -0,0 +1,42 @@
package org.mosad.teapod.ui
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_media.*
import org.mosad.teapod.R
import org.mosad.teapod.util.GUIMedia
class MediaFragment(val media: GUIMedia, val streams: List<String>) : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_media, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// load poster
Glide.with(requireContext()).load(media.posterLink).into(image_poster)
text_title.text = media.title
text_desc.text = media.shortDesc
println("media streams: $streams")
initActions()
}
private fun initActions() {
button_play.setOnClickListener { onClickButtonPlay() }
}
private fun onClickButtonPlay() {
println("play ${streams.first()}")
}
}

View File

@ -27,6 +27,6 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
println("created!!!!")
println("HomeFragment created")
}
}

View File

@ -5,10 +5,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import kotlinx.android.synthetic.main.fragment_library.*
import kotlinx.coroutines.*
import org.mosad.teapod.MainActivity
import org.mosad.teapod.R
import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.ui.MediaFragment
import org.mosad.teapod.util.CustomAdapter
import org.mosad.teapod.util.GUIMedia
@ -19,6 +22,7 @@ class LibraryFragment : Fragment() {
private var mediaList = arrayListOf<GUIMedia>()
private lateinit var adapter : CustomAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_library, container, false)
}
@ -27,7 +31,11 @@ class LibraryFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
GlobalScope.launch {
mediaList = parser.listAnimes()
if (AoDParser.mediaList.isEmpty()) {
AoDParser().listAnimes()
}
mediaList = AoDParser.mediaList
// create and set the adapter, needs context
withContext(Dispatchers.Main) {
@ -43,14 +51,33 @@ class LibraryFragment : Fragment() {
private fun initActions() {
list_library.setOnItemClickListener { parent, view, position, id ->
println("selected item is: ${mediaList[position]}")
showDetailFragment(mediaList[position])
//showDetailFragment(mediaList[position])
val mainActivity = activity as MainActivity
mainActivity.showDetailFragment(mediaList[position])
}
}
private fun showDetailFragment(media: GUIMedia) {
parser.loadDetails(media.link)
val streams = parser.loadStreams(media.link) // load the streams for the selected media
println("done: $streams")
println("done")
// TODO create detail fragment
val mediaFragment = MediaFragment(media, streams)
activity?.supportFragmentManager?.commit {
add(mediaFragment, "MediaFragment")
addToBackStack(null)
}
// activity?.supportFragmentManager?.beginTransaction()?.let {
// it.replace(mContainer.id, mediaFragment, "MediaFragment")
// it.addToBackStack("MediaFragment")
// it.commit()
// }
println("done!!!")
}
}