diff --git a/src/ko/agitoon/build.gradle b/src/ko/agitoon/build.gradle deleted file mode 100644 index 9f7f83f8e..000000000 --- a/src/ko/agitoon/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -ext { - extName = 'AgiToon' - extClass = '.AgiToon' - extVersionCode = 1 - isNsfw = true -} - -apply from: "$rootDir/common.gradle" diff --git a/src/ko/agitoon/res/mipmap-hdpi/ic_launcher.png b/src/ko/agitoon/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index ac595ab56..000000000 Binary files a/src/ko/agitoon/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/ko/agitoon/res/mipmap-mdpi/ic_launcher.png b/src/ko/agitoon/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 15ea8b9ff..000000000 Binary files a/src/ko/agitoon/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/ko/agitoon/res/mipmap-xhdpi/ic_launcher.png b/src/ko/agitoon/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index a97a89d0d..000000000 Binary files a/src/ko/agitoon/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/ko/agitoon/res/mipmap-xxhdpi/ic_launcher.png b/src/ko/agitoon/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index f41de9c21..000000000 Binary files a/src/ko/agitoon/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/ko/agitoon/res/mipmap-xxxhdpi/ic_launcher.png b/src/ko/agitoon/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4e666aaa8..000000000 Binary files a/src/ko/agitoon/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/AgiToon.kt b/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/AgiToon.kt deleted file mode 100644 index 9033a0604..000000000 --- a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/AgiToon.kt +++ /dev/null @@ -1,218 +0,0 @@ -package eu.kanade.tachiyomi.extension.ko.agitoon - -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.FilterList -import eu.kanade.tachiyomi.source.model.MangasPage -import eu.kanade.tachiyomi.source.model.Page -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.source.online.HttpSource -import eu.kanade.tachiyomi.util.asJsoup -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.Request -import okhttp3.Response -import okio.IOException -import rx.Observable -import uy.kohesive.injekt.injectLazy -import kotlin.math.min -import kotlin.random.Random - -class AgiToon : HttpSource() { - - override val name = "아지툰" - - override val lang = "ko" - - private var currentBaseUrlHost = "" - override val baseUrl = "https://agitoon.in" - - private val cdnUrl = "https://blacktoonimg.com/" - - override val supportsLatest = true - - override val client = network.cloudflareClient.newBuilder().addInterceptor { chain -> - if (currentBaseUrlHost.isBlank()) { - noRedirectClient.newCall(GET(baseUrl, headers)).execute().use { - currentBaseUrlHost = it.headers["location"]?.toHttpUrlOrNull()?.host - ?: throw IOException("unable to get updated url") - } - } - - val request = chain.request().newBuilder().apply { - if (chain.request().url.toString().startsWith(baseUrl)) { - url( - chain.request().url.newBuilder() - .host(currentBaseUrlHost) - .build(), - ) - } - header("Referer", "https://$currentBaseUrlHost/") - header("Origin", "https://$currentBaseUrlHost") - }.build() - - return@addInterceptor chain.proceed(request) - }.build() - - private val noRedirectClient = network.cloudflareClient.newBuilder() - .followRedirects(false) - .build() - - private val json by injectLazy() - - private val db by lazy { - val doc = client.newCall(GET(baseUrl, headers)).execute().asJsoup() - doc.select("script[src*=data/webtoon]").flatMap { scriptEl -> - var listIdx: Int - client.newCall(GET(scriptEl.absUrl("src"), headers)) - .execute().body.string() - .also { - listIdx = it.substringBefore(" = ") - .substringAfter("data") - .toInt() - } - .substringAfter(" = ") - .removeSuffix(";") - .let { json.decodeFromString>(it) } - .onEach { it.listIndex = listIdx } - } - } - - private fun List.getPageChunk(page: Int): MangasPage { - return MangasPage( - mangas = subList((page - 1) * 24, min(page * 24, size)) - .map { it.toSManga(cdnUrl) }, - hasNextPage = (page + 1) * 24 <= size, - ) - } - - override fun fetchPopularManga(page: Int): Observable { - return Observable.just( - db.sortedByDescending { it.hot }.getPageChunk(page), - ) - } - - override fun fetchLatestUpdates(page: Int): Observable { - return Observable.just( - db.sortedByDescending { it.updatedAt }.getPageChunk(page), - ) - } - - override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { - var list = db - - if (query.isNotBlank()) { - val stdQuery = query.trim() - list = list.filter { - it.name.contains(stdQuery, true) || - it.author.contains(stdQuery, true) - } - } - - filters.filterIsInstance().forEach { - list = it.applyFilter(list) - } - - return Observable.just( - list.getPageChunk(page), - ) - } - - override fun getFilterList() = getFilters() - - override fun mangaDetailsRequest(manga: SManga): Request { - return GET("$baseUrl/azi_toon/${manga.url}.html#${manga.status}", headers) - } - - override fun getMangaUrl(manga: SManga): String { - return buildString { - if (currentBaseUrlHost.isBlank()) { - append(baseUrl) - } else { - append("https://") - append(currentBaseUrlHost) - } - append("/azi_toon/") - append(manga.url) - append(".html") - } - } - - override fun mangaDetailsParse(response: Response): SManga { - val doc = response.asJsoup() - return SManga.create().apply { - description = doc.select("p.mt-2").last()?.text() - thumbnail_url = doc.selectFirst("script:containsData(+img_domain+)")?.data()?.let { - cdnUrl + it.substringAfter("+'").substringBefore("'+") - } - status = response.request.url.fragment!!.toInt() - } - } - - override fun chapterListRequest(manga: SManga): Request { - val url = "$baseUrl/data/toonlist/${manga.url}.js?v=${"%.17f".format(Random.nextDouble())}" - - return GET(url, headers) - } - - override fun chapterListParse(response: Response): List { - val mangaId = response.request.url.pathSegments.last().removeSuffix(".js") - - val data = response.body.string() - .substringAfter(" = ") - .removeSuffix(";") - .let { json.decodeFromString>(it) } - - return data.map { it.toSChapter(mangaId) }.reversed() - } - - override fun getChapterUrl(chapter: SChapter): String { - return buildString { - if (currentBaseUrlHost.isBlank()) { - append(baseUrl) - } else { - append("https://") - append(currentBaseUrlHost) - } - append("/azi_toons/") - append(chapter.url) - append(".html") - } - } - - override fun pageListRequest(chapter: SChapter): Request { - return GET("$baseUrl/azi_toons/${chapter.url}.html", headers) - } - - override fun pageListParse(response: Response): List { - val document = response.asJsoup() - - return document.select("#toon_content_imgs img").map { - Page(0, imageUrl = cdnUrl + it.attr("o_src")) - } - } - - // unused - override fun popularMangaRequest(page: Int): Request { - throw UnsupportedOperationException() - } - override fun popularMangaParse(response: Response): MangasPage { - throw UnsupportedOperationException() - } - override fun latestUpdatesRequest(page: Int): Request { - throw UnsupportedOperationException() - } - override fun latestUpdatesParse(response: Response): MangasPage { - throw UnsupportedOperationException() - } - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - throw UnsupportedOperationException() - } - override fun searchMangaParse(response: Response): MangasPage { - throw UnsupportedOperationException() - } - override fun imageUrlParse(response: Response): String { - throw UnsupportedOperationException() - } -} diff --git a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Data.kt b/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Data.kt deleted file mode 100644 index 04e3b2b00..000000000 --- a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Data.kt +++ /dev/null @@ -1,57 +0,0 @@ -package eu.kanade.tachiyomi.extension.ko.agitoon - -val platformsMap = mapOf( - Pair(1, "네이버"), - Pair(2, "다음"), - Pair(3, "카카오"), - Pair(4, "레진"), - Pair(5, "투믹스"), - Pair(6, "탑툰"), - Pair(7, "코미카"), - Pair(8, "배틀코믹"), - Pair(9, "코믹GT"), - Pair(10, "케이툰"), - Pair(11, "애니툰"), - Pair(12, "폭스툰"), - Pair(13, "피너툰"), - Pair(14, "봄툰"), - Pair(15, "코미코"), - Pair(16, "무툰"), - Pair(17, "지존신마"), - Pair(99, "기타"), -) - -val tagsMap = mapOf( - Pair(1, "학원"), - Pair(2, "액션"), - Pair(3, "SF"), - Pair(4, "스토리"), - Pair(5, "판타지"), - Pair(6, "BL/백합"), - Pair(7, "개그/코미디"), - Pair(8, "연애/순정"), - Pair(9, "드라마"), - Pair(10, "로맨스"), - Pair(11, "시대극"), - Pair(12, "스포츠"), - Pair(13, "일상"), - Pair(14, "추리/미스터리"), - Pair(15, "공포/스릴러"), - Pair(16, "성인"), - Pair(17, "옴니버스"), - Pair(18, "에피소드"), - Pair(19, "무협"), - Pair(20, "소년"), - Pair(99, "기타"), -) - -val publishDayMap = mapOf( - Pair(1, "월"), - Pair(2, "화"), - Pair(3, "수"), - Pair(4, "목"), - Pair(5, "금"), - Pair(6, "토"), - Pair(7, "일"), - Pair(10, "열흘"), -) diff --git a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Dto.kt b/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Dto.kt deleted file mode 100644 index ed5fb19b9..000000000 --- a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Dto.kt +++ /dev/null @@ -1,84 +0,0 @@ -package eu.kanade.tachiyomi.extension.ko.agitoon - -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.source.model.SManga -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import java.text.ParseException -import java.text.SimpleDateFormat -import java.util.Locale - -@Serializable -class SeriesItem( - @SerialName("x") - private val id: String, - @SerialName("t") - val name: String, - @SerialName("p") - private val poster: String = "", - @SerialName("au") - val author: String = "", - @SerialName("g") - val updatedAt: Long = 0, - @SerialName("tag") - private val tagIds: String = "", - @SerialName("c") - private val platformId: String = "-1", - @SerialName("d") - private val publishDayId: String = "-1", - @SerialName("h") - val hot: Int = 0, -) { - val tag get() = tagIds.split(",") - .filter(String::isNotBlank) - .map(String::toInt) - - val platform get() = platformId.toInt() - - val publishDay get() = publishDayId.toInt() - - var listIndex = -1 - - fun toSManga(cdnUrl: String) = SManga.create().apply { - url = id - title = name - thumbnail_url = poster.takeIf { it.isNotBlank() }?.let { - cdnUrl + it.replace("_x4", "").replace("_x3", "") - } - genre = buildList { - add(platformsMap[platform]) - add(publishDayMap[publishDay]) - tag.forEach { - add(tagsMap[it]) - } - }.filterNotNull().joinToString() - author = this@SeriesItem.author - status = when (listIndex) { - 0 -> SManga.COMPLETED - 1 -> SManga.ONGOING - else -> SManga.UNKNOWN - } - } -} - -@Serializable -class Chapter( - @SerialName("id") - val id: String, - @SerialName("t") - val title: String, - @SerialName("d") - val date: String = "", -) { - fun toSChapter(mangaId: String) = SChapter.create().apply { - url = "$mangaId/$id" - name = title - date_upload = try { - dateFormat.parse(date)!!.time - } catch (_: ParseException) { - 0L - } - } -} - -private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) diff --git a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Filters.kt b/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Filters.kt deleted file mode 100644 index 8bf2e462f..000000000 --- a/src/ko/agitoon/src/eu/kanade/tachiyomi/extension/ko/agitoon/Filters.kt +++ /dev/null @@ -1,122 +0,0 @@ -package eu.kanade.tachiyomi.extension.ko.agitoon - -import eu.kanade.tachiyomi.source.model.Filter -import eu.kanade.tachiyomi.source.model.FilterList - -interface ListFilter { - fun applyFilter(list: List): List -} - -class TriFilter(name: String, val id: Int) : Filter.TriState(name) - -abstract class TriFilterGroup( - name: String, - values: Map, -) : Filter.Group(name, values.map { TriFilter(it.value, it.key) }), ListFilter { - private val included get() = state.filter { it.isIncluded() }.map { it.id } - private val excluded get() = state.filter { it.isExcluded() }.map { it.id } - - abstract fun SeriesItem.getAttribute(): List - override fun applyFilter(list: List): List { - return list.filter { series -> - included.all { - it in series.getAttribute() - } and excluded.all { - it !in series.getAttribute() - } - } - } -} - -abstract class SelectFilter( - name: String, - private val options: List>, -) : Filter.Select( - name, - options.map { it.second }.toTypedArray(), -) { - - val selected get() = options[state].first -} - -class TagFilter : TriFilterGroup("Tag", tagsMap) { - override fun SeriesItem.getAttribute(): List { - return tag - } -} - -class PlatformFilter : - SelectFilter( - "Platform", - buildList { - add(-1 to "") - platformsMap.forEach { - add(it.key to it.value) - } - }, - ), - ListFilter { - override fun applyFilter(list: List): List { - return list.filter { selected == -1 || it.platform == selected } - } -} - -class PublishDayFilter : - SelectFilter( - "Publishing Day", - buildList { - add(-1 to "") - publishDayMap.forEach { - add(it.key to it.value) - } - }, - ), - ListFilter { - override fun applyFilter(list: List): List { - return list.filter { selected == -1 || it.publishDay == state } - } -} - -class Status : - SelectFilter( - "Status", - listOf( - -1 to "All", - 1 to "연재", - 0 to "완결", - ), - ), - ListFilter { - override fun applyFilter(list: List): List { - return when (selected) { - 1, 0 -> list.filter { it.listIndex == selected } - else -> list - } - } -} - -class Order : - SelectFilter( - "Order by", - listOf( - 0 to "최신순", - 1 to "인기순", - ), - ), - ListFilter { - override fun applyFilter(list: List): List { - return when (selected) { - 0 -> list.sortedByDescending { it.updatedAt } - 1 -> list.sortedByDescending { it.hot } - else -> list - } - } -} - -fun getFilters() = FilterList( - Order(), - Status(), - PlatformFilter(), - PublishDayFilter(), - TagFilter(), -)