improve getting links

This commit is contained in:
jmir1 2021-05-02 18:47:04 +02:00
parent d387b8c76f
commit 8423e9e35f
11 changed files with 144 additions and 14 deletions

View file

@ -20,17 +20,20 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.watcher.WatcherActivity
import eu.kanade.tachiyomi.util.lang.awaitSingle
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -433,7 +436,8 @@ class NotificationReceiver : BroadcastReceiver() {
* @param episode episode that needs to be opened
*/
internal fun openEpisodePendingActivity(context: Context, anime: Anime, episode: Episode): PendingIntent {
val newIntent = WatcherActivity.newIntent(context, anime, episode)
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
val newIntent = WatcherActivity.newIntent(context, anime, episode, runBlocking { source.fetchEpisodeLink(episode).awaitSingle() })
return PendingIntent.getActivity(context, anime.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}

View file

@ -37,13 +37,21 @@ interface AnimeSource : tachiyomi.source.AnimeSource {
fun fetchAnimeDetails(anime: SAnime): Observable<SAnime>
/**
* Returns an observable with all the available chapters for a anime.
* Returns an observable with all the available episodes for an anime.
*
* @param anime the anime to update.
*/
@Deprecated("Use getEpisodeList instead")
fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>>
/**
* Returns an observable with a link for the episode of an anime.
*
* @param episode the episode to get the link for.
*/
@Deprecated("Use getEpisodeList instead")
fun fetchEpisodeLink(episode: SEpisode): Observable<String>
/**
* Returns an observable with the list of pages a chapter has.
*
@ -64,7 +72,7 @@ interface AnimeSource : tachiyomi.source.AnimeSource {
}
/**
* [1.x API] Get all the available chapters for a anime.
* [1.x API] Get all the available episodes for a anime.
*/
@Suppress("DEPRECATION")
override suspend fun getEpisodeList(anime: AnimeInfo): List<EpisodeInfo> {
@ -72,6 +80,14 @@ interface AnimeSource : tachiyomi.source.AnimeSource {
.map { it.toEpisodeInfo() }
}
/**
* [1.x API] Get a link for the episode of an anime.
*/
@Suppress("DEPRECATION")
override suspend fun getEpisodeLink(episode: EpisodeInfo): String {
return fetchEpisodeLink(episode.toSEpisode()).awaitSingle()
}
/**
* [1.x API] Get the list of pages a chapter has.
*/

View file

@ -62,6 +62,10 @@ open class AnimeSourceManager(private val context: Context) {
return Observable.error(getSourceNotInstalledException())
}
override fun fetchEpisodeLink(episode: SEpisode): Observable<String> {
return Observable.error(getSourceNotInstalledException())
}
override fun fetchPageList(episode: SEpisode): Observable<List<Page>> {
return Observable.error(getSourceNotInstalledException())
}

View file

@ -203,6 +203,12 @@ class LocalAnimeSource(private val context: Context) : AnimeCatalogueSource {
return Observable.just(episodes)
}
override fun fetchEpisodeLink(episode: SEpisode): Observable<String> {
val link = episode.url
return Observable.just(link)
}
/**
* Strips the anime title from a episode name, matching only based on alphanumeric and whitespace
* characters.

View file

@ -218,6 +218,14 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
}
}
override fun fetchEpisodeLink(episode: SEpisode): Observable<String> {
return client.newCall(episodeLinkRequest(episode))
.asObservableSuccess()
.map { response ->
episodeLinkParse(response)
}
}
/**
* Returns the request for updating the episode list. Override only if it's needed to override
* the url, send different headers or request method like POST.
@ -228,6 +236,16 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
return GET(baseUrl + anime.url, headers)
}
/**
* Returns the request for getting the episode link. Override only if it's needed to override
* the url, send different headers or request method like POST.
*
* @param episode the episode to look for links.
*/
protected open fun episodeLinkRequest(episode: SEpisode): Request {
return GET(baseUrl + episode.url, headers)
}
/**
* Parses the response from the site and returns a list of episodes.
*
@ -235,6 +253,13 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
*/
protected abstract fun episodeListParse(response: Response): List<SEpisode>
/**
* Parses the response from the site and returns a list of episodes.
*
* @param response the response from the site.
*/
protected abstract fun episodeLinkParse(response: Response): String
/**
* Returns an observable with the page list for a episode.
*

View file

@ -159,6 +159,21 @@ abstract class ParsedAnimeHttpSource : AnimeHttpSource() {
*/
protected abstract fun episodeListSelector(): String
/**
* Parses the response from the site and returns a list of episodes.
*
* @param response the response from the site.
*/
override fun episodeLinkParse(response: Response): String {
val document = response.asJsoup()
return linkFromElement(document.select(episodeLinkSelector()).first())
}
/**
* Returns the Jsoup selector that returns a list of [Element] corresponding to each episode.
*/
protected abstract fun episodeLinkSelector(): String
/**
* Returns a episode from the given element.
*
@ -166,6 +181,13 @@ abstract class ParsedAnimeHttpSource : AnimeHttpSource() {
*/
protected abstract fun episodeFromElement(element: Element): SEpisode
/**
* Returns a episode from the given element.
*
* @param element an element obtained from [episodeListSelector].
*/
protected abstract fun linkFromElement(element: Element): String
/**
* Parses the response from the site and returns the page list.
*

View file

@ -79,6 +79,9 @@ import eu.kanade.tachiyomi.util.view.shrinkOnScroll
import eu.kanade.tachiyomi.util.view.snack
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.Callback
import reactivecircus.flowbinding.recyclerview.scrollEvents
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
@ -722,6 +725,14 @@ class AnimeController :
}
}
private fun fetchEpisodeLinksFromSource(manualFetch: Boolean = false, episode: Episode): String {
return presenter.fetchEpisodeLinksFromSource(manualFetch, episode)
}
fun onFetchEpisodeLinksError(error: Throwable) {
activity?.toast("no links found")
}
fun onEpisodeDownloadUpdate(download: AnimeDownload) {
episodesAdapter?.currentItems?.find { it.id == download.episode.id }?.let {
episodesAdapter?.updateItem(it, it.status)
@ -730,11 +741,16 @@ class AnimeController :
fun openEpisode(episode: Episode, hasAnimation: Boolean = false) {
val activity = activity ?: return
val intent = WatcherActivity.newIntent(activity, presenter.anime, episode)
if (hasAnimation) {
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
runBlocking {
launch {
val url = fetchEpisodeLinksFromSource(false, episode)
val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, url)
if (hasAnimation) {
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
}
startActivityForResult(intent, REQUEST_SECONDS)
}
}
startActivityForResult(intent, REQUEST_SECONDS)
}
override fun onItemClick(view: View?, position: Int): Boolean {

View file

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.anime
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.util.Log
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
@ -19,6 +20,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
@ -31,10 +33,7 @@ import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.*
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@ -43,6 +42,8 @@ import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class AnimePresenter(
val anime: Anime,
@ -83,6 +84,11 @@ class AnimePresenter(
*/
private var fetchEpisodesJob: Job? = null
/**
* Subscription to retrieve the new link of episodes from the source.
*/
private var fetchEpisodeLinksJob: Job? = null
/**
* Subscription to observe download status changes.
*/
@ -391,6 +397,28 @@ class AnimePresenter(
}
}
/**
* Requests an updated list of episodes from the source.
*/
fun fetchEpisodeLinksFromSource(manualFetch: Boolean = false, episode: Episode): String {
hasRequested = true
var link = runBlocking {
return@runBlocking suspendCoroutine<String> { continuation ->
var link: String
presenterScope.launchIO {
try {
link = source.getEpisodeLink(episode.toEpisodeInfo())
continuation.resume(link)
} catch (e: Throwable) {
withUIContext { view?.onFetchEpisodeLinksError(e) }
}
}
}
}
Log.i("lol", "omg" + link)
return link
}
/**
* Updates the UI after applying the filters.
*/

View file

@ -43,8 +43,8 @@ import eu.kanade.tachiyomi.ui.base.controller.TabbedController
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.BrowseController
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourceController
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
import eu.kanade.tachiyomi.ui.download.DownloadController
import eu.kanade.tachiyomi.ui.library.LibraryController

View file

@ -42,6 +42,7 @@ class WatcherActivity : AppCompatActivity() {
setContentView(R.layout.watcher_activity)
playerView = findViewById(R.id.player_view)
dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "xyz.jmir.tachiyomi.mi"))
Log.i("uri is ", intent.getStringExtra("uri"))
mediaItem = MediaItem.Builder()
.setUri(intent.getStringExtra("uri"))
.setMimeType(MimeTypes.VIDEO_MP4)
@ -127,12 +128,13 @@ class WatcherActivity : AppCompatActivity() {
}
companion object {
fun newIntent(context: Context, anime: Anime, episode: Episode): Intent {
fun newIntent(context: Context, anime: Anime, episode: Episode, url: String): Intent {
return Intent(context, WatcherActivity::class.java).apply {
putExtra("anime", anime.id)
putExtra("episode", episode)
putExtra("second", episode.last_second_seen)
putExtra("uri", episode.url)
putExtra("uri", url)
Log.i("bruhh", url)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
}

View file

@ -36,6 +36,13 @@ interface AnimeSource {
*/
suspend fun getEpisodeList(anime: AnimeInfo): List<EpisodeInfo>
/**
* Returns an observable with all the available chapters for a anime.
*
* @param anime the anime to update.
*/
suspend fun getEpisodeLink(episode: EpisodeInfo): String
/**
* Returns an observable with the list of pages a chapter has.
*