Make internal and delegated sources able to use getMangaDetails, getChapterList, and getPageList properly
This commit is contained in:
parent
23ac4b271c
commit
28fca8c839
@ -11,8 +11,10 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
|
|||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
import exh.metadata.metadata.base.insertFlatMetadata
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
|
import exh.util.await
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -33,6 +35,8 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
*/
|
*/
|
||||||
fun parseIntoMetadata(metadata: M, input: I)
|
fun parseIntoMetadata(metadata: M, input: I)
|
||||||
|
|
||||||
|
suspend fun parseInfoIntoMetadata(metadata: M, input: I) = parseIntoMetadata(metadata, input)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use reflection to create a new instance of metadata
|
* Use reflection to create a new instance of metadata
|
||||||
*/
|
*/
|
||||||
@ -46,6 +50,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
*
|
*
|
||||||
* Will also save the metadata to the DB if possible
|
* Will also save the metadata to the DB if possible
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use the MangaInfo variant")
|
||||||
fun parseToManga(manga: SManga, input: I): Completable {
|
fun parseToManga(manga: SManga, input: I): Completable {
|
||||||
val mangaId = manga.id
|
val mangaId = manga.id
|
||||||
val metaObservable = if (mangaId != null) {
|
val metaObservable = if (mangaId != null) {
|
||||||
@ -71,6 +76,22 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo {
|
||||||
|
val mangaId = manga.id()
|
||||||
|
val metadata = if (mangaId != null) {
|
||||||
|
val flatMetadata = db.getFlatMetadataForManga(mangaId).await()
|
||||||
|
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
||||||
|
} else newMetaInstance()
|
||||||
|
|
||||||
|
parseInfoIntoMetadata(metadata, input)
|
||||||
|
if (mangaId != null) {
|
||||||
|
metadata.mangaId = mangaId
|
||||||
|
db.insertFlatMetadata(metadata.flatten()).await()
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata.createMangaInfo(manga)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to first get the metadata from the DB. If the metadata is not in the DB, calls the input
|
* Try to first get the metadata from the DB. If the metadata is not in the DB, calls the input
|
||||||
* producer and parses the metadata from the input
|
* producer and parses the metadata from the input
|
||||||
@ -78,6 +99,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
* If the metadata needs to be parsed from the input producer, the resulting parsed metadata will
|
* If the metadata needs to be parsed from the input producer, the resulting parsed metadata will
|
||||||
* also be saved to the DB.
|
* also be saved to the DB.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("use fetchOrLoadMetadata made for MangaInfo")
|
||||||
fun getOrLoadMetadata(mangaId: Long?, inputProducer: () -> Single<I>): Single<M> {
|
fun getOrLoadMetadata(mangaId: Long?, inputProducer: () -> Single<I>): Single<M> {
|
||||||
val metaObservable = if (mangaId != null) {
|
val metaObservable = if (mangaId != null) {
|
||||||
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
||||||
@ -103,8 +125,34 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to first get the metadata from the DB. If the metadata is not in the DB, calls the input
|
||||||
|
* producer and parses the metadata from the input
|
||||||
|
*
|
||||||
|
* If the metadata needs to be parsed from the input producer, the resulting parsed metadata will
|
||||||
|
* also be saved to the DB.
|
||||||
|
*/
|
||||||
|
suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M {
|
||||||
|
val meta = if (mangaId != null) {
|
||||||
|
val flatMetadata = db.getFlatMetadataForManga(mangaId).await()
|
||||||
|
flatMetadata?.raise(metaClass)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta ?: inputProducer().let { input ->
|
||||||
|
val newMeta = newMetaInstance()
|
||||||
|
parseInfoIntoMetadata(newMeta, input)
|
||||||
|
if (mangaId != null) {
|
||||||
|
newMeta.mangaId = mangaId
|
||||||
|
db.insertFlatMetadata(newMeta.flatten()).let { newMeta }
|
||||||
|
} else newMeta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>?
|
fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>?
|
||||||
|
|
||||||
|
suspend fun MangaInfo.id() = db.getManga(key, id).await()?.id
|
||||||
val SManga.id get() = (this as? Manga)?.id
|
val SManga.id get() = (this as? Manga)?.id
|
||||||
val SChapter.mangaId get() = (this as? Chapter)?.manga_id
|
val SChapter.mangaId get() = (this as? Chapter)?.manga_id
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
@ -16,6 +17,8 @@ import eu.kanade.tachiyomi.source.model.MetadataMangasPage
|
|||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toChapterInfo
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -41,6 +44,7 @@ import exh.ui.metadata.adapters.EHentaiDescriptionAdapter
|
|||||||
import exh.util.UriFilter
|
import exh.util.UriFilter
|
||||||
import exh.util.UriGroup
|
import exh.util.UriGroup
|
||||||
import exh.util.asObservableWithAsyncStacktrace
|
import exh.util.asObservableWithAsyncStacktrace
|
||||||
|
import exh.util.awaitSingle
|
||||||
import exh.util.dropBlank
|
import exh.util.dropBlank
|
||||||
import exh.util.ignore
|
import exh.util.ignore
|
||||||
import exh.util.nullIfBlank
|
import exh.util.nullIfBlank
|
||||||
@ -72,6 +76,8 @@ import org.jsoup.nodes.Element
|
|||||||
import org.jsoup.nodes.TextNode
|
import org.jsoup.nodes.TextNode
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
|
import tachiyomi.source.model.ChapterInfo
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
@ -276,8 +282,13 @@ class EHentai(
|
|||||||
MetadataMangasPage(mangaFromSource.first.map { it.manga }, mangaFromSource.second, mangaFromSource.first.map { it.metadata })
|
MetadataMangasPage(mangaFromSource.first.map { it.manga }, mangaFromSource.second, mangaFromSource.first.map { it.metadata })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> = getChapterList(manga) {}
|
||||||
|
|
||||||
|
suspend fun getChapterList(manga: MangaInfo, throttleFunc: () -> Unit) = fetchChapterList(manga.toSManga(), throttleFunc).awaitSingle().map { it.toChapterInfo() }
|
||||||
|
|
||||||
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
|
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
|
||||||
|
|
||||||
|
@Deprecated("Use getChapterList instead")
|
||||||
fun fetchChapterList(manga: SManga, throttleFunc: () -> Unit): Observable<List<SChapter>> {
|
fun fetchChapterList(manga: SManga, throttleFunc: () -> Unit): Observable<List<SChapter>> {
|
||||||
return Single.fromCallable {
|
return Single.fromCallable {
|
||||||
// Pull all the way to the root gallery
|
// Pull all the way to the root gallery
|
||||||
@ -516,6 +527,31 @@ class EHentai(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val exception = Exception("Async stacktrace")
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
// Pull to most recent
|
||||||
|
val doc = response.asJsoup()
|
||||||
|
val newerGallery = doc.select("#gnd a").lastOrNull()
|
||||||
|
val pre = if (newerGallery != null && DebugToggles.PULL_TO_ROOT_WHEN_LOADING_EXH_MANGA_DETAILS.enabled) {
|
||||||
|
val sManga = manga.toSManga().apply {
|
||||||
|
url = EHentaiSearchMetadata.normalizeUrl(newerGallery.attr("href"))
|
||||||
|
}
|
||||||
|
client.newCall(mangaDetailsRequest(sManga)).await().asJsoup()
|
||||||
|
} else doc
|
||||||
|
return parseToManga(manga, pre)
|
||||||
|
} else {
|
||||||
|
response.close()
|
||||||
|
|
||||||
|
if (response.code == 404) {
|
||||||
|
throw GalleryNotFoundException(exception)
|
||||||
|
} else {
|
||||||
|
throw Exception("HTTP error ${response.code}", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse gallery page to metadata model
|
* Parse gallery page to metadata model
|
||||||
*/
|
*/
|
||||||
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -21,6 +23,7 @@ import exh.ui.metadata.adapters.HitomiDescriptionAdapter
|
|||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@ -46,6 +49,11 @@ class Hitomi(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: HitomiSearchMetadata, input: Document) {
|
override fun parseIntoMetadata(metadata: HitomiSearchMetadata, input: Document) {
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
url = input.location()
|
url = input.location()
|
||||||
|
@ -57,6 +57,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
@ -126,6 +127,10 @@ class MangaDex(delegate: HttpSource, val context: Context) :
|
|||||||
return MangaHandler(client, headers, listOf(mdLang), preferences.mangaDexForceLatestCovers().get()).fetchMangaDetailsObservable(manga)
|
return MangaHandler(client, headers, listOf(mdLang), preferences.mangaDexForceLatestCovers().get()).fetchMangaDetailsObservable(manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
return MangaHandler(client, headers, listOf(mdLang), preferences.mangaDexForceLatestCovers().get()).getMangaDetails(manga, id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
return MangaHandler(client, headers, listOf(mdLang), preferences.mangaDexForceLatestCovers().get()).fetchChapterListObservable(manga)
|
return MangaHandler(client, headers, listOf(mdLang), preferences.mangaDexForceLatestCovers().get()).fetchChapterListObservable(manga)
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -24,6 +26,7 @@ import kotlinx.serialization.decodeFromString
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class NHentai(delegate: HttpSource, val context: Context) :
|
class NHentai(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -63,6 +66,11 @@ class NHentai(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response)
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: NHentaiSearchMetadata, input: Response) {
|
override fun parseIntoMetadata(metadata: NHentaiSearchMetadata, input: Response) {
|
||||||
val json = GALLERY_JSON_REGEX.find(input.body!!.string())!!.groupValues[1].replace(
|
val json = GALLERY_JSON_REGEX.find(input.body!!.string())!!.groupValues[1].replace(
|
||||||
UNICODE_ESCAPE_REGEX
|
UNICODE_ESCAPE_REGEX
|
||||||
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -22,6 +24,7 @@ import org.jsoup.nodes.Document
|
|||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import org.jsoup.nodes.TextNode
|
import org.jsoup.nodes.TextNode
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class PervEden(delegate: HttpSource, val context: Context) :
|
class PervEden(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -44,6 +47,11 @@ class PervEden(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: PervEdenSearchMetadata, input: Document) {
|
override fun parseIntoMetadata(metadata: PervEdenSearchMetadata, input: Document) {
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
url = input.location().toUri().path
|
url = input.location().toUri().path
|
||||||
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -21,6 +23,7 @@ import exh.util.urlImportFetchSearchManga
|
|||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class EightMuses(delegate: HttpSource, val context: Context) :
|
class EightMuses(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -44,6 +47,11 @@ class EightMuses(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
data class SelfContents(val albums: List<Element>, val images: List<Element>)
|
data class SelfContents(val albums: List<Element>, val images: List<Element>)
|
||||||
|
|
||||||
private fun parseSelf(doc: Document): SelfContents {
|
private fun parseSelf(doc: Document): SelfContents {
|
||||||
|
@ -3,9 +3,11 @@ package eu.kanade.tachiyomi.source.online.english
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -20,6 +22,7 @@ import exh.util.urlImportFetchSearchManga
|
|||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class HBrowse(delegate: HttpSource, val context: Context) :
|
class HBrowse(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -43,6 +46,11 @@ class HBrowse(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: HBrowseSearchMetadata, input: Document) {
|
override fun parseIntoMetadata(metadata: HBrowseSearchMetadata, input: Document) {
|
||||||
val tables = parseIntoTables(input)
|
val tables = parseIntoTables(input)
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
|
@ -3,14 +3,17 @@ package eu.kanade.tachiyomi.source.online.english
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||||
import exh.metadata.metadata.HentaiCafeSearchMetadata
|
import exh.metadata.metadata.HentaiCafeSearchMetadata
|
||||||
import exh.metadata.metadata.HentaiCafeSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
import exh.metadata.metadata.HentaiCafeSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
||||||
@ -21,6 +24,8 @@ import exh.util.urlImportFetchSearchManga
|
|||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.ChapterInfo
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class HentaiCafe(delegate: HttpSource, val context: Context) :
|
class HentaiCafe(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -56,6 +61,11 @@ class HentaiCafe(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the supplied input into the supplied metadata object
|
* Parse the supplied input into the supplied metadata object
|
||||||
*/
|
*/
|
||||||
@ -86,12 +96,12 @@ class HentaiCafe(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchChapterList(manga: SManga) = getOrLoadMetadata(manga.id) {
|
override fun fetchChapterList(manga: SManga) = runAsObservable({
|
||||||
client.newCall(mangaDetailsRequest(manga))
|
fetchOrLoadMetadata(manga.id) {
|
||||||
.asObservableSuccess()
|
val response = client.newCall(mangaDetailsRequest(manga)).await()
|
||||||
.map { it.asJsoup() }
|
response.asJsoup()
|
||||||
.toSingle()
|
}
|
||||||
}.map {
|
}).map {
|
||||||
listOf(
|
listOf(
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
url = "/manga/read/${it.readerId}/en/0/1/"
|
url = "/manga/read/${it.readerId}/en/0/1/"
|
||||||
@ -99,7 +109,21 @@ class HentaiCafe(delegate: HttpSource, val context: Context) :
|
|||||||
chapter_number = 0.0f
|
chapter_number = 0.0f
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}.toObservable()
|
}
|
||||||
|
|
||||||
|
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
|
||||||
|
val metadata = fetchOrLoadMetadata(manga.id()) {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
response.asJsoup()
|
||||||
|
}
|
||||||
|
return listOf(
|
||||||
|
ChapterInfo(
|
||||||
|
key = "/manga/read/${metadata.readerId}/en/0/1/",
|
||||||
|
name = "Chapter",
|
||||||
|
number = 0F
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override val matchingHosts = listOf(
|
override val matchingHosts = listOf(
|
||||||
"hentai.cafe"
|
"hentai.cafe"
|
||||||
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -23,6 +25,7 @@ import exh.util.trimAll
|
|||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class Pururin(delegate: HttpSource, val context: Context) :
|
class Pururin(delegate: HttpSource, val context: Context) :
|
||||||
DelegatedHttpSource(delegate),
|
DelegatedHttpSource(delegate),
|
||||||
@ -60,6 +63,11 @@ class Pururin(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: PururinSearchMetadata, input: Document) {
|
override fun parseIntoMetadata(metadata: PururinSearchMetadata, input: Document) {
|
||||||
val selfLink = input.select("[itemprop=name]").last().parent()
|
val selfLink = input.select("[itemprop=name]").last().parent()
|
||||||
val parsedSelfLink = selfLink.attr("href").toUri().pathSegments
|
val parsedSelfLink = selfLink.attr("href").toUri().pathSegments
|
||||||
|
@ -3,9 +3,11 @@ package eu.kanade.tachiyomi.source.online.english
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||||
@ -23,6 +25,7 @@ import exh.util.trimAll
|
|||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@ -56,6 +59,11 @@ class Tsumino(delegate: HttpSource, val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
|
||||||
|
return parseToManga(manga, response.asJsoup())
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: TsuminoSearchMetadata, input: Document) {
|
override fun parseIntoMetadata(metadata: TsuminoSearchMetadata, input: Document) {
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
tmId = TsuminoSearchMetadata.tmIdFromUrl(input.location())!!.toInt()
|
tmId = TsuminoSearchMetadata.tmIdFromUrl(input.location())!!.toInt()
|
||||||
|
@ -14,6 +14,7 @@ import exh.metadata.metadata.MangaDexSearchMetadata
|
|||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
import exh.metadata.metadata.base.insertFlatMetadata
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
|
import exh.util.await
|
||||||
import exh.util.floor
|
import exh.util.floor
|
||||||
import exh.util.nullIfZero
|
import exh.util.nullIfZero
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
@ -24,6 +25,7 @@ import kotlinx.serialization.json.jsonPrimitive
|
|||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
@ -70,6 +72,24 @@ class ApiMangaParser(private val langs: List<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun parseToManga(manga: MangaInfo, input: Response, forceLatestCover: Boolean, sourceId: Long): MangaInfo {
|
||||||
|
val mangaId = db.getManga(manga.key, sourceId).await()?.id
|
||||||
|
val metadata = if (mangaId != null) {
|
||||||
|
val flatMetadata = db.getFlatMetadataForManga(mangaId).await()
|
||||||
|
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
||||||
|
} else newMetaInstance()
|
||||||
|
|
||||||
|
parseInfoIntoMetadata(metadata, input, forceLatestCover)
|
||||||
|
if (mangaId != null) {
|
||||||
|
metadata.mangaId = mangaId
|
||||||
|
db.insertFlatMetadata(metadata.flatten()).await()
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata.createMangaInfo(manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseInfoIntoMetadata(metadata: MangaDexSearchMetadata, input: Response, forceLatestCover: Boolean) = parseIntoMetadata(metadata, input, forceLatestCover)
|
||||||
|
|
||||||
fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Response, forceLatestCover: Boolean) {
|
fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Response, forceLatestCover: Boolean) {
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
try {
|
try {
|
||||||
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
|||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import exh.md.utils.MdUtil
|
import exh.md.utils.MdUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -14,6 +15,7 @@ import okhttp3.Headers
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: List<String>, val forceLatestCovers: Boolean = false) {
|
class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: List<String>, val forceLatestCovers: Boolean = false) {
|
||||||
|
|
||||||
@ -56,6 +58,13 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long): MangaInfo {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
val response = client.newCall(apiRequest(manga.toSManga())).await()
|
||||||
|
ApiMangaParser(langs).parseToManga(manga, response, forceLatestCovers, sourceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun fetchMangaDetailsObservable(manga: SManga): Observable<SManga> {
|
fun fetchMangaDetailsObservable(manga: SManga): Observable<SManga> {
|
||||||
return client.newCall(apiRequest(manga))
|
return client.newCall(apiRequest(manga))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.MetadataUtil
|
import exh.metadata.MetadataUtil
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -42,6 +43,53 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
var aged: Boolean = false
|
var aged: Boolean = false
|
||||||
var lastUpdateCheck: Long = 0
|
var lastUpdateCheck: Long = 0
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = gId?.let { gId ->
|
||||||
|
gToken?.let { gToken ->
|
||||||
|
idAndTokenToUrl(gId, gToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
// No title bug?
|
||||||
|
val title = if (Injekt.get<PreferencesHelper>().useJapaneseTitle().get()) {
|
||||||
|
altTitle ?: title
|
||||||
|
} else {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set artist (if we can find one)
|
||||||
|
val artist = tags.filter { it.namespace == EH_ARTIST_NAMESPACE }.let { tags ->
|
||||||
|
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy tags -> genres
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
// Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
||||||
|
// We default to completed
|
||||||
|
var status = MangaInfo.COMPLETED
|
||||||
|
title?.let { t ->
|
||||||
|
MetadataUtil.ONGOING_SUFFIX.find {
|
||||||
|
t.endsWith(it, ignoreCase = true)
|
||||||
|
}?.let {
|
||||||
|
status = MangaInfo.ONGOING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
description = description,
|
||||||
|
genres = genres,
|
||||||
|
status = status,
|
||||||
|
cover = cover ?: manga.cover
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
gId?.let { gId ->
|
gId?.let { gId ->
|
||||||
gToken?.let { gToken ->
|
gToken?.let { gToken ->
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class EightMusesSearchMetadata : RaisedSearchMetadata() {
|
class EightMusesSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -14,6 +15,29 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var thumbnailUrl: String? = null
|
var thumbnailUrl: String? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = path.joinToString("/", prefix = "/")
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
val artist = tags.ofNamespace(ARTIST_NAMESPACE).joinToString { it.name }
|
||||||
|
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
artist = artist,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
manga.url = path.joinToString("/", prefix = "/")
|
manga.url = path.joinToString("/", prefix = "/")
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class HBrowseSearchMetadata : RaisedSearchMetadata() {
|
class HBrowseSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -19,6 +20,32 @@ class HBrowseSearchMetadata : RaisedSearchMetadata() {
|
|||||||
// Length in pages
|
// Length in pages
|
||||||
var length: Int? = null
|
var length: Int? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = hbUrl
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
|
||||||
|
// Guess thumbnail URL if manga does not have thumbnail URL
|
||||||
|
val cover = if (manga.cover.isBlank()) {
|
||||||
|
guessThumbnailUrl(hbId.toString())
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val artist = tags.ofNamespace(ARTIST_NAMESPACE).joinToString { it.name }
|
||||||
|
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
artist = artist,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
hbUrl?.let {
|
hbUrl?.let {
|
||||||
manga.url = it
|
manga.url = it
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
|
class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -24,6 +25,31 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var artist: String? = null
|
var artist: String? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
val artist = artist
|
||||||
|
val author = artist
|
||||||
|
|
||||||
|
// Not available
|
||||||
|
val status = MangaInfo.UNKNOWN
|
||||||
|
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
author = author ?: manga.author,
|
||||||
|
status = status,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
thumbnailUrl?.let { manga.thumbnail_url = it }
|
thumbnailUrl?.let { manga.thumbnail_url = it }
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.MetadataUtil
|
import exh.metadata.MetadataUtil
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -37,6 +38,30 @@ class HitomiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var uploadDate: Long? = null
|
var uploadDate: Long? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
|
||||||
|
// Copy tags -> genres
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val artist = artists.joinToString()
|
||||||
|
|
||||||
|
val status = MangaInfo.UNKNOWN
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
genres = genres,
|
||||||
|
artist = artist,
|
||||||
|
status = status,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
thumbnailUrl?.let { manga.thumbnail_url = it }
|
thumbnailUrl?.let { manga.thumbnail_url = it }
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class MangaDexSearchMetadata : RaisedSearchMetadata() {
|
class MangaDexSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -40,6 +41,43 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var follow_status: Int? = null
|
var follow_status: Int? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = mdUrl?.let {
|
||||||
|
try {
|
||||||
|
val uri = it.toUri()
|
||||||
|
val out = uri.path!!.removePrefix("/api")
|
||||||
|
out + if (out.endsWith("/")) "" else "/"
|
||||||
|
} catch (e: Exception) {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
|
||||||
|
val cover = thumbnail_url
|
||||||
|
|
||||||
|
val author = author
|
||||||
|
|
||||||
|
val artist = artist
|
||||||
|
|
||||||
|
val status = status
|
||||||
|
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = description
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
author = author ?: manga.author,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
status = status ?: manga.status,
|
||||||
|
genres = genres,
|
||||||
|
description = description ?: manga.description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
mdUrl?.let {
|
mdUrl?.let {
|
||||||
manga.url = try {
|
manga.url = try {
|
||||||
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.MetadataUtil
|
import exh.metadata.MetadataUtil
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -37,6 +38,53 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var preferredTitle: Int? = null
|
var preferredTitle: Int? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = nhId?.let { nhIdToPath(it) }
|
||||||
|
|
||||||
|
val cover = if (mediaId != null) {
|
||||||
|
typeToExtension(coverImageType)?.let {
|
||||||
|
"https://t.nhentai.net/galleries/$mediaId/cover.$it"
|
||||||
|
}
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val title = when (preferredTitle) {
|
||||||
|
TITLE_TYPE_SHORT -> shortTitle ?: englishTitle ?: japaneseTitle ?: manga.title
|
||||||
|
0, TITLE_TYPE_ENGLISH -> englishTitle ?: japaneseTitle ?: shortTitle ?: manga.title
|
||||||
|
else -> englishTitle ?: japaneseTitle ?: shortTitle ?: manga.title
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set artist (if we can find one)
|
||||||
|
val artist = tags.filter { it.namespace == NHENTAI_ARTIST_NAMESPACE }.let { tags ->
|
||||||
|
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy tags -> genres
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
// Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
||||||
|
// We default to completed
|
||||||
|
var status = SManga.COMPLETED
|
||||||
|
englishTitle?.let { t ->
|
||||||
|
MetadataUtil.ONGOING_SUFFIX.find {
|
||||||
|
t.endsWith(it, ignoreCase = true)
|
||||||
|
}?.let {
|
||||||
|
status = SManga.ONGOING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
title = title,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
genres = genres,
|
||||||
|
status = status,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
nhId?.let { manga.url = nhIdToPath(it) }
|
nhId?.let { manga.url = nhIdToPath(it) }
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.RaisedTitle
|
import exh.metadata.metadata.base.RaisedTitle
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class PervEdenSearchMetadata : RaisedSearchMetadata() {
|
class PervEdenSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -33,6 +34,36 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var lang: String? = null
|
var lang: String? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = url
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
val title = title
|
||||||
|
|
||||||
|
val artist = artist
|
||||||
|
|
||||||
|
val status = when (status) {
|
||||||
|
"Ongoing" -> MangaInfo.ONGOING
|
||||||
|
"Completed", "Suspended" -> MangaInfo.COMPLETED
|
||||||
|
else -> MangaInfo.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy tags -> genres
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
status = status,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
url?.let { manga.url = it }
|
url?.let { manga.url = it }
|
||||||
thumbnailUrl?.let { manga.thumbnail_url = it }
|
thumbnailUrl?.let { manga.thumbnail_url = it }
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class PururinSearchMetadata : RaisedSearchMetadata() {
|
class PururinSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -26,6 +27,33 @@ class PururinSearchMetadata : RaisedSearchMetadata() {
|
|||||||
var ratingCount: Int? = null
|
var ratingCount: Int? = null
|
||||||
var averageRating: Double? = null
|
var averageRating: Double? = null
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val key = prId?.let { prId ->
|
||||||
|
prShortLink?.let { prShortLink ->
|
||||||
|
"/gallery/$prId/$prShortLink"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val title = title ?: altTitle
|
||||||
|
|
||||||
|
val cover = thumbnailUrl
|
||||||
|
|
||||||
|
val artist = tags.ofNamespace(TAG_NAMESPACE_ARTIST).joinToString { it.name }
|
||||||
|
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
key = key ?: manga.key,
|
||||||
|
title = title ?: manga.title,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
artist = artist,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
prId?.let { prId ->
|
prId?.let { prId ->
|
||||||
prShortLink?.let { prShortLink ->
|
prShortLink?.let { prShortLink ->
|
||||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.MetadataUtil
|
import exh.metadata.MetadataUtil
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@ -41,6 +42,29 @@ class TsuminoSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
var character: List<String> = emptyList()
|
var character: List<String> = emptyList()
|
||||||
|
|
||||||
|
override fun createMangaInfo(manga: MangaInfo): MangaInfo {
|
||||||
|
val title = title
|
||||||
|
val cover = tmId?.let { BASE_URL.replace("www", "content") + thumbUrlFromId(it.toString()) }
|
||||||
|
|
||||||
|
val artist = artist
|
||||||
|
|
||||||
|
val status = SManga.UNKNOWN
|
||||||
|
|
||||||
|
// Copy tags -> genres
|
||||||
|
val genres = tagsToGenreList()
|
||||||
|
|
||||||
|
val description = "meta"
|
||||||
|
|
||||||
|
return manga.copy(
|
||||||
|
title = title ?: manga.title,
|
||||||
|
cover = cover ?: manga.cover,
|
||||||
|
artist = artist ?: manga.artist,
|
||||||
|
status = status,
|
||||||
|
genres = genres,
|
||||||
|
description = description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun copyTo(manga: SManga) {
|
override fun copyTo(manga: SManga) {
|
||||||
title?.let { manga.title = it }
|
title?.let { manga.title = it }
|
||||||
manga.thumbnail_url = BASE_URL.replace("www", "content") + thumbUrlFromId(tmId.toString())
|
manga.thumbnail_url = BASE_URL.replace("www", "content") + thumbUrlFromId(tmId.toString())
|
||||||
|
@ -25,6 +25,7 @@ import kotlinx.serialization.json.Json
|
|||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import kotlinx.serialization.modules.polymorphic
|
import kotlinx.serialization.modules.polymorphic
|
||||||
import kotlinx.serialization.modules.subclass
|
import kotlinx.serialization.modules.subclass
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@ -57,8 +58,12 @@ abstract class RaisedSearchMetadata {
|
|||||||
|
|
||||||
abstract fun copyTo(manga: SManga)
|
abstract fun copyTo(manga: SManga)
|
||||||
|
|
||||||
|
abstract fun createMangaInfo(manga: MangaInfo): MangaInfo
|
||||||
|
|
||||||
fun tagsToGenreString() = tags.toGenreString()
|
fun tagsToGenreString() = tags.toGenreString()
|
||||||
|
|
||||||
|
fun tagsToGenreList() = tags.toGenreList()
|
||||||
|
|
||||||
fun tagsToDescription() =
|
fun tagsToDescription() =
|
||||||
StringBuilder("Tags:\n").apply {
|
StringBuilder("Tags:\n").apply {
|
||||||
// BiConsumer only available in Java 8, don't bother calling forEach directly on 'tags'
|
// BiConsumer only available in Java 8, don't bother calling forEach directly on 'tags'
|
||||||
@ -142,6 +147,10 @@ abstract class RaisedSearchMetadata {
|
|||||||
(this).filter { it.type != TAG_TYPE_VIRTUAL }
|
(this).filter { it.type != TAG_TYPE_VIRTUAL }
|
||||||
.joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
|
.joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
|
||||||
|
|
||||||
|
fun MutableList<RaisedTag>.toGenreList() =
|
||||||
|
(this).filter { it.type != TAG_TYPE_VIRTUAL }
|
||||||
|
.map { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
|
||||||
|
|
||||||
private val module = SerializersModule {
|
private val module = SerializersModule {
|
||||||
polymorphic(RaisedSearchMetadata::class) {
|
polymorphic(RaisedSearchMetadata::class) {
|
||||||
subclass(EHentaiSearchMetadata::class)
|
subclass(EHentaiSearchMetadata::class)
|
||||||
|
@ -10,6 +10,8 @@ import okhttp3.OkHttpClient
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import tachiyomi.source.model.ChapterInfo
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
|
|
||||||
abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
||||||
/**
|
/**
|
||||||
@ -185,6 +187,14 @@ abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
|||||||
return delegate.fetchMangaDetails(manga)
|
return delegate.fetchMangaDetails(manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get the updated details for a manga.
|
||||||
|
*/
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
|
||||||
|
ensureDelegateCompatible()
|
||||||
|
return delegate.getMangaDetails(manga)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for the details of a manga. Override only if it's needed to change the
|
* Returns the request for the details of a manga. Override only if it's needed to change the
|
||||||
* url, send different headers or request method like POST.
|
* url, send different headers or request method like POST.
|
||||||
@ -207,6 +217,14 @@ abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
|||||||
return delegate.fetchChapterList(manga)
|
return delegate.fetchChapterList(manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get all the available chapters for a manga.
|
||||||
|
*/
|
||||||
|
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
|
||||||
|
ensureDelegateCompatible()
|
||||||
|
return delegate.getChapterList(manga)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable with the page list for a chapter.
|
* Returns an observable with the page list for a chapter.
|
||||||
*
|
*
|
||||||
@ -217,6 +235,14 @@ abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
|||||||
return delegate.fetchPageList(chapter)
|
return delegate.fetchPageList(chapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get the list of pages a chapter has.
|
||||||
|
*/
|
||||||
|
override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> {
|
||||||
|
ensureDelegateCompatible()
|
||||||
|
return delegate.getPageList(chapter)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable with the page containing the source url of the image. If there's any
|
* Returns an observable with the page containing the source url of the image. If there's any
|
||||||
* error, it will return null instead of throwing an exception.
|
* error, it will return null instead of throwing an exception.
|
||||||
|
@ -9,6 +9,8 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
import tachiyomi.source.model.ChapterInfo
|
||||||
|
import tachiyomi.source.model.MangaInfo
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class EnhancedHttpSource(
|
class EnhancedHttpSource(
|
||||||
@ -177,6 +179,11 @@ class EnhancedHttpSource(
|
|||||||
*/
|
*/
|
||||||
override fun fetchMangaDetails(manga: SManga) = source().fetchMangaDetails(manga)
|
override fun fetchMangaDetails(manga: SManga) = source().fetchMangaDetails(manga)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get the updated details for a manga.
|
||||||
|
*/
|
||||||
|
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo = source().getMangaDetails(manga)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for the details of a manga. Override only if it's needed to change the
|
* Returns the request for the details of a manga. Override only if it's needed to change the
|
||||||
* url, send different headers or request method like POST.
|
* url, send different headers or request method like POST.
|
||||||
@ -193,6 +200,11 @@ class EnhancedHttpSource(
|
|||||||
*/
|
*/
|
||||||
override fun fetchChapterList(manga: SManga) = source().fetchChapterList(manga)
|
override fun fetchChapterList(manga: SManga) = source().fetchChapterList(manga)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get all the available chapters for a manga.
|
||||||
|
*/
|
||||||
|
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> = source().getChapterList(manga)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable with the page list for a chapter.
|
* Returns an observable with the page list for a chapter.
|
||||||
*
|
*
|
||||||
@ -200,6 +212,11 @@ class EnhancedHttpSource(
|
|||||||
*/
|
*/
|
||||||
override fun fetchPageList(chapter: SChapter) = source().fetchPageList(chapter)
|
override fun fetchPageList(chapter: SChapter) = source().fetchPageList(chapter)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1.x API] Get the list of pages a chapter has.
|
||||||
|
*/
|
||||||
|
override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> = source().getPageList(chapter)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable with the page containing the source url of the image. If there's any
|
* Returns an observable with the page containing the source url of the image. If there's any
|
||||||
* error, it will return null instead of throwing an exception.
|
* error, it will return null instead of throwing an exception.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user