merge GUIMedia and StreamMedia into Media, parse episode title from aod
This commit is contained in:
parent
0fc1d8b5c2
commit
ae20e74702
|
@ -17,7 +17,7 @@ import org.mosad.teapod.ui.components.LoginDialog
|
|||
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
|
||||
import org.mosad.teapod.util.Media
|
||||
|
||||
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
|
@ -87,10 +87,10 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
|||
}
|
||||
}
|
||||
|
||||
fun showDetailFragment(media: GUIMedia) {
|
||||
val streamMedia = AoDParser().loadStreams(media.link) // load the streams for the selected media
|
||||
fun showDetailFragment(media: Media) {
|
||||
media.episodes = AoDParser().loadStreams(media) // load the streams for the selected media
|
||||
|
||||
val mediaFragment = MediaFragment(media, streamMedia)
|
||||
val mediaFragment = MediaFragment(media)
|
||||
supportFragmentManager.commit {
|
||||
add(R.id.nav_host_fragment, mediaFragment, "MediaFragment")
|
||||
addToBackStack(null)
|
||||
|
|
|
@ -7,8 +7,9 @@ import org.jsoup.Connection
|
|||
import org.jsoup.Jsoup
|
||||
import org.mosad.teapod.preferences.EncryptedPreferences
|
||||
import org.mosad.teapod.util.DataTypes.MediaType
|
||||
import org.mosad.teapod.util.GUIMedia
|
||||
import org.mosad.teapod.util.StreamMedia
|
||||
import org.mosad.teapod.util.Episode
|
||||
import org.mosad.teapod.util.Media
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class AoDParser {
|
||||
|
@ -21,7 +22,7 @@ class AoDParser {
|
|||
private var sessionCookies = mutableMapOf<String, String>()
|
||||
private var loginSuccess = false
|
||||
|
||||
val mediaList = arrayListOf<GUIMedia>()
|
||||
val mediaList = arrayListOf<Media>()
|
||||
}
|
||||
|
||||
private fun login() = runBlocking {
|
||||
|
@ -67,7 +68,7 @@ class AoDParser {
|
|||
/**
|
||||
* list all animes from the website
|
||||
*/
|
||||
fun listAnimes(): ArrayList<GUIMedia> = runBlocking {
|
||||
fun listAnimes(): ArrayList<Media> = runBlocking {
|
||||
if (sessionCookies.isEmpty()) login()
|
||||
|
||||
withContext(Dispatchers.Default) {
|
||||
|
@ -79,13 +80,19 @@ class AoDParser {
|
|||
|
||||
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"),
|
||||
it.select("p.animebox-shorttext").text(),
|
||||
it.select("p.animebox-link").select("a").attr("href")
|
||||
)
|
||||
val type = if (it.select("p.animebox-link").select("a").text().toLowerCase(Locale.ROOT) == "zur serie") {
|
||||
MediaType.TVSHOW
|
||||
} else {
|
||||
MediaType.MOVIE
|
||||
}
|
||||
|
||||
val media = Media(
|
||||
it.select("h3.animebox-title").text(),
|
||||
it.select("p.animebox-link").select("a").attr("href"),
|
||||
type,
|
||||
it.select("p.animebox-image").select("img").attr("src"),
|
||||
it.select("p.animebox-shorttext").text()
|
||||
)
|
||||
mediaList.add(media)
|
||||
}
|
||||
|
||||
|
@ -98,17 +105,17 @@ class AoDParser {
|
|||
/**
|
||||
* load streams for the media path
|
||||
*/
|
||||
fun loadStreams(mediaPath: String): StreamMedia = runBlocking {
|
||||
fun loadStreams(media: Media): List<Episode> = runBlocking {
|
||||
if (sessionCookies.isEmpty()) login()
|
||||
|
||||
if (!loginSuccess) {
|
||||
println("please log in") // TODO
|
||||
return@runBlocking StreamMedia(MediaType.OTHER)
|
||||
return@runBlocking listOf()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Default) {
|
||||
|
||||
val res = Jsoup.connect(baseURL + mediaPath)
|
||||
val res = Jsoup.connect(baseURL + media.link)
|
||||
.cookies(sessionCookies)
|
||||
.get()
|
||||
|
||||
|
@ -120,20 +127,14 @@ class AoDParser {
|
|||
//println("first entry: ${playlists.first()}")
|
||||
//println("csrf token is: $csrfToken")
|
||||
|
||||
val type = if (res.select("h2").eachText().filter { it == "Episoden" }.any()) {
|
||||
MediaType.TVSHOW
|
||||
} else {
|
||||
MediaType.MOVIE
|
||||
}
|
||||
|
||||
return@withContext loadStreamInfo(playlists.first(), csrfToken, type)
|
||||
return@withContext loadStreamInfo(playlists.first(), csrfToken, media.type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load the playlist path and parse it, read the stream info from json
|
||||
*/
|
||||
private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType): StreamMedia = runBlocking {
|
||||
private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType): List<Episode> = runBlocking {
|
||||
withContext(Dispatchers.Default) {
|
||||
val headers = mutableMapOf(
|
||||
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
|
||||
|
@ -151,36 +152,36 @@ class AoDParser {
|
|||
|
||||
//println(res.body())
|
||||
|
||||
println(type)
|
||||
return@withContext when (type) {
|
||||
MediaType.MOVIE -> {
|
||||
val movie = JsonParser.parseString(res.body()).asJsonObject
|
||||
.get("playlist").asJsonArray
|
||||
|
||||
val streamList = arrayListOf<String>()
|
||||
movie.first().asJsonObject.get("sources").asJsonArray.toList().forEach {
|
||||
streamList.add(it.asJsonObject.get("file").asString)
|
||||
movie.first().asJsonObject.get("sources").asJsonArray.toList().map {
|
||||
Episode(streamUrl = it.asJsonObject.get("file").asString)
|
||||
}
|
||||
|
||||
StreamMedia(MediaType.MOVIE, streamList)
|
||||
}
|
||||
MediaType.TVSHOW -> {
|
||||
val episodes = JsonParser.parseString(res.body()).asJsonObject
|
||||
val episodesJson = JsonParser.parseString(res.body()).asJsonObject
|
||||
.get("playlist").asJsonArray
|
||||
|
||||
val streamList = arrayListOf<String>()
|
||||
episodes.forEach {
|
||||
val streamUrl = it.asJsonObject.get("sources").asJsonArray
|
||||
|
||||
episodesJson.map {
|
||||
val episodeStream = it.asJsonObject.get("sources").asJsonArray
|
||||
.first().asJsonObject
|
||||
.get("file").asString
|
||||
streamList.add(streamUrl)
|
||||
val episodeTitle = it.asJsonObject.get("title").asString
|
||||
|
||||
Episode(
|
||||
episodeTitle,
|
||||
episodeStream
|
||||
)
|
||||
}
|
||||
|
||||
StreamMedia(MediaType.TVSHOW, streamList)
|
||||
}
|
||||
else -> {
|
||||
Log.e(javaClass.name, "Wrong Type, please report this issue.")
|
||||
StreamMedia(MediaType.OTHER)
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,9 @@ import org.mosad.teapod.MainActivity
|
|||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.util.DataTypes.MediaType
|
||||
import org.mosad.teapod.util.EpisodesAdapter
|
||||
import org.mosad.teapod.util.GUIMedia
|
||||
import org.mosad.teapod.util.StreamMedia
|
||||
import org.mosad.teapod.util.Media
|
||||
|
||||
class MediaFragment(private val guiMedia: GUIMedia, private val streamMedia: StreamMedia) : Fragment() {
|
||||
class MediaFragment(private val media: Media) : Fragment() {
|
||||
|
||||
private lateinit var adapterRecEpisodes: EpisodesAdapter
|
||||
private lateinit var viewManager: RecyclerView.LayoutManager
|
||||
|
@ -31,53 +30,47 @@ class MediaFragment(private val guiMedia: GUIMedia, private val streamMedia: Str
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// generic gui
|
||||
Glide.with(requireContext()).load(guiMedia.posterLink).into(image_poster)
|
||||
text_title.text = guiMedia.title
|
||||
text_desc.text = guiMedia.shortDesc
|
||||
Glide.with(requireContext()).load(media.posterLink).into(image_poster)
|
||||
text_title.text = media.title
|
||||
text_desc.text = media.shortDesc
|
||||
|
||||
// specific gui
|
||||
if (streamMedia.type == MediaType.TVSHOW) {
|
||||
val episodes = streamMedia.streams.mapIndexed { index, _ ->
|
||||
"${guiMedia.title} - Ep. ${index + 1}"
|
||||
}
|
||||
if (media.type == MediaType.TVSHOW) {
|
||||
// TODO
|
||||
val episodeTitles = media.episodes.map { it.title }
|
||||
|
||||
|
||||
adapterRecEpisodes = EpisodesAdapter(episodes)
|
||||
adapterRecEpisodes = EpisodesAdapter(episodeTitles)
|
||||
viewManager = LinearLayoutManager(context)
|
||||
recycler_episodes.layoutManager = viewManager
|
||||
recycler_episodes.adapter = adapterRecEpisodes
|
||||
|
||||
} else if (streamMedia.type == MediaType.MOVIE) {
|
||||
} else if (media.type == MediaType.MOVIE) {
|
||||
recycler_episodes.visibility = View.GONE
|
||||
}
|
||||
|
||||
|
||||
println("media streams: ${streamMedia.streams}")
|
||||
println("media streams: ${media.episodes}")
|
||||
|
||||
initActions()
|
||||
}
|
||||
|
||||
private fun initActions() {
|
||||
button_play.setOnClickListener {
|
||||
onClickButtonPlay()
|
||||
when (media.type) {
|
||||
MediaType.MOVIE -> playStream(media.episodes.first().streamUrl)
|
||||
MediaType.TVSHOW -> playStream(media.episodes.first().streamUrl)
|
||||
MediaType.OTHER -> Log.e(javaClass.name, "Wrong Type, please report this issue.")
|
||||
}
|
||||
}
|
||||
|
||||
// set onItemClick only in adapter is initialized
|
||||
if (this::adapterRecEpisodes.isInitialized) {
|
||||
adapterRecEpisodes.onItemClick = { item, position ->
|
||||
playStream(streamMedia.streams[position])
|
||||
playStream(media.episodes[position].streamUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClickButtonPlay() {
|
||||
when (streamMedia.type) {
|
||||
MediaType.MOVIE -> playStream(streamMedia.streams.first())
|
||||
MediaType.TVSHOW -> playStream(streamMedia.streams.first())
|
||||
MediaType.OTHER -> Log.e(javaClass.name, "Wrong Type, please report this issue.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun playStream(url: String) {
|
||||
val mainActivity = activity as MainActivity
|
||||
mainActivity.startPlayer(url)
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.mosad.teapod.MainActivity
|
|||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.util.CustomAdapter
|
||||
import org.mosad.teapod.util.GUIMedia
|
||||
import org.mosad.teapod.util.Media
|
||||
|
||||
class LibraryFragment : Fragment() {
|
||||
|
||||
|
@ -41,7 +41,7 @@ class LibraryFragment : Fragment() {
|
|||
|
||||
private fun initActions() {
|
||||
list_library.setOnItemClickListener { _, _, position, _ ->
|
||||
val media = adapter.getItem(position) as GUIMedia
|
||||
val media = adapter.getItem(position) as Media
|
||||
println("selected item is: ${media.title}")
|
||||
|
||||
val mainActivity = activity as MainActivity
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.mosad.teapod.MainActivity
|
|||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.util.CustomAdapter
|
||||
import org.mosad.teapod.util.GUIMedia
|
||||
import org.mosad.teapod.util.Media
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
|
||||
|
@ -55,7 +55,7 @@ class SearchFragment : Fragment() {
|
|||
})
|
||||
|
||||
list_search.setOnItemClickListener { _, _, position, _ ->
|
||||
val media = adapter.getItem(position) as GUIMedia
|
||||
val media = adapter.getItem(position) as Media
|
||||
|
||||
println("selected item is: ${media.title}")
|
||||
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
package org.mosad.teapod.util
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import org.mosad.teapod.R
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class CustomAdapter(val context: Context, private val originalMedia: ArrayList<GUIMedia>) : BaseAdapter(), Filterable {
|
||||
class CustomAdapter(val context: Context, private val originalMedia: ArrayList<Media>) : BaseAdapter(), Filterable {
|
||||
|
||||
private var filteredMedia = originalMedia.map { it.copy() }
|
||||
private val customFilter = CustomFilter()
|
||||
|
@ -68,7 +62,7 @@ class CustomAdapter(val context: Context, private val originalMedia: ArrayList<G
|
|||
}
|
||||
|
||||
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
|
||||
filteredMedia = results?.values as ArrayList<GUIMedia>
|
||||
filteredMedia = results?.values as ArrayList<Media>
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,10 @@ class DataTypes {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO rework: add type, episodes list with episode title, if type == MOVIE the first episode will be the movie stream
|
||||
data class GUIMedia(val title: String, val posterLink: String, val shortDesc : String, val link: String) {
|
||||
data class Media(val title: String, val link: String, val type: DataTypes.MediaType, val posterLink: String, val shortDesc : String, var episodes: List<Episode> = listOf()) {
|
||||
override fun toString(): String {
|
||||
return title
|
||||
}
|
||||
}
|
||||
|
||||
data class StreamMedia(val type: DataTypes.MediaType, val streams: ArrayList<String> = arrayListOf())
|
||||
data class Episode(val title: String = "", val streamUrl: String = "", var watched: Boolean = false)
|
||||
|
|
Loading…
Reference in New Issue