Temple Scan: migrate to HeanCms (#18899)
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,35 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.en.templescan
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.heancms.Genre
|
||||||
|
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
|
||||||
|
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||||
|
|
||||||
|
class TempleScan : HeanCms("Temple Scan", "https://templescan.net", "en") {
|
||||||
|
|
||||||
|
override val versionId = 3
|
||||||
|
|
||||||
|
override val client = super.client.newBuilder()
|
||||||
|
.rateLimit(1)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override val useNewQueryEndpoint = true
|
||||||
|
override val coverPath = ""
|
||||||
|
override val mangaSubDirectory = "comic"
|
||||||
|
|
||||||
|
override fun getGenreList() = listOf(
|
||||||
|
Genre("Drama", 1),
|
||||||
|
Genre("Josei", 2),
|
||||||
|
Genre("Romance", 3),
|
||||||
|
Genre("Girls Love", 4),
|
||||||
|
Genre("Reincarnation", 5),
|
||||||
|
Genre("Fantasia", 6),
|
||||||
|
Genre("Ecchi", 7),
|
||||||
|
Genre("Adventure", 8),
|
||||||
|
Genre("Boys Love", 9),
|
||||||
|
Genre("School Life", 10),
|
||||||
|
Genre("Action", 11),
|
||||||
|
Genre("Military", 13),
|
||||||
|
Genre("Comedy", 14),
|
||||||
|
Genre("Apocalypse", 15),
|
||||||
|
)
|
||||||
|
}
|
|
@ -63,6 +63,8 @@ abstract class HeanCms(
|
||||||
|
|
||||||
protected open val coverPath: String = "cover/"
|
protected open val coverPath: String = "cover/"
|
||||||
|
|
||||||
|
protected open val mangaSubDirectory: String = "series"
|
||||||
|
|
||||||
protected open val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US)
|
protected open val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.US)
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
||||||
|
@ -116,7 +118,7 @@ abstract class HeanCms(
|
||||||
preferences.slugMap = preferences.slugMap.toMutableMap()
|
preferences.slugMap = preferences.slugMap.toMutableMap()
|
||||||
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
||||||
}
|
}
|
||||||
it.toSManga(apiUrl, coverPath, slugStrategy)
|
it.toSManga(apiUrl, coverPath, mangaSubDirectory, slugStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllTitles()
|
fetchAllTitles()
|
||||||
|
@ -130,7 +132,7 @@ abstract class HeanCms(
|
||||||
preferences.slugMap = preferences.slugMap.toMutableMap()
|
preferences.slugMap = preferences.slugMap.toMutableMap()
|
||||||
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
||||||
}
|
}
|
||||||
it.toSManga(apiUrl, coverPath, slugStrategy)
|
it.toSManga(apiUrl, coverPath, mangaSubDirectory, slugStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllTitles()
|
fetchAllTitles()
|
||||||
|
@ -186,9 +188,9 @@ abstract class HeanCms(
|
||||||
val manga = SManga.create().apply {
|
val manga = SManga.create().apply {
|
||||||
url = if (slugStrategy != SlugStrategy.NONE) {
|
url = if (slugStrategy != SlugStrategy.NONE) {
|
||||||
val mangaId = getIdBySlug(slug)
|
val mangaId = getIdBySlug(slug)
|
||||||
"/series/${slug.toPermSlugIfNeeded()}#$mangaId"
|
"/$mangaSubDirectory/${slug.toPermSlugIfNeeded()}#$mangaId"
|
||||||
} else {
|
} else {
|
||||||
"/series/$slug"
|
"/$mangaSubDirectory/$slug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +287,7 @@ abstract class HeanCms(
|
||||||
.filter { it.type == "Comic" }
|
.filter { it.type == "Comic" }
|
||||||
.map {
|
.map {
|
||||||
it.slug = it.slug.toPermSlugIfNeeded()
|
it.slug = it.slug.toPermSlugIfNeeded()
|
||||||
it.toSManga(apiUrl, coverPath, seriesSlugMap.orEmpty(), slugStrategy)
|
it.toSManga(apiUrl, coverPath, mangaSubDirectory, seriesSlugMap.orEmpty(), slugStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
return MangasPage(mangaList, false)
|
return MangasPage(mangaList, false)
|
||||||
|
@ -298,7 +300,7 @@ abstract class HeanCms(
|
||||||
preferences.slugMap = preferences.slugMap.toMutableMap()
|
preferences.slugMap = preferences.slugMap.toMutableMap()
|
||||||
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
||||||
}
|
}
|
||||||
it.toSManga(apiUrl, coverPath, slugStrategy)
|
it.toSManga(apiUrl, coverPath, mangaSubDirectory, slugStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllTitles()
|
fetchAllTitles()
|
||||||
|
@ -312,7 +314,7 @@ abstract class HeanCms(
|
||||||
preferences.slugMap = preferences.slugMap.toMutableMap()
|
preferences.slugMap = preferences.slugMap.toMutableMap()
|
||||||
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
.also { map -> map[it.slug.toPermSlugIfNeeded()] = it.slug }
|
||||||
}
|
}
|
||||||
it.toSManga(apiUrl, coverPath, slugStrategy)
|
it.toSManga(apiUrl, coverPath, mangaSubDirectory, slugStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllTitles()
|
fetchAllTitles()
|
||||||
|
@ -332,7 +334,7 @@ abstract class HeanCms(
|
||||||
seriesSlug
|
seriesSlug
|
||||||
}
|
}
|
||||||
|
|
||||||
return "$baseUrl/series/$currentSlug"
|
return "$baseUrl/$mangaSubDirectory/$currentSlug"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
|
@ -380,7 +382,7 @@ abstract class HeanCms(
|
||||||
.also { it[seriesResult.slug.toPermSlugIfNeeded()] = seriesResult.slug }
|
.also { it[seriesResult.slug.toPermSlugIfNeeded()] = seriesResult.slug }
|
||||||
}
|
}
|
||||||
|
|
||||||
val seriesDetails = seriesResult.toSManga(apiUrl, coverPath, slugStrategy)
|
val seriesDetails = seriesResult.toSManga(apiUrl, coverPath, mangaSubDirectory, slugStrategy)
|
||||||
|
|
||||||
return seriesDetails.apply {
|
return seriesDetails.apply {
|
||||||
status = status.takeUnless { it == SManga.UNKNOWN }
|
status = status.takeUnless { it == SManga.UNKNOWN }
|
||||||
|
@ -404,13 +406,13 @@ abstract class HeanCms(
|
||||||
return result.seasons.orEmpty()
|
return result.seasons.orEmpty()
|
||||||
.flatMap { it.chapters.orEmpty() }
|
.flatMap { it.chapters.orEmpty() }
|
||||||
.filterNot { it.price == 1 }
|
.filterNot { it.price == 1 }
|
||||||
.map { it.toSChapter(result.slug, dateFormat, slugStrategy) }
|
.map { it.toSChapter(result.slug, mangaSubDirectory, dateFormat, slugStrategy) }
|
||||||
.filter { it.date_upload <= currentTimestamp }
|
.filter { it.date_upload <= currentTimestamp }
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.chapters.orEmpty()
|
return result.chapters.orEmpty()
|
||||||
.filterNot { it.price == 1 }
|
.filterNot { it.price == 1 }
|
||||||
.map { it.toSChapter(result.slug, dateFormat, slugStrategy) }
|
.map { it.toSChapter(result.slug, mangaSubDirectory, dateFormat, slugStrategy) }
|
||||||
.filter { it.date_upload <= currentTimestamp }
|
.filter { it.date_upload <= currentTimestamp }
|
||||||
.reversed()
|
.reversed()
|
||||||
}
|
}
|
||||||
|
@ -419,7 +421,7 @@ abstract class HeanCms(
|
||||||
if (slugStrategy == SlugStrategy.NONE) return baseUrl + chapter.url
|
if (slugStrategy == SlugStrategy.NONE) return baseUrl + chapter.url
|
||||||
|
|
||||||
val seriesSlug = chapter.url
|
val seriesSlug = chapter.url
|
||||||
.substringAfter("/series/")
|
.substringAfter("/$mangaSubDirectory/")
|
||||||
.substringBefore("/")
|
.substringBefore("/")
|
||||||
.toPermSlugIfNeeded()
|
.toPermSlugIfNeeded()
|
||||||
|
|
||||||
|
@ -432,7 +434,7 @@ abstract class HeanCms(
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
if (useNewQueryEndpoint) {
|
if (useNewQueryEndpoint) {
|
||||||
if (slugStrategy != SlugStrategy.NONE) {
|
if (slugStrategy != SlugStrategy.NONE) {
|
||||||
val seriesPermSlug = chapter.url.substringAfter("/series/").substringBefore("/")
|
val seriesPermSlug = chapter.url.substringAfter("/$mangaSubDirectory/").substringBefore("/")
|
||||||
val seriesSlug = preferences.slugMap[seriesPermSlug] ?: seriesPermSlug
|
val seriesSlug = preferences.slugMap[seriesPermSlug] ?: seriesPermSlug
|
||||||
val chapterUrl = chapter.url.replaceFirst(seriesPermSlug, seriesSlug)
|
val chapterUrl = chapter.url.replaceFirst(seriesPermSlug, seriesSlug)
|
||||||
return GET(baseUrl + chapterUrl, headers)
|
return GET(baseUrl + chapterUrl, headers)
|
||||||
|
|
|
@ -36,6 +36,7 @@ data class HeanCmsSearchDto(
|
||||||
fun toSManga(
|
fun toSManga(
|
||||||
apiUrl: String,
|
apiUrl: String,
|
||||||
coverPath: String,
|
coverPath: String,
|
||||||
|
mangaSubDirectory: String,
|
||||||
slugMap: Map<String, HeanCms.HeanCmsTitle>,
|
slugMap: Map<String, HeanCms.HeanCmsTitle>,
|
||||||
slugStrategy: SlugStrategy,
|
slugStrategy: SlugStrategy,
|
||||||
): SManga = SManga.create().apply {
|
): SManga = SManga.create().apply {
|
||||||
|
@ -44,7 +45,7 @@ data class HeanCmsSearchDto(
|
||||||
title = this@HeanCmsSearchDto.title
|
title = this@HeanCmsSearchDto.title
|
||||||
thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
||||||
?: thumbnailFileName?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
?: thumbnailFileName?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
||||||
url = "/series/$slugOnly"
|
url = "/$mangaSubDirectory/$slugOnly"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +68,7 @@ data class HeanCmsSeriesDto(
|
||||||
fun toSManga(
|
fun toSManga(
|
||||||
apiUrl: String,
|
apiUrl: String,
|
||||||
coverPath: String,
|
coverPath: String,
|
||||||
|
mangaSubDirectory: String,
|
||||||
slugStrategy: SlugStrategy,
|
slugStrategy: SlugStrategy,
|
||||||
): SManga = SManga.create().apply {
|
): SManga = SManga.create().apply {
|
||||||
val descriptionBody = this@HeanCmsSeriesDto.description?.let(Jsoup::parseBodyFragment)
|
val descriptionBody = this@HeanCmsSeriesDto.description?.let(Jsoup::parseBodyFragment)
|
||||||
|
@ -85,9 +87,9 @@ data class HeanCmsSeriesDto(
|
||||||
?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
|
||||||
status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN
|
status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN
|
||||||
url = if (slugStrategy != SlugStrategy.NONE) {
|
url = if (slugStrategy != SlugStrategy.NONE) {
|
||||||
"/series/$slugOnly#$id"
|
"/$mangaSubDirectory/$slugOnly#$id"
|
||||||
} else {
|
} else {
|
||||||
"/series/$slug"
|
"/$mangaSubDirectory/$slug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +114,7 @@ data class HeanCmsChapterDto(
|
||||||
) {
|
) {
|
||||||
fun toSChapter(
|
fun toSChapter(
|
||||||
seriesSlug: String,
|
seriesSlug: String,
|
||||||
|
mangaSubDirectory: String,
|
||||||
dateFormat: SimpleDateFormat,
|
dateFormat: SimpleDateFormat,
|
||||||
slugStrategy: SlugStrategy,
|
slugStrategy: SlugStrategy,
|
||||||
): SChapter = SChapter.create().apply {
|
): SChapter = SChapter.create().apply {
|
||||||
|
@ -119,7 +122,7 @@ data class HeanCmsChapterDto(
|
||||||
name = this@HeanCmsChapterDto.name.trim()
|
name = this@HeanCmsChapterDto.name.trim()
|
||||||
date_upload = runCatching { dateFormat.parse(createdAt)?.time }
|
date_upload = runCatching { dateFormat.parse(createdAt)?.time }
|
||||||
.getOrNull() ?: 0L
|
.getOrNull() ?: 0L
|
||||||
url = "/series/$seriesSlugOnly/$slug#$id"
|
url = "/$mangaSubDirectory/$seriesSlugOnly/$slug#$id"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class HeanCmsGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Omega Scans", "https://omegascans.org", "en", isNsfw = true, overrideVersionCode = 18),
|
SingleLang("Omega Scans", "https://omegascans.org", "en", isNsfw = true, overrideVersionCode = 18),
|
||||||
SingleLang("Perf Scan", "https://perf-scan.fr", "fr"),
|
SingleLang("Perf Scan", "https://perf-scan.fr", "fr"),
|
||||||
SingleLang("Reaper Scans", "https://reaperscans.net", "pt-BR", overrideVersionCode = 36),
|
SingleLang("Reaper Scans", "https://reaperscans.net", "pt-BR", overrideVersionCode = 36),
|
||||||
|
SingleLang("Temple Scan", "https://templescan.net", "en", isNsfw = true, overrideVersionCode = 16),
|
||||||
SingleLang("YugenMangas", "https://yugenmangas.net", "es", isNsfw = true, overrideVersionCode = 9),
|
SingleLang("YugenMangas", "https://yugenmangas.net", "es", isNsfw = true, overrideVersionCode = 9),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<application>
|
|
||||||
<activity
|
|
||||||
android:name=".en.templescan.TempleScanUrlActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:exported="true"
|
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
|
|
||||||
<data
|
|
||||||
android:host="templescan.net"
|
|
||||||
android:pathPattern="/comic/..*"
|
|
||||||
android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
|
@ -1,12 +0,0 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlinx-serialization'
|
|
||||||
|
|
||||||
ext {
|
|
||||||
extName = 'Temple Scan'
|
|
||||||
pkgNameSuffix = 'en.templescan'
|
|
||||||
extClass = '.TempleScan'
|
|
||||||
extVersionCode = 33
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
|
@ -1,217 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.templescan
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
|
||||||
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.asJsoup
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import okhttp3.Response
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import rx.Observable
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.util.Calendar
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class TempleScan : HttpSource() {
|
|
||||||
|
|
||||||
override val name = "Temple Scan"
|
|
||||||
|
|
||||||
override val lang = "en"
|
|
||||||
|
|
||||||
override val baseUrl = "https://templescan.net"
|
|
||||||
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
override val versionId = 2
|
|
||||||
|
|
||||||
override val client = network.cloudflareClient.newBuilder()
|
|
||||||
.rateLimit(1)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
private val homeDocument: Document by lazy {
|
|
||||||
val response = client.newCall(GET(baseUrl, headers)).execute()
|
|
||||||
|
|
||||||
if (response.isSuccessful.not()) {
|
|
||||||
response.close()
|
|
||||||
throw Exception("Http Error ${response.code}")
|
|
||||||
}
|
|
||||||
|
|
||||||
response.use { it.asJsoup() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val seriesCache: List<Series> by lazy {
|
|
||||||
homeDocument.selectFirst("script:containsData(proyectos)")
|
|
||||||
?.data()
|
|
||||||
?.let { proyectosRegex.find(it)?.groupValues?.get(1) }
|
|
||||||
?.let(json::decodeFromString)
|
|
||||||
?: throw Exception("Unable to extract series information")
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var filteredSeriesCache: List<Series>
|
|
||||||
|
|
||||||
private fun List<Series>.toMangasPage(page: Int): MangasPage {
|
|
||||||
val end = min(page * limit, this.size)
|
|
||||||
val entries = this.subList((page - 1) * limit, end)
|
|
||||||
.map(Series::toSManga)
|
|
||||||
|
|
||||||
return MangasPage(entries, end < this.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Series(
|
|
||||||
@SerialName("nombre") val name: String,
|
|
||||||
val slug: String,
|
|
||||||
@SerialName("portada") val cover: String,
|
|
||||||
) {
|
|
||||||
fun toSManga() = SManga.create().apply {
|
|
||||||
url = "/comic/$slug"
|
|
||||||
title = name
|
|
||||||
thumbnail_url = cover
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
|
||||||
val mangasPage = seriesCache.toMangasPage(page)
|
|
||||||
|
|
||||||
return Observable.just(mangasPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
|
||||||
val slugs = homeDocument.select("section:contains(new release) figure")
|
|
||||||
.mapNotNull { element ->
|
|
||||||
element.selectFirst("a")?.attr("abs:href")
|
|
||||||
?.substringAfter("/comic/")
|
|
||||||
?.substringBefore("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
val entries = slugs.mapNotNull { slug ->
|
|
||||||
seriesCache.firstOrNull { it.slug == slug }?.toSManga()
|
|
||||||
}
|
|
||||||
|
|
||||||
val mangasPage = MangasPage(entries, false)
|
|
||||||
|
|
||||||
return Observable.just(mangasPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
|
||||||
if (query.startsWith(SEARCH_PREFIX)) {
|
|
||||||
val url = "/comic/${query.substringAfter(SEARCH_PREFIX)}"
|
|
||||||
val manga = SManga.create().apply { this.url = url }
|
|
||||||
return fetchMangaDetails(manga).map {
|
|
||||||
val newManga = it.apply { this.url = url }
|
|
||||||
MangasPage(listOf(newManga), false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page == 1) {
|
|
||||||
filteredSeriesCache = seriesCache.filter {
|
|
||||||
it.name.contains(query.trim(), true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val mangasPage = filteredSeriesCache.toMangasPage(page)
|
|
||||||
|
|
||||||
return Observable.just(mangasPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
|
||||||
val document = response.asJsoup()
|
|
||||||
|
|
||||||
return SManga.create().apply {
|
|
||||||
thumbnail_url = document.select(".max-w-80 > img").attr("abs:src")
|
|
||||||
description = document.select("section[id=section-sinopsis] p").text()
|
|
||||||
title = document.select("h1").text()
|
|
||||||
genre = document.select("div.flex div:contains(gen) + div a").joinToString { it.text().trim() }
|
|
||||||
author = document.selectFirst("div.flex div:contains(aut) + div")?.text()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
|
||||||
val elements = response.asJsoup()
|
|
||||||
.select("div.contenedor-capitulo-miniatura")
|
|
||||||
|
|
||||||
return elements.map { element ->
|
|
||||||
SChapter.create().apply {
|
|
||||||
setUrlWithoutDomain(element.select("a").attr("href"))
|
|
||||||
name = element.select("div[id=name]").text()
|
|
||||||
date_upload = element.select("time").text().let {
|
|
||||||
runCatching { it.parseRelativeDate() }.getOrDefault(0L)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
|
||||||
val elements = response.asJsoup()
|
|
||||||
.select("main div img")
|
|
||||||
|
|
||||||
return elements.mapIndexed { index, element ->
|
|
||||||
Page(index, "", element.attr("abs:src"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.parseRelativeDate(): Long {
|
|
||||||
val now = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
var parsedDate = 0L
|
|
||||||
|
|
||||||
val relativeDate = this.split(" ")[0].trim().toInt()
|
|
||||||
|
|
||||||
when {
|
|
||||||
"second" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.SECOND, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"minute" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.MINUTE, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"hour" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.HOUR, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"day" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.DAY_OF_YEAR, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"week" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.WEEK_OF_YEAR, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"month" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.MONTH, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
"year" in this -> {
|
|
||||||
parsedDate = now.apply { add(Calendar.YEAR, -relativeDate) }.timeInMillis
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parsedDate
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val proyectosRegex by lazy {
|
|
||||||
Regex("""proyectos\s*=\s*([^;]+)""")
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val limit = 20
|
|
||||||
const val SEARCH_PREFIX = "slug:"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun popularMangaParse(response: Response) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException("Not Used")
|
|
||||||
override fun searchMangaParse(response: Response) = throw UnsupportedOperationException("Not Used")
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.templescan
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import kotlin.system.exitProcess
|
|
||||||
|
|
||||||
class TempleScanUrlActivity : Activity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
val pathSegments = intent?.data?.pathSegments
|
|
||||||
if (pathSegments != null && pathSegments.size > 1) {
|
|
||||||
val slug = pathSegments[1]
|
|
||||||
val mainIntent = Intent().apply {
|
|
||||||
action = "eu.kanade.tachiyomi.SEARCH"
|
|
||||||
putExtra("query", "${TempleScan.SEARCH_PREFIX}$slug")
|
|
||||||
putExtra("filter", packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
startActivity(mainIntent)
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
Log.e("TempleScanUrlActivity", e.toString())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e("TempleScanUrlActivity", "could not parse uri from intent $intent")
|
|
||||||
}
|
|
||||||
|
|
||||||
finish()
|
|
||||||
exitProcess(0)
|
|
||||||
}
|
|
||||||
}
|
|