Remove dead sources

Closes #16546
Closes #16547
Closes #16548
Closes #16577
Closes #16578
Closes #16583
This commit is contained in:
arkon 2023-05-26 17:34:13 -04:00
parent 757f5d8fb1
commit 61646e9953
21 changed files with 0 additions and 611 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

View File

@ -1,68 +0,0 @@
package eu.kanade.tachiyomi.extension.vi.phemanga
import eu.kanade.tachiyomi.multisrc.mymangacms.MyMangaCMS
class PheManga : MyMangaCMS("Phê Manga", "https://phemanga.net", "vi") {
override fun dateUpdatedParser(date: String): Long =
runCatching { super.dateUpdatedParser(date.split(" - ")[1]) }.getOrNull() ?: 0L
override fun getGenreList() = listOf(
Genre("16+", 1),
Genre("18+", 2),
Genre("Action", 3),
Genre("Adult", 4),
Genre("Adventure", 5),
Genre("Anime", 6),
Genre("Comedy", 7),
Genre("Comic", 8),
Genre("Doujinshi", 9),
Genre("Drama", 10),
Genre("Ecchi", 11),
Genre("Fantasy", 13),
Genre("Full màu", 14),
Genre("Game", 15),
Genre("Gender Bender", 16),
Genre("Harem", 17),
Genre("Historical", 18),
Genre("Horror", 19),
Genre("Isekai/Dị giới/Trọng sinh", 20),
Genre("Josei", 21),
Genre("Live action", 22),
Genre("Magic", 23),
Genre("Manga", 24),
Genre("Manhua", 25),
Genre("Manhwa", 26),
Genre("Martial Arts", 27),
Genre("Mature", 28),
Genre("Mecha", 29),
Genre("Mystery", 30),
Genre("Nấu Ăn", 31),
Genre("Ngôn Tình", 32),
Genre("NTR", 33),
Genre("One shot", 34),
Genre("Psychological", 35),
Genre("Romance", 36),
Genre("School Life", 37),
Genre("Sci-fi", 38),
Genre("Seinen", 39),
Genre("Shoujo", 40),
Genre("Shoujo Ai", 41),
Genre("Shounen", 42),
Genre("Shounen Ai", 43),
Genre("Slice of life", 44),
Genre("Smut", 45),
Genre("Soft Yaoi", 46),
Genre("Soft Yuri", 47),
Genre("Sports", 48),
Genre("Supernatural", 49),
Genre("Tạp chí truyện tranh", 50),
Genre("Tragedy", 51),
Genre("Trap (Crossdressing)", 52),
Genre("Trinh Thám", 53),
Genre("Truyện scan", 54),
Genre("Tu chân - tu tiên", 55),
Genre("VnComic", 56),
Genre("Webtoon", 57),
Genre("Yuri", 58),
)
}

View File

