Move Olympus Scanlation to an individual extension (#15540)
* created OlympusScan * adjustments * removed old olympus scanlation ext * adjustments
|
@ -1,35 +0,0 @@
|
|||
package eu.kanade.tachiyomi.extension.all.olympusscanlation
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
import okhttp3.OkHttpClient
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class OlympusScanlationFactory : SourceFactory {
|
||||
override fun createSources() = listOf(
|
||||
OlympusScanlationBr(),
|
||||
OlympusScanlationEs(),
|
||||
)
|
||||
}
|
||||
|
||||
abstract class OlympusScanlation(
|
||||
override val baseUrl: String,
|
||||
lang: String,
|
||||
dateFormat: SimpleDateFormat = SimpleDateFormat("MMMMM dd, yyyy", Locale.US),
|
||||
) : Madara("Olympus Scanlation", baseUrl, lang, dateFormat)
|
||||
|
||||
class OlympusScanlationEs : OlympusScanlation("https://olympusscanlation.com", "es")
|
||||
|
||||
class OlympusScanlationBr : OlympusScanlation(
|
||||
"https://br.olympusscanlation.com",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("MMMMM dd, yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
|
||||
override val client: OkHttpClient = super.client.newBuilder()
|
||||
.rateLimit(1, 2, TimeUnit.SECONDS)
|
||||
.build()
|
||||
}
|
|
@ -16,7 +16,6 @@ class MadaraGenerator : ThemeSourceGenerator {
|
|||
MultiLang("Leviatan Scans", "https://leviatanscans.com", listOf("en", "es"), className = "LeviatanScansFactory", overrideVersionCode = 13),
|
||||
MultiLang("MangaForFree.net", "https://mangaforfree.net", listOf("en", "ko", "all"), isNsfw = true, className = "MangaForFreeFactory", pkgName = "mangaforfree", overrideVersionCode = 1),
|
||||
MultiLang("Manhwa18.cc", "https://manhwa18.cc", listOf("en", "ko", "all"), isNsfw = true, className = "Manhwa18CcFactory", pkgName = "manhwa18cc", overrideVersionCode = 4),
|
||||
MultiLang("Olympus Scanlation", "https://olympusscanlation.com", listOf("es", "pt-BR")),
|
||||
MultiLang("Reaper Scans", "https://reaperscans.com", listOf("fr", "tr"), className = "ReaperScansFactory", pkgName = "reaperscans", overrideVersionCode = 12),
|
||||
SingleLang("1st Kiss Manga.love", "https://1stkissmanga.love", "en", className = "FirstKissMangaLove", overrideVersionCode = 2),
|
||||
SingleLang("1st Kiss Manhua", "https://1stkissmanhua.com", "en", className = "FirstKissManhua", overrideVersionCode = 4),
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
|
@ -0,0 +1,13 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
|
||||
ext {
|
||||
extName = 'Olympus Scanlation'
|
||||
pkgNameSuffix = 'es.olympusscanlation'
|
||||
extClass = '.OlympusScanlation'
|
||||
extVersionCode = 2
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
@ -0,0 +1,165 @@
|
|||
package eu.kanade.tachiyomi.extension.es.olympusscanlation
|
||||
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.ChapterDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.MangaDetailDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.MangaDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.PayloadChapterDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.PayloadHomeDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.PayloadMangaDto
|
||||
import eu.kanade.tachiyomi.extension.es.olympusscanlation.dto.OlympusScanlationDto.PayloadPagesDto
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
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 kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
class OlympusScanlation : HttpSource() {
|
||||
|
||||
override val baseUrl: String = "https://olympusscans.com"
|
||||
private val apiBaseUrl: String = "https://dashboard.olympusscans.com"
|
||||
override val lang: String = "es"
|
||||
override val name: String = "Olympus Scanlation"
|
||||
override val versionId = 2
|
||||
override val supportsLatest: Boolean = true
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
// Search
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val apiUrl = "$apiBaseUrl/api/search".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("name", query)
|
||||
.build()
|
||||
return GET(apiUrl, headers)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val result = json.decodeFromString<PayloadMangaDto>(response.body.string())
|
||||
val mangaList = result.data.map {
|
||||
SManga.create().apply {
|
||||
url = "/series/comic-${it.slug}"
|
||||
title = it.name
|
||||
thumbnail_url = it.cover
|
||||
}
|
||||
}
|
||||
return MangasPage(mangaList, hasNextPage = false)
|
||||
}
|
||||
|
||||
// Latest
|
||||
override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(1)
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val result = json.decodeFromString<PayloadHomeDto>(response.body.string())
|
||||
val mangaList = result.data.new_chapters.map {
|
||||
SManga.create().apply {
|
||||
url = "/series/comic-${it.slug}"
|
||||
title = it.name
|
||||
thumbnail_url = it.cover
|
||||
}
|
||||
}
|
||||
return MangasPage(mangaList, hasNextPage = false)
|
||||
}
|
||||
|
||||
// Details
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val slug = response.request.url
|
||||
.toString()
|
||||
.substringAfter("/series/comic-")
|
||||
.substringBefore("/chapters")
|
||||
val urla = "$apiBaseUrl/api/series/$slug?type=comic"
|
||||
val newRequest = GET(url = urla, headers = headers)
|
||||
val newResponse = client.newCall(newRequest).execute()
|
||||
val result = json.decodeFromString<MangaDetailDto>(newResponse.body.string())
|
||||
return SManga.create().apply {
|
||||
url = "/series/comic-$slug"
|
||||
title = result.data.name
|
||||
thumbnail_url = result.data.cover
|
||||
description = result.data.summary
|
||||
}
|
||||
}
|
||||
override fun imageUrlParse(response: Response): String = throw Exception("Not used")
|
||||
|
||||
// Chapters
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
return paginatedChapterListRequest(
|
||||
manga.url
|
||||
.substringAfter("/series/comic-")
|
||||
.substringBefore("/chapters"),
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
private fun paginatedChapterListRequest(mangaUrl: String, page: Int): Request {
|
||||
return GET(
|
||||
url = "$apiBaseUrl/api/series/$mangaUrl/chapters?page=$page&direction=desc&type=comic",
|
||||
headers = headers,
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val slug = response.request.url
|
||||
.toString()
|
||||
.substringAfter("/series/")
|
||||
.substringBefore("/chapters")
|
||||
var data = json.decodeFromString<PayloadChapterDto>(response.body.string())
|
||||
var resultSize = data.data.size
|
||||
var page = 2
|
||||
while (data.meta.total > resultSize) {
|
||||
val newRequest = paginatedChapterListRequest("$slug", page)
|
||||
val newResponse = client.newCall(newRequest).execute()
|
||||
var newData = json.decodeFromString<PayloadChapterDto>(newResponse.body.string())
|
||||
data.data += newData.data
|
||||
resultSize += newData.data.size
|
||||
page += 1
|
||||
}
|
||||
return data.data.map { chap -> chapterFromObject(chap, slug) }
|
||||
}
|
||||
|
||||
private fun chapterFromObject(chapter: ChapterDto, slug: String) = SChapter.create().apply {
|
||||
url = "/capitulo/${chapter.id}/comic-$slug"
|
||||
name = "Capitulo ${chapter.name}"
|
||||
chapter_number = chapter.name.toFloatOrNull() ?: -1f
|
||||
}
|
||||
// Pages
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
var id = chapter.url
|
||||
.substringAfter("/capitulo/")
|
||||
.substringBefore("/chapters")
|
||||
.substringBefore("/comic")
|
||||
val slug = chapter.url
|
||||
.substringAfter("comic-")
|
||||
.substringBefore("/chapters")
|
||||
.substringBefore("/comic")
|
||||
return GET("$apiBaseUrl/api/series/$slug/chapters/$id?type=comic")
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> =
|
||||
json.decodeFromString<PayloadPagesDto>(response.body.string()).chapter.pages.mapIndexed { i, img ->
|
||||
Page(i, "", img)
|
||||
}
|
||||
|
||||
// Popular
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val result = json.decodeFromString<PayloadHomeDto>(response.body.string())
|
||||
val resultMangaList = json.decodeFromString<List<MangaDto>>(result.data.popular_comics)
|
||||
val mangaList = resultMangaList.map {
|
||||
SManga.create().apply {
|
||||
url = "/series/comic-${it.slug}"
|
||||
title = it.name
|
||||
thumbnail_url = it.cover
|
||||
}
|
||||
}
|
||||
return MangasPage(mangaList, hasNextPage = false)
|
||||
}
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
val apiUrl = "$apiBaseUrl/api/home".toHttpUrl().newBuilder()
|
||||
.build()
|
||||
return GET(apiUrl, headers)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package eu.kanade.tachiyomi.extension.es.olympusscanlation.dto
|
||||
import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
object OlympusScanlationDto {
|
||||
@Serializable
|
||||
data class ChapterDto(val id: Int, val name: String)
|
||||
|
||||
@Serializable
|
||||
data class MangaDto(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val slug: String?,
|
||||
val cover: String?,
|
||||
val type: String?,
|
||||
val summary: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MangaDetailDto(
|
||||
var data: MangaDto,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MetaDto(val total: Int)
|
||||
|
||||
@Serializable
|
||||
data class PageDto(val pages: List<String>)
|
||||
|
||||
@Serializable
|
||||
data class PayloadChapterDto(var data: List<ChapterDto>, val meta: MetaDto)
|
||||
|
||||
@Serializable
|
||||
data class PayloadMangaDto(val data: List<MangaDto>)
|
||||
|
||||
@Serializable
|
||||
data class PayloadPagesDto(val chapter: PageDto)
|
||||
|
||||
@Serializable
|
||||
data class HomeDto(
|
||||
val popular_comics: String,
|
||||
val new_chapters: List<MangaDto>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PayloadHomeDto(
|
||||
val data: HomeDto,
|
||||
)
|
||||
}
|