lots of background work for manga extensions

This commit is contained in:
Finnley Somdahl 2023-10-18 23:52:03 -05:00
parent dbe573131e
commit 57a584a820
123 changed files with 2676 additions and 553 deletions

View file

@ -1,10 +1,18 @@
package ani.dantotsu.parsers
import android.content.ContentResolver
import android.content.ContentValues
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.widget.Toast
import ani.dantotsu.FileUrl
import ani.dantotsu.aniyomi.anime.model.AnimeExtension
import ani.dantotsu.aniyomi.animesource.AnimeCatalogueSource
import ani.dantotsu.aniyomi.util.network.interceptor.CloudflareBypassException
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.network.interceptor.CloudflareBypassException
import ani.dantotsu.currContext
import ani.dantotsu.logger
import eu.kanade.tachiyomi.animesource.model.SEpisode
@ -13,6 +21,22 @@ import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.lang.awaitSingle
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.net.URL
import java.net.URLDecoder
@ -91,7 +115,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
return emptyList() // Return an empty list if source is not an AnimeCatalogueSource
}
fun convertAnimesPageToShowResponse(animesPage: AnimesPage): List<ShowResponse> {
private fun convertAnimesPageToShowResponse(animesPage: AnimesPage): List<ShowResponse> {
return animesPage.animes.map { sAnime ->
// Extract required fields from sAnime
val name = sAnime.title
@ -106,34 +130,160 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
}
}
fun SEpisodeToEpisode(sEpisode: SEpisode): Episode {
val episode = Episode(
sEpisode.episode_number.toString(),
private fun SEpisodeToEpisode(sEpisode: SEpisode): Episode {
//if the float episode number is a whole number, convert it to an int
val episodeNumberInt =
if (sEpisode.episode_number % 1 == 0f) {
sEpisode.episode_number.toInt()
} else {
sEpisode.episode_number
}
return Episode(
episodeNumberInt.toString(),
sEpisode.url,
sEpisode.name,
null,
null,
false,
null,
sEpisode)
return episode
sEpisode
)
}
fun VideoToVideoServer(video: Video): VideoServer {
val videoServer = VideoServer(
private fun VideoToVideoServer(video: Video): VideoServer {
return VideoServer(
video.quality,
video.url,
null,
video)
return videoServer
video
)
}
}
class VideoServerPassthrough : VideoExtractor{
val videoServer: VideoServer
constructor(videoServer: VideoServer) {
this.videoServer = videoServer
class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
val extension: MangaExtension.Installed
init {
this.extension = extension
}
override val name = extension.name
override val saveName = extension.name
override val hostUrl = extension.sources.first().name
override suspend fun loadChapters(mangaLink: String, extra: Map<String, String>?, sManga: SManga): List<MangaChapter> {
val source = extension.sources.first()
if (source is CatalogueSource) {
try {
val res = source.getChapterList(sManga)
var chapterList: List<MangaChapter> = emptyList()
for (chapter in res) {
chapterList += SChapterToMangaChapter(chapter)
}
logger("chapterList size: ${chapterList.size}")
return chapterList
}
catch (e: Exception) {
logger("loadChapters Exception: $e")
}
return emptyList()
}
return emptyList() // Return an empty list if source is not a catalogueSource
}
override suspend fun loadImages(chapterLink: String, sChapter: SChapter): List<MangaImage> {
val source = extension.sources.first()
if (source is HttpSource) {
//try {
val res = source.getPageList(sChapter)
var chapterList: List<MangaImage> = emptyList()
for (page in res) {
println("page: $page")
currContext()?.let { fetchAndProcessImage(page, source, it.contentResolver) }
logger("new image url: ${page.imageUrl}")
chapterList += PageToMangaImage(page)
}
logger("image url: chapterList size: ${chapterList.size}")
return chapterList
//}
//catch (e: Exception) {
// logger("loadImages Exception: $e")
//}
return emptyList()
}
return emptyList() // Return an empty list if source is not a CatalogueSource
}
override suspend fun search(query: String): List<ShowResponse> {
val source = extension.sources.first()
if (source is HttpSource) {
var res: MangasPage? = null
try {
res = source.fetchSearchManga(1, query, FilterList()).toBlocking().first()
logger("res observable: $res")
}
catch (e: CloudflareBypassException) {
logger("Exception in search: $e")
Toast.makeText(currContext(), "Failed to bypass Cloudflare", Toast.LENGTH_SHORT).show()
}
val conv = convertMangasPageToShowResponse(res!!)
return conv
}
return emptyList() // Return an empty list if source is not a CatalogueSource
}
private fun convertMangasPageToShowResponse(mangasPage: MangasPage): List<ShowResponse> {
return mangasPage.mangas.map { sManga ->
// Extract required fields from sManga
val name = sManga.title
val link = sManga.url
val coverUrl = sManga.thumbnail_url ?: ""
val otherNames = emptyList<String>() // Populate as needed
val total = 20
val extra: Map<String, String>? = null // Populate as needed
// Create a new ShowResponse
ShowResponse(name, link, coverUrl, sManga)
}
}
private fun PageToMangaImage(page: Page): MangaImage {
//find and move any headers from page.imageUrl to headersMap
val headersMap: Map<String, String> = page.imageUrl?.split("&")?.mapNotNull {
val idx = it.indexOf("=")
if (idx != -1) {
val key = URLDecoder.decode(it.substring(0, idx), "UTF-8")
val value = URLDecoder.decode(it.substring(idx + 1), "UTF-8")
Pair(key, value)
} else {
null // Or some other default value
}
}?.toMap() ?: mapOf()
val urlWithoutHeaders = page.imageUrl?.split("&")?.get(0) ?: ""
val url = page.imageUrl ?: ""
logger("Pageurl: $url")
logger("regularurl: ${page.url}")
logger("regularurl: ${page.status}")
return MangaImage(
FileUrl(url, headersMap),
false,
page
)
}
private fun SChapterToMangaChapter(sChapter: SChapter): MangaChapter {
return MangaChapter(
sChapter.name,
sChapter.url,
sChapter.name,
null,
sChapter
)
}
}
class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
override val server: VideoServer
get() {
return videoServer