From ae20e747027529da4b3b77bff131df6b35ed053b Mon Sep 17 00:00:00 2001 From: Jannik Date: Mon, 12 Oct 2020 17:52:24 +0200 Subject: [PATCH] merge GUIMedia and StreamMedia into Media, parse episode title from aod --- .../java/org/mosad/teapod/MainActivity.kt | 8 +-- .../java/org/mosad/teapod/parser/AoDParser.kt | 69 ++++++++++--------- .../java/org/mosad/teapod/ui/MediaFragment.kt | 41 +++++------ .../teapod/ui/library/LibraryFragment.kt | 4 +- .../mosad/teapod/ui/search/SearchFragment.kt | 4 +- .../org/mosad/teapod/util/CustomAdapter.kt | 10 +-- .../java/org/mosad/teapod/util/DataTypes.kt | 5 +- 7 files changed, 64 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/org/mosad/teapod/MainActivity.kt b/app/src/main/java/org/mosad/teapod/MainActivity.kt index 48ffbe2..9302079 100644 --- a/app/src/main/java/org/mosad/teapod/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/MainActivity.kt @@ -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) diff --git a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt index 04600eb..92250a4 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -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() private var loginSuccess = false - val mediaList = arrayListOf() + val mediaList = arrayListOf() } private fun login() = runBlocking { @@ -67,7 +68,7 @@ class AoDParser { /** * list all animes from the website */ - fun listAnimes(): ArrayList = runBlocking { + fun listAnimes(): ArrayList = 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 = 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 = 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() - 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() - 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() } } } diff --git a/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt index 561227c..8a4bc5a 100644 --- a/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt @@ -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) diff --git a/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt b/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt index a82ce41..fca99f4 100644 --- a/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt @@ -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 diff --git a/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt b/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt index bd4e46a..9f16f39 100644 --- a/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt @@ -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}") diff --git a/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt b/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt index 4be1472..75bf42d 100644 --- a/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt +++ b/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt @@ -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) : BaseAdapter(), Filterable { +class CustomAdapter(val context: Context, private val originalMedia: ArrayList) : 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 + filteredMedia = results?.values as ArrayList notifyDataSetChanged() } diff --git a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt index 3dcdc2d..ee9ea95 100644 --- a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt @@ -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 = listOf()) { override fun toString(): String { return title } } -data class StreamMedia(val type: DataTypes.MediaType, val streams: ArrayList = arrayListOf()) \ No newline at end of file +data class Episode(val title: String = "", val streamUrl: String = "", var watched: Boolean = false)