@ -25,7 +25,6 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("247Manga", "https://247manga.com", "en", className = "Manga247", overrideVersionCode = 1),
SingleLang("365Manga", "https://365manga.com", "en", className = "ThreeSixtyFiveManga", overrideVersionCode = 1),
SingleLang("Adonis Fansub", "https://manga.adonisfansub.com", "tr", overrideVersionCode = 1),
SingleLang("Adult Painful Nightz", "https://adults.painfulnightz.com", "en", isNsfw = true),
SingleLang("Adult Webtoon", "https://adultwebtoon.com", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("AiYuManga", "https://aiyumangascanlation.com", "es", overrideVersionCode = 1),
SingleLang("Akuma no Tenshi", "https://akumanotenshi.com", "pt-BR", className = "AkumaNoTenshi"),
@ -211,7 +210,6 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Manga-Scantrad", "https://manga-scantrad.io", "fr", className = "MangaScantrad", overrideVersionCode = 3),
SingleLang("Manga-TX", "https://manga-tx.com", "en", className = "Mangatxunoriginal"),
SingleLang("Manga18fx", "https://manga18fx.com", "en", isNsfw = true, overrideVersionCode = 5),
SingleLang("Manga1st", "https://manga1st.com", "en", overrideVersionCode = 2),
SingleLang("Manga1st.online", "https://manga1st.online", "en", className = "MangaFirstOnline", overrideVersionCode = 1),
SingleLang("Manga347", "https://manga347.com", "en", overrideVersionCode = 3),
SingleLang("Manga3S", "https://manga3s.com", "en", overrideVersionCode = 4),
@ -265,7 +263,6 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("MangaXP", "https://mangaxp.com", "en", overrideVersionCode = 1),
SingleLang("MangaYami", "https://www.mangayami.club", "en", overrideVersionCode = 2),
SingleLang("Manhatic", "https://manhatic.com", "ar", isNsfw = true),
SingleLang("Manhua Dragon", "https://manhuadragon.com", "en"),
SingleLang("Manhua ES", "https://manhuaes.com", "en", overrideVersionCode = 6),
SingleLang("Manhua Kiss", "https://manhuakiss.com", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("Manhua Plus", "https://manhuaplus.com", "en", overrideVersionCode = 6),

View File

@ -20,7 +20,6 @@ class MMRCMSGenerator : ThemeSourceGenerator {
SingleLang("Scan VF", "https://www.scan-vf.net", "fr", overrideVersionCode = 1),
SingleLang("Scan OP", "https://scan-op.cc", "fr"),
SingleLang("Komikid", "https://www.komikid.com", "id"),
SingleLang("Fallen Angels Scans", "https://truyen.fascans.com", "vi"),
SingleLang("Mangadoor", "https://mangadoor.com", "es", overrideVersionCode = 1),
SingleLang("Utsukushii", "https://manga.utsukushii-bg.com", "bg", overrideVersionCode = 1),
SingleLang("Phoenix-Scans", "https://phoenix-scans.pl", "pl", className = "PhoenixScans", overrideVersionCode = 1),

View File

@ -14,7 +14,6 @@ object SourceData {
"https://scan-op.cc" -> """{"name":"Scan OP","base_url":"https://scan-op.cc","supports_latest":true,"item_url":"https://scan-op.cc/manga/","categories":[{"id":"1","name":"Comedy"},{"id":"2","name":"Doujinshi"},{"id":"3","name":"Drama"},{"id":"4","name":"Ecchi"},{"id":"5","name":"Fantasy"},{"id":"6","name":"Gender Bender"},{"id":"7","name":"Josei"},{"id":"8","name":"Mature"},{"id":"9","name":"Mecha"},{"id":"10","name":"Mystery"},{"id":"11","name":"One Shot"},{"id":"12","name":"Psychological"},{"id":"13","name":"Romance"},{"id":"14","name":"School Life"},{"id":"15","name":"Sci-fi"},{"id":"16","name":"Seinen"},{"id":"17","name":"Shoujo"},{"id":"18","name":"Shoujo Ai"},{"id":"19","name":"Shounen"},{"id":"20","name":"Shounen Ai"},{"id":"21","name":"Slice of Life"},{"id":"22","name":"Sports"},{"id":"23","name":"Supernatural"},{"id":"24","name":"Tragedy"},{"id":"25","name":"Yaoi"},{"id":"26","name":"Yuri"},{"id":"27","name":"Comics"},{"id":"28","name":"Autre"}],"tags":[{"id":"nouveau","name":"nouveau"}]}"""
"https://www.komikid.com" -> """{"name":"Komikid","base_url":"https://www.komikid.com","supports_latest":true,"item_url":"https://www.komikid.com/manga/","categories":[{"id":"1","name":"Action"},{"id":"2","name":"Adventure"},{"id":"3","name":"Comedy"},{"id":"4","name":"Doujinshi"},{"id":"5","name":"Drama"},{"id":"6","name":"Fantasy"},{"id":"7","name":"Gender Bender"},{"id":"8","name":"Historical"},{"id":"9","name":"Horror"},{"id":"10","name":"Josei"},{"id":"11","name":"Martial Arts"},{"id":"12","name":"Mature"},{"id":"13","name":"Mecha"},{"id":"14","name":"Mystery"},{"id":"15","name":"One Shot"},{"id":"16","name":"Psychological"},{"id":"17","name":"Romance"},{"id":"18","name":"School Life"},{"id":"19","name":"Sci-fi"},{"id":"20","name":"Seinen"},{"id":"21","name":"Shoujo"},{"id":"22","name":"Shoujo Ai"},{"id":"23","name":"Shounen"},{"id":"24","name":"Shounen Ai"},{"id":"25","name":"Slice of Life"},{"id":"26","name":"Sports"},{"id":"27","name":"Supernatural"},{"id":"28","name":"Tragedy"},{"id":"29","name":"Yaoi"},{"id":"30","name":"Yuri"}]}"""
"http://azbivo.webd.pro" -> """{"name":"Nikushima","base_url":"http://azbivo.webd.pro","supports_latest":false,"item_url":"\u003chtml\u003e \n \u003chead\u003e \n \u003cmeta http-equiv\u003d\"Content-Language\" content\u003d\"pl\"\u003e \n \u003cmeta http-equiv name\u003d\"pragma\" content\u003d\"no-cache\"\u003e \n \u003clink href\u003d\"style/style.css\" rel\u003d\"stylesheet\" type\u003d\"text/css\"\u003e \n \u003cmeta http-equiv\u003d\"Refresh\" content\u003d\"0; url\u003dhttps://www.webd.pl/_errnda.php?utm_source\u003dwn07\u0026amp;utm_medium\u003dwww\u0026amp;utm_campaign\u003dblock\"\u003e \n \u003cmeta name\u003d\"Robots\" content\u003d\"index, follow\"\u003e \n \u003cmeta name\u003d\"revisit-after\" content\u003d\"2 days\"\u003e \n \u003cmeta name\u003d\"rating\" content\u003d\"general\"\u003e \n \u003cmeta name\u003d\"keywords\" content\u003d\"STRONA ZAWIESZONA, WEBD, DOMENY, DOMENA, HOSTING, SERWER, INTERNET, PHP, MySQL, FTP, WEBMASTER, SERWERY WIRTUALNE, WWW, KONTO, MAIL, POCZTA, E-MAIL, NET, .COM, .ORG, TANIE, PHP+MySQL, DOMENY, DOMENA, HOSTING, SERWER, INTERNET, PHP, MySQL, FTP, WEBMASTER, SERWERY WIRTUALNE, WWW, KONTO, MAIL, POCZTA, E-MAIL, DOMENY, DOMENA, NET, .COM, .ORG, TANIE, PHP+MySQL, HOSTING, SERWER, INTERNET, PHP, MySQL, FTP, WEBMASTER, SERWERY WIRTUALNE, WWW, KONTO, MAIL, POCZTA, E-MAIL, NET, .COM, .ORG, TANIE, PHP+MySQL\"\u003e \n \u003cmeta name\u003d\"description\" content\u003d\"STRONA ZAWIESZONA - Oferujemy profesjonalny hosting z PHP + MySQL, rejestrujemy domeny. Sprawdz nasz hosting i przetestuj nasze serwery. Kupuj tanio domeny i serwery!\"\u003e \n \u003ctitle\u003eSTRONA ZAWIESZONA - WEBD.PL - Tw<54>j profesjonalny hosting za jedyne 4.99PLN! Serwery z PHP+MySQL, tanie domeny, serwer + domena .pl - taniej sie nie da!\u003c/title\u003e \n \u003cscript type\u003d\"text/javascript\"\u003e\nfunction init() {\n if (!document.getElementById) return\n var imgOriginSrc;\n var imgTemp \u003d new Array();\n var imgarr \u003d document.getElementsByTagName(\u0027img\u0027);\n for (var i \u003d 0; i \u003c imgarr.length; i++) {\n if (imgarr[i].getAttribute(\u0027hsrc\u0027)) {\n imgTemp[i] \u003d new Image();\n imgTemp[i].src \u003d imgarr[i].getAttribute(\u0027hsrc\u0027);\n imgarr[i].onmouseover \u003d function() {\n imgOriginSrc \u003d this.getAttribute(\u0027src\u0027);\n this.setAttribute(\u0027src\u0027,this.getAttribute(\u0027hsrc\u0027))\n }\n imgarr[i].onmouseout \u003d function() {\n this.setAttribute(\u0027src\u0027,imgOriginSrc)\n }\n }\n }\n}\nonload\u003dinit;\n\u003c/script\u003e \n \u003c/head\u003e \n \u003cbody\u003e\n Trwa przekierowanie .... \u0026gt;\u0026gt;\u0026gt;\u0026gt; \u003c!--\n--\u003e \n \u003c/body\u003e\n\u003c/html\u003e/","categories":[]}"""
"https://truyen.fascans.com" -> """{"name":"Fallen Angels Scans","base_url":"https://truyen.fascans.com","supports_latest":true,"item_url":"https://truyen.fascans.com/manga/","categories":[{"id":"1","name":"Action"},{"id":"2","name":"Adventure"},{"id":"3","name":"Comedy"},{"id":"4","name":"Doujinshi"},{"id":"5","name":"Drama"},{"id":"6","name":"Ecchi"},{"id":"7","name":"Fantasy"},{"id":"8","name":"Gender Bender"},{"id":"9","name":"Harem"},{"id":"10","name":"Historical"},{"id":"11","name":"Horror"},{"id":"12","name":"Josei"},{"id":"13","name":"Martial Arts"},{"id":"14","name":"Mature"},{"id":"15","name":"Mecha"},{"id":"16","name":"Mystery"},{"id":"17","name":"One Shot"},{"id":"18","name":"Psychological"},{"id":"19","name":"Romance"},{"id":"20","name":"School Life"},{"id":"21","name":"Sci-fi"},{"id":"22","name":"Seinen"},{"id":"23","name":"Shoujo"},{"id":"24","name":"Shoujo Ai"},{"id":"25","name":"Shounen"},{"id":"26","name":"Shounen Ai"},{"id":"27","name":"Slice of Life"},{"id":"28","name":"Sports"},{"id":"29","name":"Supernatural"},{"id":"30","name":"Tragedy"},{"id":"31","name":"Yaoi"},{"id":"32","name":"Yuri"}]}"""
"https://mangadoor.com" -> """{"name":"Mangadoor","base_url":"https://mangadoor.com","supports_latest":true,"item_url":"https://mangadoor.com/manga/","categories":[{"id":"1","name":"Acción"},{"id":"2","name":"Aventura"},{"id":"3","name":"Comedia"},{"id":"4","name":"Drama"},{"id":"5","name":"Ecchi"},{"id":"6","name":"Fantasía"},{"id":"7","name":"Gender Bender"},{"id":"8","name":"Harem"},{"id":"9","name":"Histórico"},{"id":"10","name":"Horror"},{"id":"11","name":"Josei"},{"id":"12","name":"Artes Marciales"},{"id":"13","name":"Maduro"},{"id":"14","name":"Mecha"},{"id":"15","name":"Misterio"},{"id":"16","name":"One Shot"},{"id":"17","name":"Psicológico"},{"id":"18","name":"Romance"},{"id":"19","name":"Escolar"},{"id":"20","name":"Ciencia Ficción"},{"id":"21","name":"Seinen"},{"id":"22","name":"Shoujo"},{"id":"23","name":"Shoujo Ai"},{"id":"24","name":"Shounen"},{"id":"25","name":"Shounen Ai"},{"id":"26","name":"Recuentos de la vida"},{"id":"27","name":"Deportes"},{"id":"28","name":"Supernatural"},{"id":"29","name":"Tragedia"},{"id":"30","name":"Yaoi"},{"id":"31","name":"Yuri"},{"id":"32","name":"Demonios"},{"id":"33","name":"Juegos"},{"id":"34","name":"Policial"},{"id":"35","name":"Militar"},{"id":"36","name":"Thriller"},{"id":"37","name":"Autos"},{"id":"38","name":"Música"},{"id":"39","name":"Vampiros"},{"id":"40","name":"Magia"},{"id":"41","name":"Samurai"},{"id":"42","name":"Boys love"},{"id":"43","name":"Hentai"}]}"""
"https://mangas.in" -> """{"name":"Mangas.pw","base_url":"https://mangas.in","supports_latest":true,"item_url":"https://mangas.in/manga/","categories":[{"id":"1","name":"Action"},{"id":"2","name":"Adventure"},{"id":"3","name":"Comedy"},{"id":"4","name":"Doujinshi"},{"id":"5","name":"Drama"},{"id":"6","name":"Ecchi"},{"id":"7","name":"Fantasy"},{"id":"8","name":"Gender Bender"},{"id":"9","name":"Harem"},{"id":"10","name":"Historical"},{"id":"11","name":"Horror"},{"id":"12","name":"Josei"},{"id":"13","name":"Martial Arts"},{"id":"14","name":"Mature"},{"id":"15","name":"Mecha"},{"id":"16","name":"Mystery"},{"id":"17","name":"One Shot"},{"id":"18","name":"Psychological"},{"id":"19","name":"Romance"},{"id":"20","name":"School Life"},{"id":"21","name":"Sci-fi"},{"id":"22","name":"Seinen"},{"id":"23","name":"Shoujo"},{"id":"24","name":"Shoujo Ai"},{"id":"25","name":"Shounen"},{"id":"26","name":"Shounen Ai"},{"id":"27","name":"Slice of Life"},{"id":"28","name":"Sports"},{"id":"29","name":"Supernatural"},{"id":"30","name":"Tragedy"},{"id":"31","name":"Yaoi"},{"id":"32","name":"Yuri"},{"id":"33","name":"Hentai"},{"id":"34","name":"Smut"}]}"""
"https://manga.utsukushii-bg.com" -> """{"name":"Utsukushii","base_url":"https://manga.utsukushii-bg.com","supports_latest":true,"item_url":"https://manga.utsukushii-bg.com/manga/","categories":[{"id":"1","name":"Екшън"},{"id":"2","name":"Приключенски"},{"id":"3","name":"Комедия"},{"id":"4","name":"Драма"},{"id":"5","name":"Фентъзи"},{"id":"6","name":"Исторически"},{"id":"7","name":"Ужаси"},{"id":"8","name":"Джосей"},{"id":"9","name":"Бойни изкуства"},{"id":"10","name":"Меха"},{"id":"11","name":"Мистерия"},{"id":"12","name":"Самостоятелна/Пилотна глава"},{"id":"13","name":"Психологически"},{"id":"14","name":"Романтика"},{"id":"15","name":"Училищни"},{"id":"16","name":"Научна фантастика"},{"id":"17","name":"Сейнен"},{"id":"18","name":"Шоджо"},{"id":"19","name":"Реализъм"},{"id":"20","name":"Спорт"},{"id":"21","name":"Свръхестествено"},{"id":"22","name":"Трагедия"},{"id":"23","name":"Йокаи"},{"id":"24","name":"Паралелна вселена"},{"id":"25","name":"Супер сили"},{"id":"26","name":"Пародия"},{"id":"27","name":"Шонен"}]}"""

View File

@ -18,14 +18,6 @@ class MyMangaCMSGenerator : ThemeSourceGenerator {
"vi",
overrideVersionCode = 9,
),
SingleLang(
"Phê Manga",
"https://phemanga.net",
"vi",
true,
"PheManga",
"phemanga",
),
SingleLang("LKDTT", "https://lkdttee.com", "vi", true, overrideVersionCode = 4),
)

View File

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="eu.kanade.tachiyomi.extension">
<application>
<activity android:name=".vi.blogtruyen.BlogTruyenUrlActivity"
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="blogtruyen.vn" />
<data android:host="m.blogtruyen.vn" />
<data android:scheme="https" />
<data android:pathPattern="/tac-gia/..*" />
<data android:pathPattern="/nhom-dich/..*" />
<!--
Try to ensure that the passed URL is a chapter `c{id}` or a manga `{id}`, with `id`
being a number.
-->
<data android:pathPattern="/c1.*/..*" />
<data android:pathPattern="/c2.*/..*" />
<data android:pathPattern="/c3.*/..*" />
<data android:pathPattern="/c4.*/..*" />
<data android:pathPattern="/c5.*/..*" />
<data android:pathPattern="/c6.*/..*" />
<data android:pathPattern="/c7.*/..*" />
<data android:pathPattern="/c8.*/..*" />
<data android:pathPattern="/c9.*/..*" />
<data android:pathPattern="/1.*/..*" />
<data android:pathPattern="/2.*/..*" />
<data android:pathPattern="/3.*/..*" />
<data android:pathPattern="/4.*/..*" />
<data android:pathPattern="/5.*/..*" />
<data android:pathPattern="/6.*/..*" />
<data android:pathPattern="/7.*/..*" />
<data android:pathPattern="/8.*/..*" />
<data android:pathPattern="/9.*/..*" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,12 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'BlogTruyen'
pkgNameSuffix = 'vi.blogtruyen'
extClass = '.BlogTruyen'
extVersionCode = 14
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

View File

@ -1,432 +0,0 @@
package eu.kanade.tachiyomi.extension.vi.blogtruyen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.interceptor.rateLimit
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 kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.FormBody
import okhttp3.Headers
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 rx.Observable
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
class BlogTruyen : ParsedHttpSource() {
override val name = "BlogTruyen"
override val baseUrl = "https://blogtruyen.vn"
override val lang = "vi"
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.rateLimit(1)
.build()
private val json: Json by injectLazy()
private val dateFormat: SimpleDateFormat = SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.ENGLISH)
companion object {
const val PREFIX_ID_SEARCH = "id:"
const val PREFIX_AUTHOR_SEARCH = "author:"
const val PREFIX_TEAM_SEARCH = "team:"
}
override fun headersBuilder(): Headers.Builder =
super.headersBuilder().add("Referer", "$baseUrl/")
override fun popularMangaRequest(page: Int): Request =
GET("$baseUrl/ajax/Search/AjaxLoadListManga?key=tatca&orderBy=3&p=$page", headers)
override fun popularMangaParse(response: Response): MangasPage {
val document = response.asJsoup()
val manga = document.select(popularMangaSelector()).map {
val tiptip = it.attr("data-tiptip")
popularMangaFromElement(it, document.getElementById(tiptip)!!)
}
val hasNextPage = document.selectFirst(popularMangaNextPageSelector()) != null
return MangasPage(manga, hasNextPage)
}
override fun popularMangaSelector() = ".list .tiptip"
override fun popularMangaFromElement(element: Element): SManga =
throw UnsupportedOperationException("Not used")
private fun popularMangaFromElement(element: Element, tiptip: Element) = SManga.create().apply {
val anchor = element.selectFirst("a")!!
setUrlWithoutDomain(anchor.attr("href"))
title = anchor.attr("title").replace("truyện tranh ", "").trim()
thumbnail_url = tiptip.selectFirst("img")!!.attr("abs:src")
description = tiptip.selectFirst(".al-j")!!.text()
}
override fun popularMangaNextPageSelector() = ".paging:last-child:not(.current_page)"
override fun latestUpdatesRequest(page: Int): Request =
GET(baseUrl + if (page != 1) "/page-$page" else "", headers)
override fun latestUpdatesSelector() = ".storyitem .fl-l"
override fun latestUpdatesFromElement(element: Element): SManga = SManga.create().apply {
setUrlWithoutDomain(element.select("a").attr("href"))
title = element.select("a").attr("title")
thumbnail_url = element.select("img").attr("abs:src")
}
override fun latestUpdatesNextPageSelector() = "select.slcPaging option:last-child:not([selected])"
override fun fetchSearchManga(
page: Int,
query: String,
filters: FilterList,
): Observable<MangasPage> {
return when {
query.startsWith(PREFIX_ID_SEARCH) -> {
var id = query.removePrefix(PREFIX_ID_SEARCH).trim()
// it's a chapter, resolve to manga ID
if (id.startsWith("c")) {
val document = client.newCall(GET("$baseUrl/$id", headers)).execute().asJsoup()
id = document.selectFirst(".breadcrumbs a:last-child")!!.attr("href").removePrefix("/")
}
fetchMangaDetails(
SManga.create().apply {
url = "/$id"
},
)
.map { MangasPage(listOf(it.apply { url = "/$id" }), false) }
}
else -> super.fetchSearchManga(page, query, filters)
}
}
private fun extractIdFromQuery(prefix: String, query: String): String {
val q = query.substringAfter(prefix).trim()
return if (q.contains("-")) {
q.substringAfterLast("-")
} else {
q
}
}
private val ajaxSearchUrls: Map<String, String> = mapOf(
PREFIX_AUTHOR_SEARCH to "Author/AjaxLoadMangaByAuthor?orderBy=3",
PREFIX_TEAM_SEARCH to "TranslateTeam/AjaxLoadMangaByTranslateTeam",
)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
ajaxSearchUrls.keys.forEach {
if (!query.startsWith(it)) {
return@forEach
}
val id = extractIdFromQuery(it, query)
val url = "$baseUrl/ajax/${ajaxSearchUrls[it]}".toHttpUrl().newBuilder()
.addQueryParameter("id", id)
.addQueryParameter("p", page.toString())
.build()
.toString()
return GET(url, headers)
}
val url = "$baseUrl/timkiem/nangcao/1".toHttpUrl().newBuilder().apply {
addQueryParameter("txt", query)
addQueryParameter("p", page.toString())
val genres = mutableListOf<Int>()
val genresEx = mutableListOf<Int>()
var status = 0
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) {
is GenreList -> filter.state.forEach {
when (it.state) {
Filter.TriState.STATE_INCLUDE -> genres.add(it.id)
Filter.TriState.STATE_EXCLUDE -> genresEx.add(it.id)
else -> {}
}
}
is Author -> {
addQueryParameter("aut", filter.state)
}
is Scanlator -> {
addQueryParameter("gr", filter.state)
}
is Status -> {
status = filter.state
}
else -> {}
}
}
addPathSegment(status.toString())
addPathSegment(genres.joinToString(","))
addPathSegment(genresEx.joinToString(","))
}.build().toString()
return GET(url, headers)
}
override fun searchMangaParse(response: Response): MangasPage {
val document = response.asJsoup()
val manga = document.select(searchMangaSelector()).map {
val tiptip = it.attr("data-tiptip")
searchMangaFromElement(it, document.getElementById(tiptip)!!)
}
val hasNextPage = document.selectFirst(searchMangaNextPageSelector()) != null
return MangasPage(manga, hasNextPage)
}
override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaFromElement(element: Element): SManga =
throw UnsupportedOperationException("Not used")
private fun searchMangaFromElement(element: Element, tiptip: Element) =
popularMangaFromElement(element, tiptip)
override fun searchMangaNextPageSelector() = ".pagination .glyphicon-step-forward"
private fun getMangaTitle(document: Document) = document.selectFirst(".entry-title a")!!
.attr("title")
.replaceFirst("truyện tranh", "", false)
.trim()
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
val anchor = document.selectFirst(".entry-title a")!!
setUrlWithoutDomain(anchor.attr("href"))
title = getMangaTitle(document)
thumbnail_url = document.select(".thumbnail img").attr("abs:src")
author = document.select("a[href*=tac-gia]").joinToString { it.text() }
genre = document.select("span.category a").joinToString { it.text() }
status = parseStatus(
document.select("span.color-red:not(.bold)").text(),
)
description = StringBuilder().apply {
// the actual synopsis
val synopsisBlock = document.selectFirst(".manga-detail .detail .content")!!
// replace the facebook blockquote in synopsis with the link (if there is one)
val fbElement = synopsisBlock.selectFirst(".fb-page, .fb-group")
if (fbElement != null) {
val fbLink = fbElement.attr("data-href")
val node = document.createElement("p")
node.appendText(fbLink)
fbElement.replaceWith(node)
}
appendLine(synopsisBlock.textWithNewlines().trim())
appendLine()
// other metadata
document.select(".description p").forEach {
val text = it.text()
if (text.contains("Thể loại") ||
text.contains("Tác giả") ||
text.isBlank()
) {
return@forEach
}
if (text.contains("Trạng thái")) {
appendLine(text.substringBefore("Trạng thái").trim())
return@forEach
}
if (text.contains("Nguồn") ||
text.contains("Tham gia update") ||
text.contains("Nhóm dịch")
) {
val key = text.substringBefore(":")
val value = it.select("a").joinToString { el -> el.text() }
appendLine("$key: $value")
return@forEach
}
it.select("a, span").append("\\n")
appendLine(it.text().replace("\\n", "\n").replace("\n ", "\n").trim())
}
}.toString().trim()
}
private fun Element.textWithNewlines() = run {
select("p").prepend("\\n")
select("br").prepend("\\n")
text().replace("\\n", "\n").replace("\n ", "\n")
}
private fun parseStatus(status: String) = when {
status.contains("Đang tiến hành") -> SManga.ONGOING
status.contains("Đã hoàn thành") -> SManga.COMPLETED
status.contains("Tạm ngưng") -> SManga.ON_HIATUS
else -> SManga.UNKNOWN
}
override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup()
val title = getMangaTitle(document)
return document.select(chapterListSelector()).map { chapterFromElement(it, title) }
}
override fun chapterListSelector() = "div.list-wrap > p"
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException("Not used")
private fun chapterFromElement(element: Element, title: String): SChapter = SChapter.create().apply {
val anchor = element.select("span > a").first()!!
setUrlWithoutDomain(anchor.attr("href"))
name = anchor.attr("title").replace(title, "", true).trim()
date_upload = runCatching {
dateFormat.parse(
element.selectFirst("span.publishedDate")!!.text(),
)?.time
}.getOrNull() ?: 0L
}
private fun countViewRequest(mangaId: String, chapterId: String): Request = POST(
"$baseUrl/Chapter/UpdateView",
headers,
FormBody.Builder()
.add("mangaId", mangaId)
.add("chapterId", chapterId)
.build(),
)
private fun countView(document: Document) {
val mangaId = document.getElementById("MangaId")!!.attr("value")
val chapterId = document.getElementById("ChapterId")!!.attr("value")
runCatching {
client.newCall(countViewRequest(mangaId, chapterId)).execute().close()
}
}
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("#content > img").forEachIndexed { i, e ->
pages.add(Page(i, imageUrl = e.attr("abs:src")))
}
// Some chapters use js script to render images
document.select("#content > script:containsData(listImageCaption)").lastOrNull()
?.let { script ->
val imagesStr = script.data().substringBefore(";").substringAfterLast("=").trim()
val imageArr = json.parseToJsonElement(imagesStr).jsonArray
imageArr.forEach {
val imageUrl = it.jsonObject["url"]!!.jsonPrimitive.content
pages.add(Page(pages.size, imageUrl = imageUrl))
}
}
countView(document)
return pages
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
private class Status : Filter.Select<String>(
"Status",
arrayOf("Sao cũng được", "Đang tiến hành", "Đã hoàn thành", "Tạm ngưng"),
)
private class Author : Filter.Text("Tác giả")
private class Scanlator : Filter.Text("Nhóm dịch")
private class Genre(name: String, val id: Int) : Filter.TriState(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Thể loại", genres)
override fun getFilterList() = FilterList(
Author(),
Scanlator(),
Status(),
GenreList(getGenreList()),
)
private fun getGenreList() = listOf(
Genre("16+", 54),
Genre("18+", 45),
Genre("Action", 1),
Genre("Adult", 2),
Genre("Adventure", 3),
Genre("Anime", 4),
Genre("Comedy", 5),
Genre("Comic", 6),
Genre("Doujinshi", 7),
Genre("Drama", 49),
Genre("Ecchi", 48),
Genre("Even BT", 60),
Genre("Fantasy", 50),
Genre("Game", 61),
Genre("Gender Bender", 51),
Genre("Harem", 12),
Genre("Historical", 13),
Genre("Horror", 14),
Genre("Isekai/Dị Giới", 63),
Genre("Josei", 15),
Genre("Live Action", 16),
Genre("Magic", 46),
Genre("Manga", 55),
Genre("Manhua", 17),
Genre("Manhwa", 18),
Genre("Martial Arts", 19),
Genre("Mature", 20),
Genre("Mecha", 21),
Genre("Mystery", 22),
Genre("Nấu ăn", 56),
Genre("NTR", 62),
Genre("One shot", 23),
Genre("Psychological", 24),
Genre("Romance", 25),
Genre("School Life", 26),
Genre("Sci-fi", 27),
Genre("Seinen", 28),
Genre("Shoujo", 29),
Genre("Shoujo Ai", 30),
Genre("Shounen", 31),
Genre("Shounen Ai", 32),
Genre("Slice of Life", 33),
Genre("Smut", 34),
Genre("Soft Yaoi", 35),
Genre("Soft Yuri", 36),
Genre("Sports", 37),
Genre("Supernatural", 38),
Genre("Tạp chí truyện tranh", 39),
Genre("Tragedy", 40),
Genre("Trap", 58),
Genre("Trinh thám", 57),
Genre("Truyện scan", 41),
Genre("Video clip", 53),
Genre("VnComic", 42),
Genre("Webtoon", 52),
Genre("Yuri", 59),
)
}

View File

@ -1,39 +0,0 @@
package eu.kanade.tachiyomi.extension.vi.blogtruyen
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 BlogTruyenUrlActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val pathSegments = intent?.data?.pathSegments
if (pathSegments != null && pathSegments.size > 1) {
try {
startActivity(
Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH"
with(pathSegments[0]) {
when {
equals("tac-gia") -> putExtra("query", "${BlogTruyen.PREFIX_AUTHOR_SEARCH}${pathSegments[1]}")
equals("nhom-dich") -> putExtra("query", "${BlogTruyen.PREFIX_TEAM_SEARCH}${pathSegments[1]}")
else -> putExtra("query", "${BlogTruyen.PREFIX_ID_SEARCH}${pathSegments[0]}/${pathSegments[1]}")
}
}
putExtra("filter", packageName)
},
)
} catch (e: ActivityNotFoundException) {
Log.e("BlogTruyenUrlActivity", e.toString())
}
} else {
Log.e("BlogTruyenUrlActivity", "Could not parse URI from intent $intent")
}
finish()
exitProcess(0)
}
}