Remove dead sources (#11554)
* Remove YushukeMangas * Remove WinterSun * Remove XsScan * Remove NazarickScan * Remove LimitedTimeProject * Remove InfinyxScan * Remove DianxiaTraducoes * Remove MangaOnline * Remove LichMangas * Remove LerHentai * Remove Bruttal * Remove ArgosHentai
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Argos Hentai'
|
||||
extClass = '.ArgosHentai'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://argoshentai.xyz'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
@ -1,17 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.argoshentai
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class ArgosHentai : Madara(
|
||||
"Argos Hentai",
|
||||
"https://argoshentai.xyz",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("MMMMM dd, yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
override val client = super.client.newBuilder()
|
||||
.rateLimit(3)
|
||||
.build()
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
ext {
|
||||
extName = 'Bruttal'
|
||||
extClass = '.Bruttal'
|
||||
extVersionCode = 7
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@ -1,191 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.bruttal
|
||||
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
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 kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class Bruttal : HttpSource() {
|
||||
|
||||
override val name = "Bruttal"
|
||||
|
||||
override val baseUrl = BRUTTAL_URL
|
||||
|
||||
override val lang = "pt-BR"
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||
.rateLimit(1, 2, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
||||
.add("Referer", "$baseUrl/bruttal/")
|
||||
.add("User-Agent", USER_AGENT)
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept", "application/json, text/plain, */*")
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl/data/home.json", newHeaders)
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val titles = response.parseAs<BruttalHomeDto>().list
|
||||
.map(BruttalComicBookDto::toSManga)
|
||||
|
||||
return MangasPage(titles, false)
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept", "application/json, text/plain, */*")
|
||||
.build()
|
||||
|
||||
val jsonUrl = "$baseUrl/data/home.json".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("q", query)
|
||||
.toString()
|
||||
|
||||
return GET(jsonUrl, newHeaders)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val query = response.request.url.queryParameter("q").orEmpty()
|
||||
|
||||
var titles = response.parseAs<BruttalHomeDto>().list
|
||||
.map(BruttalComicBookDto::toSManga)
|
||||
|
||||
if (query.isNotEmpty()) {
|
||||
titles = titles.filter { it.title.contains(query, ignoreCase = true) }
|
||||
}
|
||||
|
||||
return MangasPage(titles, false)
|
||||
}
|
||||
|
||||
// Workaround to allow "Open in browser" use the real URL.
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||
return client.newCall(mangaDetailsApiRequest(manga))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
mangaDetailsParse(response).apply { initialized = true }
|
||||
}
|
||||
}
|
||||
|
||||
private fun mangaDetailsApiRequest(manga: SManga): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept", "application/json, text/plain, */*")
|
||||
.set("Referer", baseUrl + manga.url)
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl/data/comicbooks.json", newHeaders)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val comicBookUrl = response.request.header("Referer")!!
|
||||
.substringAfter("/bruttal")
|
||||
|
||||
return response.parseAs<List<BruttalComicBookDto>>()
|
||||
.first { it.url == comicBookUrl }
|
||||
.toSManga()
|
||||
}
|
||||
|
||||
// Chapters are available in the same url of the manga details.
|
||||
override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga)
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val comicBooks = response.parseAs<List<BruttalComicBookDto>>()
|
||||
|
||||
val comicBookUrl = response.request.header("Referer")!!
|
||||
.substringAfter("/bruttal")
|
||||
val currentComicBook = comicBooks.first { it.url == comicBookUrl }
|
||||
|
||||
return currentComicBook.seasons
|
||||
.flatMap(BruttalSeasonDto::chapters)
|
||||
.map(BruttalChapterDto::toSChapter)
|
||||
.reversed()
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept", "application/json, text/plain, */*")
|
||||
.set("Referer", baseUrl + chapter.url)
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl/data/comicbooks.json", newHeaders)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val comicBooks = response.parseAs<List<BruttalComicBookDto>>()
|
||||
|
||||
val chapterUrl = response.request.header("Referer")!!
|
||||
val comicBookSlug = chapterUrl
|
||||
.substringAfter("bruttal/")
|
||||
.substringBefore("/")
|
||||
val seasonNumber = chapterUrl
|
||||
.substringAfter("temporada-")
|
||||
.substringBefore("/")
|
||||
val chapterNumber = chapterUrl.substringAfter("capitulo-")
|
||||
|
||||
val currentComicBook = comicBooks.first { it.url == "/$comicBookSlug" }
|
||||
val currentSeason = currentComicBook.seasons.first {
|
||||
it.alias.substringAfter("-") == seasonNumber
|
||||
}
|
||||
val currentChapter = currentSeason.chapters.first {
|
||||
it.alias.substringAfter("-") == chapterNumber
|
||||
}
|
||||
|
||||
return currentChapter.images
|
||||
.mapIndexed { i, imageDto ->
|
||||
val imageUrl = "$baseUrl/${imageDto.image.removePrefix("./")}"
|
||||
Page(i, chapterUrl, imageUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
|
||||
|
||||
override fun imageUrlParse(response: Response): String = ""
|
||||
|
||||
override fun imageRequest(page: Page): Request {
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept", "image/avif,image/webp,image/apng,image/*,*/*;q=0.8")
|
||||
.set("Referer", page.url)
|
||||
.build()
|
||||
|
||||
return GET(page.imageUrl!!, newHeaders)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request =
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage =
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
private inline fun <reified T> Response.parseAs(): T = use {
|
||||
json.decodeFromString(body.string())
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val BRUTTAL_URL = "https://originals.omelete.com.br/bruttal"
|
||||
|
||||
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.bruttal
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BruttalHomeDto(
|
||||
val list: List<BruttalComicBookDto> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class BruttalComicBookDto(
|
||||
val author: String,
|
||||
val illustrator: String,
|
||||
@SerialName("image_mobile") val imageMobile: String,
|
||||
val keywords: String,
|
||||
val seasons: List<BruttalSeasonDto> = emptyList(),
|
||||
@SerialName("soon_text") val soonText: String = "",
|
||||
val synopsis: String,
|
||||
val title: String,
|
||||
val url: String,
|
||||
) {
|
||||
|
||||
fun toSManga(): SManga = SManga.create().apply {
|
||||
title = this@BruttalComicBookDto.title
|
||||
description = synopsis + (if (soonText.isEmpty()) "" else "\n\n$soonText")
|
||||
artist = illustrator
|
||||
author = this@BruttalComicBookDto.author
|
||||
genre = keywords.split(";")
|
||||
.map { keyword -> keyword.trim().replaceFirstChar { it.uppercase() } }
|
||||
.sorted()
|
||||
.joinToString()
|
||||
status = SManga.ONGOING
|
||||
thumbnail_url = "${Bruttal.BRUTTAL_URL}/" + imageMobile.removePrefix("./")
|
||||
url = this@BruttalComicBookDto.url
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class BruttalSeasonDto(
|
||||
val alias: String,
|
||||
val chapters: List<BruttalChapterDto> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class BruttalChapterDto(
|
||||
val alias: String,
|
||||
val images: List<BruttalImageDto> = emptyList(),
|
||||
@SerialName("share_title") val shareTitle: String,
|
||||
val title: String,
|
||||
val url: String,
|
||||
) {
|
||||
|
||||
fun toSChapter(): SChapter = SChapter.create().apply {
|
||||
name = title
|
||||
chapter_number = shareTitle
|
||||
.removePrefix("Capítulo ")
|
||||
.toFloatOrNull() ?: -1f
|
||||
url = this@BruttalChapterDto.url
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class BruttalImageDto(
|
||||
val image: String,
|
||||
)
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Dianxia Traduções'
|
||||
extClass = '.DianxiaTraducoes'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://dianxiatrads.com'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 48 KiB |
@ -1,15 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.dianxiatraducoes
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class DianxiaTraducoes : Madara(
|
||||
"Dianxia Traduções",
|
||||
"https://dianxiatrads.com",
|
||||
"pt-BR",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT),
|
||||
) {
|
||||
override val useLoadMoreRequest = LoadMoreStrategy.Never
|
||||
override val useNewChapterEndpoint = false
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'InfinyxScan'
|
||||
extClass = '.InfinyxScan'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://infinyxscan.cloud'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 23 KiB |
@ -1,14 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.infinyxscan
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class InfinyxScan : Madara(
|
||||
"InfinyxScan",
|
||||
"https://infinyxscan.cloud",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
override val useNewChapterEndpoint: Boolean = true
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Ler Hentai'
|
||||
extClass = '.LerHentai'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://lerhentai.com'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 39 KiB |
@ -1,23 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.lerhentai
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import org.jsoup.nodes.Document
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class LerHentai : Madara(
|
||||
"Ler Hentai",
|
||||
"https://lerhentai.com",
|
||||
"pt-BR",
|
||||
dateFormat = SimpleDateFormat("d 'de' MMMM 'de' yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
override val useLoadMoreRequest = LoadMoreStrategy.Never
|
||||
override val useNewChapterEndpoint = false
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
return super.mangaDetailsParse(document).apply {
|
||||
description = description?.removePrefix("Sinopse\n\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Lich Mangas'
|
||||
extClass = '.LichMangas'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://lichmangas.com'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 49 KiB |
@ -1,14 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.lichmangas
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class LichMangas : Madara(
|
||||
"Lich Mangas",
|
||||
"https://lichmangas.com",
|
||||
"pt-BR",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT),
|
||||
) {
|
||||
override val useNewChapterEndpoint = true
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Limited Time Project'
|
||||
extClass = '.LimitedTimeProject'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://limitedtimeproject.com'
|
||||
overrideVersionCode = 1
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 42 KiB |
@ -1,23 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.limitedtimeproject
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class LimitedTimeProject : Madara(
|
||||
"Limited Time Project",
|
||||
"https://limitedtimeproject.com",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("dd/MM/yyyy", Locale.ROOT),
|
||||
) {
|
||||
override val client = super.client.newBuilder()
|
||||
.rateLimit(3)
|
||||
.build()
|
||||
|
||||
override val mangaSubString = "manhwas"
|
||||
|
||||
override val useLoadMoreRequest = LoadMoreStrategy.Never
|
||||
|
||||
override val useNewChapterEndpoint = true
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
ext {
|
||||
extName = 'Manga Online'
|
||||
extClass = '.MangaOnline'
|
||||
extVersionCode = 3
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation(project(':lib:randomua'))
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@ -1,201 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.mangaonline
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.lib.randomua.addRandomUAPreferenceToScreen
|
||||
import eu.kanade.tachiyomi.lib.randomua.getPrefCustomUA
|
||||
import eu.kanade.tachiyomi.lib.randomua.getPrefUAType
|
||||
import eu.kanade.tachiyomi.lib.randomua.setRandomUserAgent
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
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.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import keiyoushi.utils.getPreferences
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class MangaOnline : ParsedHttpSource(), ConfigurableSource {
|
||||
override val lang = "pt-BR"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override val name = "Manga Online"
|
||||
|
||||
override val baseUrl = "https://mangaonline.biz"
|
||||
|
||||
private var genresSet: Set<Genre> = emptySet()
|
||||
|
||||
private val preferences: SharedPreferences = getPreferences()
|
||||
|
||||
override val client: OkHttpClient =
|
||||
network.cloudflareClient.newBuilder()
|
||||
.setRandomUserAgent(
|
||||
preferences.getPrefUAType(),
|
||||
preferences.getPrefCustomUA(),
|
||||
)
|
||||
.rateLimitHost(baseUrl.toHttpUrl(), 1, 2, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
addRandomUAPreferenceToScreen(screen)
|
||||
}
|
||||
|
||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||
name = element.selectFirst("a")!!.ownText()
|
||||
date_upload = element.selectFirst("a span.date")?.ownText()!!.toDate()
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href"))
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = "div.episodiotitle"
|
||||
|
||||
override fun imageUrlParse(document: Document) = ""
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
||||
title = element.selectFirst("h3 a")!!.ownText()
|
||||
.replace("Capítulo\\s+([\\d.]+)".toRegex(), "")
|
||||
.trim()
|
||||
|
||||
thumbnail_url = element.selectFirst("img")?.absUrl("src")
|
||||
|
||||
val mangaUrl = element.selectFirst("h3 a")!!.absUrl("href")
|
||||
.replace("-capitulo-[\\d-]+".toRegex(), "")
|
||||
.replace("capitulo", "manga")
|
||||
|
||||
setUrlWithoutDomain(mangaUrl)
|
||||
}
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = null
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/capitulo/page/$page", headers)
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val mangesPage = super.latestUpdatesParse(response)
|
||||
|
||||
return MangasPage(
|
||||
mangesPage.mangas.distinctBy { it.title },
|
||||
mangesPage.hasNextPage,
|
||||
)
|
||||
}
|
||||
|
||||
override fun latestUpdatesSelector() = popularMangaSelector()
|
||||
|
||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
||||
val containerInfo = document.selectFirst("div.content > div.sheader")
|
||||
title = containerInfo!!.selectFirst("h1")!!.ownText()
|
||||
thumbnail_url = containerInfo.selectFirst("img")?.absUrl("src")
|
||||
description = containerInfo.selectFirst("p:last-child")?.ownText()
|
||||
genre = containerInfo.select("div.sgeneros a")
|
||||
.map { it.ownText() }
|
||||
.filter { it.length > 1 }
|
||||
.joinToString()
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
return document.select("img[loading=lazy]").mapIndexed { i, it ->
|
||||
Page(i, imageUrl = it.absUrl("src"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||
title = element.selectFirst("h3 a")!!.ownText()
|
||||
thumbnail_url = element.selectFirst("img")?.absUrl("src")
|
||||
setUrlWithoutDomain(element.selectFirst("h3 a")!!.absUrl("href"))
|
||||
}
|
||||
|
||||
override fun popularMangaNextPageSelector() = null
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/mais-vistos/", headers)
|
||||
|
||||
override fun popularMangaSelector() = "div.content .item"
|
||||
|
||||
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
|
||||
|
||||
override fun searchMangaNextPageSelector() = ".pagination > .current + a"
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (query.isNotBlank()) {
|
||||
val url = "$baseUrl/search".toHttpUrl().newBuilder()
|
||||
.addPathSegment(query)
|
||||
.build()
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
val path = when (val genre = (filters.first() as GenreList).selected) {
|
||||
Genre.GLOBAL -> "$baseUrl/${genre.id}"
|
||||
else -> "$baseUrl/genero/${genre.id}"
|
||||
}
|
||||
|
||||
return GET("$path/page/$page", headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
|
||||
override fun getFilterList(): FilterList {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
fetchMangaGenre()
|
||||
}
|
||||
|
||||
genresSet += Genre.GLOBAL
|
||||
|
||||
return FilterList(
|
||||
GenreList(
|
||||
title = "Gêneros",
|
||||
genres = genresSet.toTypedArray(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun fetchMangaGenre() {
|
||||
try {
|
||||
val request = client
|
||||
.newCall(GET("$baseUrl/generos/", headers))
|
||||
.execute()
|
||||
|
||||
val document = request.asJsoup()
|
||||
|
||||
genresSet = document.select(".wp-content a").map { element ->
|
||||
val id = element.absUrl("href")
|
||||
.split("/")
|
||||
.last { it.isNotEmpty() }
|
||||
Genre(element.ownText(), id)
|
||||
}.toSet()
|
||||
} catch (e: Exception) {
|
||||
Log.e("MangaOnline", e.stackTraceToString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.toDate() =
|
||||
try { dateFormat.parse(trim())!!.time } catch (_: Exception) { 0L }
|
||||
|
||||
private val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR"))
|
||||
}
|
||||
|
||||
data class Genre(val name: String, val id: String) {
|
||||
override fun toString() = name
|
||||
|
||||
companion object {
|
||||
val GLOBAL = Genre("Todos", "manga")
|
||||
}
|
||||
}
|
||||
|
||||
class GenreList(title: String, private val genres: Array<Genre>) : Filter.Select<Genre>(title, genres) {
|
||||
val selected get() = genres[state]
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Nazarick Scan'
|
||||
extClass = '.NazarickScan'
|
||||
themePkg = 'peachscan'
|
||||
baseUrl = 'https://nazarickscan.com.br'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 38 KiB |
@ -1,5 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.nazarickscan
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.peachscan.PeachScan
|
||||
|
||||
class NazarickScan : PeachScan("Nazarick Scan", "https://nazarickscan.com.br", "pt-BR")
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Winter Sun'
|
||||
extClass = '.WinterSun'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://wintersunscan.xyz'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@ -1,14 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.wintersun
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class WinterSun : Madara(
|
||||
"Winter Sun",
|
||||
"https://wintersunscan.xyz",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("dd 'de' MMMMM 'de' yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
override val useNewChapterEndpoint = true
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Xs Scan'
|
||||
extClass = '.XsScan'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://xsscan.xyz'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 19 KiB |
@ -1,19 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.xsscan
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class XsScan : Madara(
|
||||
"Xs Scan",
|
||||
"https://xsscan.xyz",
|
||||
"pt-BR",
|
||||
SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR")),
|
||||
) {
|
||||
override val client = super.client.newBuilder()
|
||||
.rateLimit(3)
|
||||
.build()
|
||||
|
||||
override val useNewChapterEndpoint = true
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Yushuke Mangas'
|
||||
extClass = '.YushukeMangas'
|
||||
themePkg = 'yuyu'
|
||||
baseUrl = 'https://new.yushukemangas.com'
|
||||
overrideVersionCode = 7
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 34 KiB |
@ -1,25 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.yushukemangas
|
||||
|
||||
import eu.kanade.tachiyomi.extension.pt.yushukemangas.YushukeMangas.Companion.dateFormat
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import keiyoushi.utils.tryParse
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class ChapterDto(
|
||||
val id: Int,
|
||||
@SerialName("numero")
|
||||
val number: Float,
|
||||
@SerialName("titulo")
|
||||
val name: String,
|
||||
@SerialName("data_publicacao")
|
||||
val date: String,
|
||||
) {
|
||||
fun toSChapter(chapterUrl: String) = SChapter.create().apply {
|
||||
name = this@ChapterDto.name
|
||||
chapter_number = number
|
||||
date_upload = dateFormat.tryParse(date)
|
||||
url = "$chapterUrl/capitulo/$id"
|
||||
}
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.pt.yushukemangas
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.yuyu.YuYu
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import keiyoushi.utils.parseAs
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class YushukeMangas : YuYu(
|
||||
"Yushuke Mangas",
|
||||
"https://new.yushukemangas.com",
|
||||
"pt-BR",
|
||||
) {
|
||||
|
||||
override val client = super.client.newBuilder()
|
||||
.rateLimit(2)
|
||||
.build()
|
||||
|
||||
override val versionId = 2
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
if (document.location().contains(MANGA_URL_ID_REGEX).not()) {
|
||||
return super.mangaDetailsParse(document)
|
||||
}
|
||||
|
||||
return SManga.create().apply {
|
||||
title = document.selectFirst("h1")!!.text()
|
||||
thumbnail_url = document.selectFirst(".detalhe-capa-img")?.absUrl("src")
|
||||
genre = document.select(".detalhe-tags-chips span").joinToString { it.text() }
|
||||
description = document.selectFirst(".detalhe-sinopse")?.text()
|
||||
document.selectFirst(".detalhe-chip.status")?.ownText()?.let {
|
||||
status = it.toStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMangaId(manga: SManga): String {
|
||||
return when {
|
||||
manga.isOldEntry() -> super.getMangaId(manga)
|
||||
else -> MANGA_URL_ID_REGEX.find(manga.url)?.groups?.get(1)?.value ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun SManga.isOldEntry(): Boolean = MANGA_URL_ID_REGEX.containsMatchIn(url).not()
|
||||
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||
if (manga.isOldEntry()) {
|
||||
return super.fetchChapterList(manga)
|
||||
}
|
||||
|
||||
val mangaId = getMangaId(manga).takeIf(String::isNotBlank)
|
||||
?: throw Exception("Manga ID não encontrado")
|
||||
|
||||
val chapters = mutableListOf<SChapter>()
|
||||
var page = 1
|
||||
val url = manga.url.replace("/$mangaId", "")
|
||||
do {
|
||||
val chaptersDto = fetchChapterListPage(mangaId, page++).parseAs<ChaptersDto<List<ChapterDto>>>()
|
||||
chapters += chaptersDto.chapters.map { it.toSChapter(url) }
|
||||
} while (chaptersDto.hasNext())
|
||||
|
||||
return Observable.just(chapters)
|
||||
}
|
||||
|
||||
private fun fetchChapterListPage(mangaId: String, page: Int): Response {
|
||||
val url = "$baseUrl/ajax/get_chapters.php".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("manga_id", mangaId)
|
||||
.addQueryParameter("page", page.toString())
|
||||
.build()
|
||||
|
||||
return client
|
||||
.newCall(GET(url, headers))
|
||||
.execute()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)
|
||||
private val MANGA_URL_ID_REGEX = """\/obra\/(\d+)\/.+$""".toRegex()
|
||||
}
|
||||
}
|
||||