diff --git a/src/pt/hqdragon/AndroidManifest.xml b/src/pt/hqdragon/AndroidManifest.xml deleted file mode 100644 index 30deb7f79..000000000 --- a/src/pt/hqdragon/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/pt/hqdragon/build.gradle b/src/pt/hqdragon/build.gradle deleted file mode 100644 index 8eb08a8e7..000000000 --- a/src/pt/hqdragon/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'HQ Dragon' - pkgNameSuffix = 'pt.hqdragon' - extClass = '.HQDragon' - extVersionCode = 4 - libVersion = '1.2' -} - -dependencies { - implementation project(':lib-ratelimit') -} - -apply from: "$rootDir/common.gradle" diff --git a/src/pt/hqdragon/res/mipmap-hdpi/ic_launcher.png b/src/pt/hqdragon/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 7c21d8b91..000000000 Binary files a/src/pt/hqdragon/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/hqdragon/res/mipmap-mdpi/ic_launcher.png b/src/pt/hqdragon/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 04df4fb73..000000000 Binary files a/src/pt/hqdragon/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/hqdragon/res/mipmap-xhdpi/ic_launcher.png b/src/pt/hqdragon/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 2d51d19fa..000000000 Binary files a/src/pt/hqdragon/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/hqdragon/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/hqdragon/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index de7b1a1cf..000000000 Binary files a/src/pt/hqdragon/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/hqdragon/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/hqdragon/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 5ea6265cd..000000000 Binary files a/src/pt/hqdragon/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/hqdragon/res/web_hi_res_512.png b/src/pt/hqdragon/res/web_hi_res_512.png deleted file mode 100644 index 3992c579d..000000000 Binary files a/src/pt/hqdragon/res/web_hi_res_512.png and /dev/null differ diff --git a/src/pt/hqdragon/src/eu/kanade/tachiyomi/extension/pt/hqdragon/HQDragon.kt b/src/pt/hqdragon/src/eu/kanade/tachiyomi/extension/pt/hqdragon/HQDragon.kt deleted file mode 100644 index 5bf24977b..000000000 --- a/src/pt/hqdragon/src/eu/kanade/tachiyomi/extension/pt/hqdragon/HQDragon.kt +++ /dev/null @@ -1,206 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.hqdragon - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -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 okhttp3.FormBody -import okhttp3.Headers -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import rx.Observable -import java.util.concurrent.TimeUnit - -class HQDragon : ParsedHttpSource() { - - override val name = "HQ Dragon" - - override val baseUrl = "https://hqdragon.com" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS)) - .build() - - override fun headersBuilder(): Headers.Builder = Headers.Builder() - .add("Accept", ACCEPT) - .add("Accept-Language", ACCEPT_LANGUAGE) - .add("Referer", "$baseUrl/") - - // Popular - - // Top 10 - override fun popularMangaRequest(page: Int): Request { - return GET(baseUrl, headers) - } - - override fun popularMangaParse(response: Response): MangasPage { - val results = super.popularMangaParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun popularMangaSelector() = "h4:contains(Top 10) + ol.mb-0 li a" - - override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply { - title = element.text() - setUrlWithoutDomain(element.attr("href")) - } - - override fun popularMangaNextPageSelector(): String? = null - - // Latest - - override fun fetchLatestUpdates(page: Int): Observable { - return super.fetchLatestUpdates(page) - .map { results -> results.copy(hasNextPage = page < 5) } - } - - override fun latestUpdatesRequest(page: Int): Request { - val formBody = FormBody.Builder() - .add("pagina", page.toString()) - .build() - - val headers = headersBuilder() - .add("Content-Length", formBody.contentLength().toString()) - .add("Content-Type", formBody.contentType().toString()) - .add("Origin", baseUrl) - .add("X-Requested-With", "XMLHttpRequest") - .set("Accept", "*/*") - .build() - - return POST("$baseUrl/assets/php/index_paginar.php", headers, formBody) - } - - override fun latestUpdatesParse(response: Response): MangasPage { - val results = super.latestUpdatesParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun latestUpdatesSelector() = "a:has(img)" - - override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply { - val image = element.select("img").first() - - title = image.attr("alt") - thumbnail_url = image.attr("abs:src") - setUrlWithoutDomain(element.attr("href")) - } - - override fun latestUpdatesNextPageSelector(): String? = null - - // Search - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = "$baseUrl/pesquisa".toHttpUrlOrNull()!!.newBuilder() - .addQueryParameter("titulo", query) - - return GET(url.toString(), headers) - } - - override fun searchMangaParse(response: Response): MangasPage { - val results = super.searchMangaParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun searchMangaSelector() = "div.col-sm-6.col-md-3:has(img.img-thumbnail)" - - override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply { - val link = element.select("a + a").first() - - title = link.text() - thumbnail_url = element.select("img").first().attr("abs:src") - setUrlWithoutDomain(link.attr("href")) - } - - override fun searchMangaNextPageSelector(): String? = null - - // Manga summary page - - override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { - val infoElement = document.select("div.blog-post div.row").firstOrNull() - ?: throw Exception(BLOCK_MESSAGE) - - title = infoElement.select("h3").first().text() - author = infoElement.select("p:contains(Editora:)").first().textWithoutLabel() - status = infoElement.select("p:contains(Status:) span").first().text().toStatus() - description = infoElement.select("p:contains(Sinopse:)").first().ownText() - thumbnail_url = infoElement.select("div.col-md-4 .img-fluid").first().attr("src") - } - - // Chapters - - override fun chapterListSelector() = "table.table tr a" - - override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { - name = element.text().replace("Ler ", "") - setUrlWithoutDomain(element.attr("href")) - } - - // Pages - - override fun pageListParse(document: Document): List { - return document.select("img.img-responsive.img-manga") - .filter { it.attr("src").contains("/leitor/") } - .mapIndexed { i, element -> - Page(i, document.location(), element.absUrl("src")) - } - } - - override fun imageUrlParse(document: Document) = "" - - override fun imageRequest(page: Page): Request { - val newHeaders = headersBuilder() - .set("Accept", ACCEPT_IMAGE) - .set("Referer", page.url) - .build() - - return GET(page.imageUrl!!, newHeaders) - } - - private fun Element.textWithoutLabel(): String = text()!!.substringAfter(":").trim() - - private fun String.toStatus(): Int = when { - contains("Ativo") -> SManga.ONGOING - contains("Completo") -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - - companion object { - private const val ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," + - "image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" - private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" - private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5" - private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36" - - private const val BLOCK_MESSAGE = "O site está bloqueando o Tachiyomi. " + - "Migre para outra fonte caso o problema persistir." - } -} diff --git a/src/pt/mangahost/AndroidManifest.xml b/src/pt/mangahost/AndroidManifest.xml deleted file mode 100644 index 30deb7f79..000000000 --- a/src/pt/mangahost/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/pt/mangahost/build.gradle b/src/pt/mangahost/build.gradle deleted file mode 100644 index 944d148d4..000000000 --- a/src/pt/mangahost/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'Mangá Host' - pkgNameSuffix = 'pt.mangahost' - extClass = '.MangaHost' - extVersionCode = 24 - libVersion = '1.2' -} - -dependencies { - implementation project(':lib-ratelimit') -} - -apply from: "$rootDir/common.gradle" diff --git a/src/pt/mangahost/res/mipmap-hdpi/ic_launcher.png b/src/pt/mangahost/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index eaf86b0f2..000000000 Binary files a/src/pt/mangahost/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/mangahost/res/mipmap-mdpi/ic_launcher.png b/src/pt/mangahost/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index dfcf87577..000000000 Binary files a/src/pt/mangahost/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/mangahost/res/mipmap-xhdpi/ic_launcher.png b/src/pt/mangahost/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index b2b7a89ea..000000000 Binary files a/src/pt/mangahost/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/mangahost/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/mangahost/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index a220903e1..000000000 Binary files a/src/pt/mangahost/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/mangahost/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/mangahost/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 70558e895..000000000 Binary files a/src/pt/mangahost/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/mangahost/res/web_hi_res_512.png b/src/pt/mangahost/res/web_hi_res_512.png deleted file mode 100644 index e7a9e90e3..000000000 Binary files a/src/pt/mangahost/res/web_hi_res_512.png and /dev/null differ diff --git a/src/pt/mangahost/src/eu/kanade/tachiyomi/extension/pt/mangahost/MangaHost.kt b/src/pt/mangahost/src/eu/kanade/tachiyomi/extension/pt/mangahost/MangaHost.kt deleted file mode 100644 index eee79f0e8..000000000 --- a/src/pt/mangahost/src/eu/kanade/tachiyomi/extension/pt/mangahost/MangaHost.kt +++ /dev/null @@ -1,288 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.mangahost - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.asObservable -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 okhttp3.Call -import okhttp3.Headers -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import org.jsoup.select.Elements -import rx.Observable -import java.text.ParseException -import java.text.SimpleDateFormat -import java.util.Locale -import java.util.concurrent.TimeUnit - -class MangaHost : ParsedHttpSource() { - - // Hardcode the id because the name was wrong and the language wasn't specific. - override val id: Long = 3926812845500643354 - - override val name = "Mangá Host" - - override val baseUrl = "https://mangahostz.com" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .addInterceptor(RateLimitInterceptor(1, 3, TimeUnit.SECONDS)) - .addInterceptor(::blockMessageIntercept) - .build() - - override fun headersBuilder(): Headers.Builder = Headers.Builder() - .add("Accept", ACCEPT) - .add("Accept-Language", ACCEPT_LANGUAGE) - .add("Referer", baseUrl) - .add("User-Agent", USER_AGENT) - - private fun genericMangaFromElement(element: Element): SManga = SManga.create().apply { - val thumbnailEl = element.select("img") - val thumbnailAttr = if (thumbnailEl.hasAttr("data-path")) "data-path" else "src" - - title = element.attr("title").withoutLanguage() - thumbnail_url = thumbnailEl.attr(thumbnailAttr).toLargeUrl() - setUrlWithoutDomain(element.attr("href")) - } - - override fun popularMangaRequest(page: Int): Request { - val listPath = if (page == 1) "" else "/mais-visualizados/page/${page - 1}" - val newHeaders = headersBuilder() - .set("Referer", "$baseUrl/mangas$listPath") - .build() - - val pageStr = if (page != 1) "/page/$page" else "" - return GET("$baseUrl/mangas/mais-visualizados$pageStr", newHeaders) - } - - override fun popularMangaParse(response: Response): MangasPage { - val results = super.popularMangaParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun popularMangaSelector(): String = "div#dados div.manga-block div.manga-block-left a" - - override fun popularMangaFromElement(element: Element): SManga = genericMangaFromElement(element) - - override fun popularMangaNextPageSelector() = "div.wp-pagenavi:has(a.nextpostslink)" - - override fun latestUpdatesRequest(page: Int): Request { - val listPath = if (page == 1) "" else "/lancamentos/page/${page - 1}" - val newHeaders = headersBuilder() - .set("Referer", baseUrl + listPath) - .build() - - val pageStr = if (page != 1) "/page/$page" else "" - return GET("$baseUrl/lancamentos$pageStr", newHeaders) - } - - override fun latestUpdatesParse(response: Response): MangasPage { - val results = super.latestUpdatesParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun latestUpdatesSelector() = "div#dados div.w-row div.column-img a" - - override fun latestUpdatesFromElement(element: Element): SManga = genericMangaFromElement(element) - - override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = "$baseUrl/find".toHttpUrlOrNull()!!.newBuilder() - .addQueryParameter("this", query) - - return GET(url.toString(), headers) - } - - override fun searchMangaSelector() = "table.table-search > tbody > tr > td:eq(0) > a" - - override fun searchMangaFromElement(element: Element): SManga = genericMangaFromElement(element) - - override fun searchMangaNextPageSelector(): String? = null - - /** - * The site wrongly return 404 for some titles, even if they are present. - * In those cases, the extension will parse the response normally. - */ - override fun fetchMangaDetails(manga: SManga): Observable { - return client.newCall(mangaDetailsRequest(manga)) - .asObservableIgnoreCode(404) - .map { response -> - mangaDetailsParse(response).apply { initialized = true } - } - } - - override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { - val infoElement = document.select("div.box-content div.w-row div.w-col:eq(1) article") - .firstOrNull() ?: throw Exception(BLOCK_MESSAGE) - - author = infoElement.select("div.text li div:contains(Autor:)").textWithoutLabel() - artist = infoElement.select("div.text li div:contains(Arte:)").textWithoutLabel() - genre = infoElement.select("h3.subtitle + div.tags a").joinToString { it.text() } - description = infoElement.select("div.text div.paragraph").first()?.text() - ?.substringBefore("Relacionados:") - status = infoElement.select("div.text li div:contains(Status:)").text().toStatus() - thumbnail_url = document.select("div.box-content div.w-row div.w-col:eq(0) div.widget img") - .attr("src") - } - - /** - * The site wrongly return 404 for some titles, even if they are present. - * In those cases, the extension will parse the response normally. - */ - override fun fetchChapterList(manga: SManga): Observable> { - return if (manga.status != SManga.LICENSED) { - client.newCall(chapterListRequest(manga)) - .asObservableIgnoreCode(404) - .map(::chapterListParse) - } else { - Observable.error(Exception("Licensed - No chapters to show")) - } - } - - override fun chapterListParse(response: Response): List { - val chapters = super.chapterListParse(response) - - if (chapters.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return chapters - } - - override fun chapterListSelector(): String = - "article section.clearfix div.chapters div.cap div.card.pop" - - override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { - name = element.select("div.pop-title").text().withoutLanguage() - scanlator = element.select("div.pop-content small strong").text() - date_upload = element.select("small.clearfix").text() - .substringAfter("Adicionado em ") - .toDate() - chapter_number = element.select("div.pop-title span.btn-caps").text() - .toFloatOrNull() ?: 1f - setUrlWithoutDomain(element.select("div.tags a").attr("href")) - - if (scanlator!!.split("/").count() >= 5) { - val scanlators = scanlator!!.split("/") - scanlator = scanlators[0] + " e mais " + (scanlators.count() - 1) - } - } - - /** - * The site wrongly return 404 for some chapters, even if they are present. - * In those cases, the extension will parse the response normally. - */ - override fun fetchPageList(chapter: SChapter): Observable> { - return client.newCall(pageListRequest(chapter)) - .asObservableIgnoreCode(404) - .map(::pageListParse) - } - - override fun pageListRequest(chapter: SChapter): Request { - // Just to prevent the detection of the crawler. - val newHeader = headersBuilder() - .set("Referer", "$baseUrl${chapter.url}".substringBeforeLast("/")) - .build() - - return GET(baseUrl + chapter.url, newHeader) - } - - override fun pageListParse(document: Document): List { - return document.select("div#slider a img") - .mapIndexed { i, el -> Page(i, document.location(), el.attr("src")) } - } - - override fun imageUrlParse(document: Document) = "" - - override fun imageRequest(page: Page): Request { - val newHeaders = headersBuilder() - .set("Accept", ACCEPT_IMAGE) - .set("Referer", "$baseUrl/") - .build() - - return GET(page.imageUrl!!, newHeaders) - } - - private fun blockMessageIntercept(chain: Interceptor.Chain): Response { - val response = chain.proceed(chain.request()) - - if (response.code == 403 || response.code == 1020) { - response.close() - throw Exception(BLOCK_MESSAGE) - } - - return response - } - - private fun Call.asObservableIgnoreCode(code: Int): Observable { - return asObservable().doOnNext { response -> - if (!response.isSuccessful && response.code != code) { - response.close() - throw Exception("HTTP error ${response.code}") - } - } - } - - private fun String.toDate(): Long { - return try { - DATE_FORMAT.parse(this)?.time ?: 0L - } catch (e: ParseException) { - 0L - } - } - - private fun String.toStatus() = when (this) { - "Ativo" -> SManga.ONGOING - "Completo" -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - - private fun String.withoutLanguage(): String = replace(LANG_REGEX, "") - - private fun String.toLargeUrl(): String = replace(IMAGE_REGEX, "_full.") - - private fun Elements.textWithoutLabel(): String = text()!!.substringAfter(":").trim() - - companion object { - private const val ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," + - "image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" - private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" - private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5" - private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36" - - private val LANG_REGEX = "( )?\\((PT-)?BR\\)".toRegex() - private val IMAGE_REGEX = "_(small|medium|xmedium)\\.".toRegex() - - private const val BLOCK_MESSAGE = "O site está bloqueando o Tachiyomi. " + - "Migre para outra fonte caso o problema persistir." - - private val DATE_FORMAT by lazy { - SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH) - } - } -} diff --git a/src/pt/unionmangas/AndroidManifest.xml b/src/pt/unionmangas/AndroidManifest.xml deleted file mode 100644 index f7d3a86a3..000000000 --- a/src/pt/unionmangas/AndroidManifest.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/pt/unionmangas/build.gradle b/src/pt/unionmangas/build.gradle deleted file mode 100644 index 29edc5641..000000000 --- a/src/pt/unionmangas/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'Union Mangás' - pkgNameSuffix = 'pt.unionmangas' - extClass = '.UnionMangas' - extVersionCode = 22 - libVersion = '1.2' -} - -dependencies { - implementation project(':lib-ratelimit') -} - -apply from: "$rootDir/common.gradle" diff --git a/src/pt/unionmangas/res/mipmap-hdpi/ic_launcher.png b/src/pt/unionmangas/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 1b71ad135..000000000 Binary files a/src/pt/unionmangas/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/unionmangas/res/mipmap-mdpi/ic_launcher.png b/src/pt/unionmangas/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 5f08eb5c0..000000000 Binary files a/src/pt/unionmangas/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/unionmangas/res/mipmap-xhdpi/ic_launcher.png b/src/pt/unionmangas/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index f70961fd0..000000000 Binary files a/src/pt/unionmangas/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/unionmangas/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/unionmangas/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index ff725b3a3..000000000 Binary files a/src/pt/unionmangas/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/unionmangas/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/unionmangas/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index e4f74dade..000000000 Binary files a/src/pt/unionmangas/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/unionmangas/res/web_hi_res_512.png b/src/pt/unionmangas/res/web_hi_res_512.png deleted file mode 100644 index fe53ed3ad..000000000 Binary files a/src/pt/unionmangas/res/web_hi_res_512.png and /dev/null differ diff --git a/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangas.kt b/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangas.kt deleted file mode 100644 index 7e4700463..000000000 --- a/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangas.kt +++ /dev/null @@ -1,278 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.unionmangas - -import com.github.salomonbrys.kotson.array -import com.github.salomonbrys.kotson.nullObj -import com.github.salomonbrys.kotson.obj -import com.github.salomonbrys.kotson.string -import com.google.gson.JsonElement -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -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 okhttp3.FormBody -import okhttp3.Headers -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import java.text.ParseException -import java.text.SimpleDateFormat -import java.util.Locale -import java.util.concurrent.TimeUnit - -class UnionMangas : ParsedHttpSource() { - - // Hardcode the id because the language wasn't specific. - override val id: Long = 6931383302802153355 - - override val name = "Union Mangás" - - override val baseUrl = "https://unionmangas.top" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .connectTimeout(3, TimeUnit.MINUTES) - .readTimeout(3, TimeUnit.MINUTES) - .writeTimeout(3, TimeUnit.MINUTES) - .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS)) - .build() - - override fun headersBuilder(): Headers.Builder = Headers.Builder() - .add("Accept", ACCEPT) - .add("Accept-Language", ACCEPT_LANGUAGE) - .add("Referer", "$baseUrl/home") - - override fun popularMangaRequest(page: Int): Request { - val listPath = if (page == 1) "" else "/visualizacoes/${page - 1}" - val newHeaders = headersBuilder() - .set("Referer", "$baseUrl/lista-mangas$listPath") - .build() - - val pageStr = if (page != 1) "/$page" else "" - return GET("$baseUrl/lista-mangas/visualizacoes$pageStr", newHeaders) - } - - override fun popularMangaParse(response: Response): MangasPage { - val results = super.popularMangaParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun popularMangaSelector(): String = "div.col-md-3.col-xs-6:has(img.img-thumbnail)" - - override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply { - title = element.select("div[id^=bloco-tooltip] > b").first().text().withoutLanguage() - thumbnail_url = element.select("a img").first()?.attr("src") - setUrlWithoutDomain(element.select("a").last().attr("href")) - } - - override fun popularMangaNextPageSelector() = ".pagination li:contains(Next)" - - override fun latestUpdatesRequest(page: Int): Request { - val form = FormBody.Builder() - .add("pagina", page.toString()) - .build() - - val newHeaders = headersBuilder() - .add("Content-Type", form.contentType().toString()) - .add("Content-Length", form.contentLength().toString()) - .add("Origin", baseUrl) - .add("X-Requested-With", "XMLHttpRequest") - .set("Accept", "*/*") - .build() - - return POST("$baseUrl/assets/noticias.php", newHeaders, form) - } - - override fun latestUpdatesParse(response: Response): MangasPage { - val results = super.latestUpdatesParse(response) - - if (results.mangas.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun latestUpdatesSelector() = "div.row[style] div.col-md-12[style]" - - override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply { - val infoElement = element.select("a.link-titulo") - - title = infoElement.last().text().withoutLanguage() - thumbnail_url = infoElement.first()?.select("img")?.attr("src") - setUrlWithoutDomain(infoElement.last().attr("href")) - } - - override fun latestUpdatesNextPageSelector() = "div#linha-botao-mais" - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - if (query.startsWith(PREFIX_SLUG_SEARCH)) { - val slug = query.removePrefix(PREFIX_SLUG_SEARCH) - return GET("$baseUrl/pagina-manga/$slug", headers) - } - - val newHeaders = headersBuilder() - .set("Accept", ACCEPT_JSON) - .add("X-Requested-With", "XMLHttpRequest") - .build() - - val url = "$baseUrl/assets/busca.php".toHttpUrlOrNull()!!.newBuilder() - .addQueryParameter("titulo", query) - - return GET(url.toString(), newHeaders) - } - - override fun searchMangaParse(response: Response): MangasPage { - val requestUrl = response.request.url.toString() - - if (requestUrl.contains("pagina-manga")) { - val slug = requestUrl.substringAfter("pagina-manga/") - val manga = mangaDetailsParse(response) - .apply { url = "/pagina-manga/$slug" } - return MangasPage(listOf(manga), false) - } - - val result = response.asJson().nullObj - ?: throw Exception(BLOCK_MESSAGE) - - val mangas = result["items"].array - .map { searchMangaFromObject(it.obj) } - - return MangasPage(mangas, false) - } - - private fun searchMangaFromObject(obj: JsonObject): SManga = SManga.create().apply { - title = obj["titulo"].string.withoutLanguage() - thumbnail_url = obj["imagem"].string - setUrlWithoutDomain("$baseUrl/pagina-manga/${obj["url"].string}") - } - - override fun mangaDetailsRequest(manga: SManga): Request { - // Map the mangas that are already in library with the old URL to the new one. - val newUrl = manga.url.replace("perfil-manga", "pagina-manga") - return GET(baseUrl + newUrl, headers) - } - - override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { - val infoElement = document.select("div.perfil-manga").firstOrNull() - ?: throw Exception(BLOCK_MESSAGE) - val rowInfo = infoElement.select("div.row:eq(2)").first() - - title = infoElement.select("h2").first().text().withoutLanguage() - author = rowInfo.select("div.col-md-8:eq(4)").first().textWithoutLabel() - artist = rowInfo.select("div.col-md-8:eq(5)").first().textWithoutLabel() - genre = rowInfo.select("div.col-md-8:eq(3)").first().textWithoutLabel() - status = rowInfo.select("div.col-md-8:eq(6)").first().text().toStatus() - description = rowInfo.select("div.col-md-8:eq(8)").first().text() - thumbnail_url = infoElement.select(".img-thumbnail").first().attr("src") - } - - override fun chapterListParse(response: Response): List { - val results = super.chapterListParse(response) - - if (results.isEmpty()) { - throw Exception(BLOCK_MESSAGE) - } - - return results - } - - override fun chapterListSelector() = "div.row.capitulos" - - override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { - val firstColumn = element.select("div.col-md-6:eq(0)").first()!! - val secondColumn = element.select("div.col-md-6:eq(1)").firstOrNull() - - name = firstColumn.select("a").first().text() - scanlator = secondColumn?.select("a")?.joinToString { it.text() } - date_upload = firstColumn.select("span").last()!!.text().toDate() - - // For some reason, setUrlWithoutDomain does not work when the url have spaces. - val absoluteUrlFixed = firstColumn.select("a").first() - .attr("href") - .replace(" ", "%20") - setUrlWithoutDomain(absoluteUrlFixed) - } - - override fun pageListParse(document: Document): List { - return document.select("img.img-responsive.img-manga") - .filter { it.attr("src").contains("/leitor/") } - .mapIndexed { i, element -> - Page(i, document.location(), element.absUrl("src")) - } - } - - override fun imageUrlParse(document: Document) = "" - - override fun imageRequest(page: Page): Request { - val newHeaders = headersBuilder() - .set("Accept", ACCEPT_IMAGE) - .set("Referer", page.url) - .build() - - return GET(page.imageUrl!!, newHeaders) - } - - override fun searchMangaSelector() = throw Exception("This method should not be called!") - - override fun searchMangaFromElement(element: Element): SManga = throw Exception("This method should not be called!") - - override fun searchMangaNextPageSelector() = throw Exception("This method should not be called!") - - private fun String.toDate(): Long { - return try { - DATE_FORMATTER.parse(this)?.time ?: 0L - } catch (e: ParseException) { - 0L - } - } - - private fun String.toStatus(): Int = when { - contains("Ativo") -> SManga.ONGOING - contains("Completo") -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - - private fun String.withoutLanguage(): String = - replace("(pt-br)", "", true).trim() - - private fun Element.textWithoutLabel(): String = text()!!.substringAfter(":").trim() - - private fun Response.asJson(): JsonElement = JsonParser.parseString(body!!.string()) - - companion object { - private const val ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," + - "image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" - private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" - private const val ACCEPT_JSON = "application/json, text/javascript, */*; q=0.01" - private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5" - private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36" - - private const val BLOCK_MESSAGE = "O site está bloqueando o Tachiyomi. " + - "Migre para outra fonte caso o problema persistir." - - private val DATE_FORMATTER by lazy { - SimpleDateFormat("(dd/MM/yyyy)", Locale.ENGLISH) - } - - const val PREFIX_SLUG_SEARCH = "slug:" - } -} diff --git a/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangasUrlActivity.kt b/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangasUrlActivity.kt deleted file mode 100644 index eebd580d3..000000000 --- a/src/pt/unionmangas/src/eu/kanade/tachiyomi/extension/pt/unionmangas/UnionMangasUrlActivity.kt +++ /dev/null @@ -1,38 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.unionmangas - -import android.app.Activity -import android.content.ActivityNotFoundException -import android.content.Intent -import android.os.Bundle -import android.util.Log -import kotlin.system.exitProcess - -/** - * Springboard that accepts https://unionleitor.top/perfil-manga/xxxxxx intents - * and redirects them to the main Tachiyomi process. - */ -class UnionMangasUrlActivity : 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", "${UnionMangas.PREFIX_SLUG_SEARCH}$slug") - putExtra("filter", packageName) - } - - try { - startActivity(mainIntent) - } catch (e: ActivityNotFoundException) { - Log.e("UnionMangasUrl", e.toString()) - } - } else { - Log.e("UnionMangasUrl", "could not parse uri from intent $intent") - } - - finish() - exitProcess(0) - } -} diff --git a/src/pt/yesmangas/AndroidManifest.xml b/src/pt/yesmangas/AndroidManifest.xml deleted file mode 100644 index 30deb7f79..000000000 --- a/src/pt/yesmangas/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/pt/yesmangas/build.gradle b/src/pt/yesmangas/build.gradle deleted file mode 100644 index 69273f976..000000000 --- a/src/pt/yesmangas/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'YES Mangás' - pkgNameSuffix = 'pt.yesmangas' - extClass = '.YesMangas' - extVersionCode = 7 - libVersion = '1.2' -} - -dependencies { - implementation project(':lib-ratelimit') -} - -apply from: "$rootDir/common.gradle" diff --git a/src/pt/yesmangas/res/mipmap-hdpi/ic_launcher.png b/src/pt/yesmangas/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 3b91c99e5..000000000 Binary files a/src/pt/yesmangas/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/yesmangas/res/mipmap-mdpi/ic_launcher.png b/src/pt/yesmangas/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 51afc3037..000000000 Binary files a/src/pt/yesmangas/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/yesmangas/res/mipmap-xhdpi/ic_launcher.png b/src/pt/yesmangas/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index f0662aa59..000000000 Binary files a/src/pt/yesmangas/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/yesmangas/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/yesmangas/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 7f3a529c6..000000000 Binary files a/src/pt/yesmangas/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/yesmangas/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/yesmangas/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index dc63f07bd..000000000 Binary files a/src/pt/yesmangas/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/yesmangas/res/web_hi_res_512.png b/src/pt/yesmangas/res/web_hi_res_512.png deleted file mode 100644 index 9c518e509..000000000 Binary files a/src/pt/yesmangas/res/web_hi_res_512.png and /dev/null differ diff --git a/src/pt/yesmangas/src/eu/kanade/tachiyomi/extension/pt/yesmangas/YesMangas.kt b/src/pt/yesmangas/src/eu/kanade/tachiyomi/extension/pt/yesmangas/YesMangas.kt deleted file mode 100644 index 101d351db..000000000 --- a/src/pt/yesmangas/src/eu/kanade/tachiyomi/extension/pt/yesmangas/YesMangas.kt +++ /dev/null @@ -1,146 +0,0 @@ -package eu.kanade.tachiyomi.extension.pt.yesmangas - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.FilterList -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 okhttp3.Headers -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.OkHttpClient -import okhttp3.Request -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import org.jsoup.select.Elements -import java.util.concurrent.TimeUnit - -class YesMangas : ParsedHttpSource() { - - // Hardcode the id because the language wasn't specific. - override val id: Long = 7187189302580957274 - - override val name = "YES Mangás" - - override val baseUrl = "https://yesmangas1.com" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .addInterceptor(RateLimitInterceptor(1, 1, TimeUnit.SECONDS)) - .build() - - override fun headersBuilder(): Headers.Builder = Headers.Builder() - .add("User-Agent", USER_AGENT) - .add("Origin", baseUrl) - .add("Referer", baseUrl) - - override fun popularMangaRequest(page: Int): Request = GET(baseUrl, headers) - - override fun popularMangaSelector(): String = "div#destaques div.three.columns a.img" - - override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply { - title = element.attr("title").withoutLanguage() - thumbnail_url = element.select("img").attr("data-path").toLargeUrl() - url = element.attr("href") - } - - override fun popularMangaNextPageSelector(): String? = null - - override fun latestUpdatesRequest(page: Int): Request = GET(baseUrl, headers) - - override fun latestUpdatesSelector(): String = "div#lancamentos table.u-full-width tbody tr td:eq(0) a" - - override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply { - title = element.attr("title").withoutLanguage() - thumbnail_url = element.select("img").attr("data-path").toLargeUrl() - setUrlWithoutDomain(element.attr("href")) - } - - override fun latestUpdatesNextPageSelector(): String? = null - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = "$baseUrl/search".toHttpUrlOrNull()!!.newBuilder() - .addQueryParameter("q", query) - - return GET(url.toString(), headers) - } - - override fun searchMangaSelector(): String = "tbody#leituras tr td:eq(0) a" - - override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply { - title = element.attr("title").withoutLanguage() - thumbnail_url = element.select("img").attr("data-path").toLargeUrl() - setUrlWithoutDomain(element.attr("href")) - } - - override fun searchMangaNextPageSelector(): String? = null - - override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { - val container = document.select("div#descricao").first() - - author = container.select("ul li:contains(Autor)").textWithoutLabel() - artist = container.select("ul li:contains(Desenho)").textWithoutLabel() - genre = container.select("ul li:contains(Categorias)").textWithoutLabel() - status = container.select("ul li:contains(Status)").text().toStatus() - description = container.select("article").text() - .substringBefore("Relacionados") - thumbnail_url = container.select("img").first() - .attr("data-path") - .toLargeUrl() - } - - override fun chapterListSelector(): String = "div#capitulos a.button" - - override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { - name = element.attr("title").substringAfter(" - ") - chapter_number = element.text().toFloatOrNull() ?: -1f - setUrlWithoutDomain(element.attr("href")) - } - - override fun pageListRequest(chapter: SChapter): Request { - val newHeaders = headersBuilder() - .set("Referer", baseUrl + chapter.url.substringBeforeLast("/")) - .build() - - return GET(baseUrl + chapter.url, newHeaders) - } - - override fun pageListParse(document: Document): List { - return document.select("div.read-slideshow a img") - .mapIndexed { i, el -> Page(i, document.location(), el.attr("src")) } - } - - override fun imageUrlParse(document: Document): String = "" - - override fun imageRequest(page: Page): Request { - val newHeaders = headersBuilder() - .set("Referer", page.url) - .build() - - return GET(page.imageUrl!!, newHeaders) - } - - private fun String.withoutLanguage(): String = replace(LANG_REGEX, "") - - private fun String.toLargeUrl(): String = replace(IMAGE_REGEX, "_full.") - - private fun Elements.textWithoutLabel(): String = text()!!.substringAfter(":").trim() - - private fun String.toStatus() = when { - contains("Completo") -> SManga.COMPLETED - contains("Ativo") -> SManga.ONGOING - else -> SManga.UNKNOWN - } - - companion object { - private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36" - - private val LANG_REGEX = "( )?\\((PT-)?BR\\)".toRegex() - private val IMAGE_REGEX = "_(small|medium|xmedium|xlarge)\\.".toRegex() - } -}