Forráskód Böngészése

Remove batoto from catalogues

inorichi 7 éve
szülő
commit
183e83684a

+ 11 - 367
app/src/main/java/eu/kanade/tachiyomi/source/online/english/Batoto.kt

@@ -1,383 +1,27 @@
 package eu.kanade.tachiyomi.source.online.english
 
-import android.text.Html
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.POST
-import eu.kanade.tachiyomi.network.asObservable
-import eu.kanade.tachiyomi.source.model.*
-import eu.kanade.tachiyomi.source.online.LoginSource
-import eu.kanade.tachiyomi.source.online.ParsedHttpSource
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.selectText
-import okhttp3.*
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
+import eu.kanade.tachiyomi.source.Source
+import eu.kanade.tachiyomi.source.model.Page
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
 import rx.Observable
-import uy.kohesive.injekt.injectLazy
-import java.net.URI
-import java.text.ParseException
-import java.text.SimpleDateFormat
-import java.util.*
-import java.util.regex.Pattern
 
-class Batoto : ParsedHttpSource(), LoginSource {
-
-    // TODO remove
-    private val preferences: PreferencesHelper by injectLazy()
+class Batoto : Source {
 
     override val id: Long = 1
 
     override val name = "Batoto"
 
-    override val baseUrl = "https://bato.to"
-
-    override val lang = "en"
-
-    override val supportsLatest = true
-
-    private val datePattern = Pattern.compile("(\\d+|A|An)\\s+(.*?)s? ago.*")
-
-    private val dateFields = HashMap<String, Int>().apply {
-        put("second", Calendar.SECOND)
-        put("minute", Calendar.MINUTE)
-        put("hour", Calendar.HOUR)
-        put("day", Calendar.DATE)
-        put("week", Calendar.WEEK_OF_YEAR)
-        put("month", Calendar.MONTH)
-        put("year", Calendar.YEAR)
-    }
-
-    private val staffNotice = Pattern.compile("=+Batoto Staff Notice=+([^=]+)==+", Pattern.CASE_INSENSITIVE)
-
-    override val client: OkHttpClient = network.cloudflareClient
-
-    override fun headersBuilder() = super.headersBuilder()
-            .add("Cookie", "lang_option=English")
-
-    private val pageHeaders = super.headersBuilder()
-            .add("Referer", "$baseUrl/reader")
-            .build()
-
-    override fun popularMangaRequest(page: Int): Request {
-        return GET("$baseUrl/search_ajax?order_cond=views&order=desc&p=$page", headers)
-    }
-
-    override fun latestUpdatesRequest(page: Int): Request {
-        return GET("$baseUrl/search_ajax?order_cond=update&order=desc&p=$page", headers)
-    }
-
-    override fun popularMangaSelector() = "tr:has(a)"
-
-    override fun latestUpdatesSelector() = "tr:has(a)"
-
-    override fun popularMangaFromElement(element: Element): SManga {
-        val manga = SManga.create()
-        element.select("a[href*=bato.to]").first().let {
-            manga.setUrlWithoutDomain(it.attr("href"))
-            manga.title = it.text().trim()
-        }
-        return manga
-    }
-
-    override fun latestUpdatesFromElement(element: Element): SManga {
-        return popularMangaFromElement(element)
-    }
-
-    override fun popularMangaNextPageSelector() = "#show_more_row"
-
-    override fun latestUpdatesNextPageSelector() = "#show_more_row"
-
-    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
-        val url = HttpUrl.parse("$baseUrl/search_ajax")!!.newBuilder()
-        if (!query.isEmpty()) url.addQueryParameter("name", query).addQueryParameter("name_cond", "c")
-        var genres = ""
-        filters.forEach { filter ->
-            when (filter) {
-                is Status -> if (!filter.isIgnored()) {
-                    url.addQueryParameter("completed", if (filter.isExcluded()) "i" else "c")
-                }
-                is GenreList -> {
-                    filter.state.forEach { filter ->
-                        when (filter) {
-                            is Genre -> if (!filter.isIgnored()) {
-                                genres += (if (filter.isExcluded()) ";e" else ";i") + filter.id
-                            }
-                            is SelectField -> {
-                                val sel = filter.values[filter.state].value
-                                if (!sel.isEmpty()) url.addQueryParameter(filter.key, sel)
-                            }
-                        }
-                    }
-                }
-                is TextField -> {
-                    if (!filter.state.isEmpty()) url.addQueryParameter(filter.key, filter.state)
-                }
-                is SelectField -> {
-                    val sel = filter.values[filter.state].value
-                    if (!sel.isEmpty()) url.addQueryParameter(filter.key, sel)
-                }
-                is Flag -> {
-                    val sel = if (filter.state) filter.valTrue else filter.valFalse
-                    if (!sel.isEmpty()) url.addQueryParameter(filter.key, sel)
-                }
-                is OrderBy -> {
-                    url.addQueryParameter("order_cond", arrayOf("title", "author", "artist", "rating", "views", "update")[filter.state!!.index])
-                    url.addQueryParameter("order", if (filter.state?.ascending == true) "asc" else "desc")
-                }
-            }
-        }
-        if (!genres.isEmpty()) url.addQueryParameter("genres", genres)
-        url.addQueryParameter("p", page.toString())
-        return GET(url.toString(), headers)
-    }
-
-    override fun searchMangaSelector() = popularMangaSelector()
-
-    override fun searchMangaFromElement(element: Element): SManga {
-        return popularMangaFromElement(element)
-    }
-
-    override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
-
-    override fun mangaDetailsRequest(manga: SManga): Request {
-        val mangaId = manga.url.substringAfterLast("r")
-        return GET("$baseUrl/comic_pop?id=$mangaId", headers)
-    }
-
-    override fun mangaDetailsParse(document: Document): SManga {
-        val tbody = document.select("tbody").first()
-        val artistElement = tbody.select("tr:contains(Author/Artist:)").first()
-
-        val manga = SManga.create()
-        manga.author = artistElement.selectText("td:eq(1)")
-        manga.artist = artistElement.selectText("td:eq(2)") ?: manga.author
-        manga.description = tbody.selectText("tr:contains(Description:) > td:eq(1)")
-        manga.thumbnail_url = document.select("img[src^=http://img.bato.to/forums/uploads/]").first()?.attr("src")
-        manga.status = parseStatus(document.selectText("tr:contains(Status:) > td:eq(1)"))
-        manga.genre = tbody.select("tr:contains(Genres:) img").map { it.attr("alt") }.joinToString(", ")
-        return manga
-    }
-
-    private fun parseStatus(status: String?) = when (status) {
-        "Ongoing" -> SManga.ONGOING
-        "Complete" -> SManga.COMPLETED
-        else -> SManga.UNKNOWN
-    }
-
-    override fun chapterListRequest(manga: SManga): Request {
-        // Https is currently very slow. The replace also saves a redirection.
-        var newUrl = "http://bato.to" + manga.url
-        if ("/comic/_/comics/" !in newUrl) {
-            newUrl = newUrl.replace("/comic/_/", "/comic/_/comics/")
-        }
-
-        return super.chapterListRequest(manga).newBuilder()
-                .url(newUrl)
-                .build()
-    }
-
-    override fun chapterListParse(response: Response): List<SChapter> {
-        val body = response.body()!!.string()
-        val matcher = staffNotice.matcher(body)
-        if (matcher.find()) {
-            @Suppress("DEPRECATION")
-            val notice = Html.fromHtml(matcher.group(1)).toString().trim()
-            throw Exception(notice)
-        }
-
-        val document = response.asJsoup(body)
-        return document.select(chapterListSelector()).map { chapterFromElement(it) }
-    }
-
-    override fun chapterListSelector() = "tr.row.lang_English.chapter_row"
-
-    override fun chapterFromElement(element: Element): SChapter {
-        val urlElement = element.select("a[href*=bato.to/reader").first()
-
-        val chapter = SChapter.create()
-        chapter.setUrlWithoutDomain(urlElement.attr("href"))
-        chapter.name = urlElement.text()
-        chapter.date_upload = element.select("td").getOrNull(4)?.let {
-            parseDateFromElement(it)
-        } ?: 0
-        chapter.scanlator = element.select("td").getOrNull(2)?.text()
-        return chapter
-    }
-
-    private fun parseDateFromElement(dateElement: Element): Long {
-        val dateAsString = dateElement.text()
-
-        var date: Date
-        try {
-            date = SimpleDateFormat("dd MMMMM yyyy - hh:mm a", Locale.ENGLISH).parse(dateAsString)
-        } catch (e: ParseException) {
-            val m = datePattern.matcher(dateAsString)
-
-            if (m.matches()) {
-                val number = m.group(1)
-                val amount = if (number.contains("A")) 1 else Integer.parseInt(m.group(1))
-                val unit = m.group(2)
-
-                date = Calendar.getInstance().apply {
-                    add(dateFields[unit]!!, -amount)
-                }.time
-            } else {
-                return 0
-            }
-        }
-
-        return date.time
-    }
-
-    override fun pageListRequest(chapter: SChapter): Request {
-        val id = chapter.url.substringAfterLast("#")
-        return GET("$baseUrl/areader?id=$id&p=1", pageHeaders)
-    }
-
-    override fun pageListParse(document: Document): List<Page> {
-        val pages = mutableListOf<Page>()
-        val selectElement = document.select("#page_select").first()
-        if (selectElement != null) {
-            for ((i, element) in selectElement.select("option").withIndex()) {
-                pages.add(Page(i, element.attr("value")))
-            }
-            pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
-        } else {
-            // For webtoons in one page
-            for ((i, element) in document.select("div > img").withIndex()) {
-                pages.add(Page(i, "", element.attr("src")))
-            }
-        }
-        return pages
-    }
-
-    override fun imageUrlRequest(page: Page): Request {
-        val pageUrl = page.url
-        val start = pageUrl.indexOf("#") + 1
-        val end = pageUrl.indexOf("_", start)
-        val id = pageUrl.substring(start, end)
-        return GET("$baseUrl/areader?id=$id&p=${pageUrl.substring(end + 1)}", pageHeaders)
-    }
-
-    override fun imageUrlParse(document: Document): String {
-        return document.select("#comic_page").first().attr("src")
-    }
-
-    override fun login(username: String, password: String) =
-            client.newCall(GET("$baseUrl/forums/index.php?app=core&module=global&section=login", headers))
-                    .asObservable()
-                    .flatMap { doLogin(it, username, password) }
-                    .map { isAuthenticationSuccessful(it) }
-
-    private fun doLogin(response: Response, username: String, password: String): Observable<Response> {
-        val doc = response.asJsoup()
-        val form = doc.select("#login").first()
-        val url = form.attr("action")
-        val authKey = form.select("input[name=auth_key]").first()
-
-        val payload = FormBody.Builder().apply {
-            add(authKey.attr("name"), authKey.attr("value"))
-            add("ips_username", username)
-            add("ips_password", password)
-            add("invisible", "1")
-            add("rememberMe", "1")
-        }.build()
-
-        return client.newCall(POST(url, headers, payload)).asObservable()
-    }
-
-    override fun isAuthenticationSuccessful(response: Response) =
-            response.priorResponse() != null && response.priorResponse()!!.code() == 302
-
-    override fun isLogged(): Boolean {
-        return network.cookies.get(URI(baseUrl)).any { it.name() == "pass_hash" }
+    override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
+        return Observable.error(Exception("RIP Batoto"))
     }
 
     override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
-        if (!isLogged()) {
-            val username = preferences.sourceUsername(this)
-            val password = preferences.sourcePassword(this)
-
-            if (username.isNullOrEmpty() || password.isNullOrEmpty()) {
-                return Observable.error(Exception("User not logged"))
-            } else {
-                return login(username, password).flatMap { super.fetchChapterList(manga) }
-            }
-
-        } else {
-            return super.fetchChapterList(manga)
-        }
+        return Observable.error(Exception("RIP Batoto"))
     }
 
-    private data class ListValue(val name: String, val value: String) {
-        override fun toString(): String = name
+    override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
+        return Observable.error(Exception("RIP Batoto"))
     }
 
-    private class Status : Filter.TriState("Completed")
-    private class Genre(name: String, val id: Int) : Filter.TriState(name)
-    private class TextField(name: String, val key: String) : Filter.Text(name)
-    private class SelectField(name: String, val key: String, values: Array<ListValue>, state: Int = 0) : Filter.Select<ListValue>(name, values, state)
-    private class Flag(name: String, val key: String, val valTrue: String, val valFalse: String) : Filter.CheckBox(name)
-    private class GenreList(genres: List<Filter<*>>) : Filter.Group<Filter<*>>("Genres", genres)
-    private class OrderBy : Filter.Sort("Order by",
-            arrayOf("Title", "Author", "Artist", "Rating", "Views", "Last Update"),
-            Filter.Sort.Selection(4, false))
-
-    override fun getFilterList() = FilterList(
-            TextField("Author", "artist_name"),
-            SelectField("Type", "type", arrayOf(ListValue("Any", ""), ListValue("Manga (Jp)", "jp"), ListValue("Manhwa (Kr)", "kr"), ListValue("Manhua (Cn)", "cn"), ListValue("Artbook", "ar"), ListValue("Other", "ot"))),
-            Status(),
-            Flag("Exclude mature", "mature", "m", ""),
-            OrderBy(),
-            GenreList(getGenreList())
-    )
-
-    // [...document.querySelectorAll("#advanced_options div.genre_buttons")].map((el,i) => {
-    //     const onClick=el.getAttribute('onclick');const id=onClick.substr(14,onClick.length-16);return `Genre("${el.textContent.trim()}", ${id})`
-    // }).join(',\n')
-    // on https://bato.to/search
-    private fun getGenreList() = listOf(
-            SelectField("Inclusion mode", "genre_cond", arrayOf(ListValue("And (all selected genres)", "and"), ListValue("Or (any selected genres) ", "or"))),
-            Genre("4-Koma", 40),
-            Genre("Action", 1),
-            Genre("Adventure", 2),
-            Genre("Award Winning", 39),
-            Genre("Comedy", 3),
-            Genre("Cooking", 41),
-            Genre("Doujinshi", 9),
-            Genre("Drama", 10),
-            Genre("Ecchi", 12),
-            Genre("Fantasy", 13),
-            Genre("Gender Bender", 15),
-            Genre("Harem", 17),
-            Genre("Historical", 20),
-            Genre("Horror", 22),
-            Genre("Josei", 34),
-            Genre("Martial Arts", 27),
-            Genre("Mecha", 30),
-            Genre("Medical", 42),
-            Genre("Music", 37),
-            Genre("Mystery", 4),
-            Genre("Oneshot", 38),
-            Genre("Psychological", 5),
-            Genre("Romance", 6),
-            Genre("School Life", 7),
-            Genre("Sci-fi", 8),
-            Genre("Seinen", 32),
-            Genre("Shoujo", 35),
-            Genre("Shoujo Ai", 16),
-            Genre("Shounen", 33),
-            Genre("Shounen Ai", 19),
-            Genre("Slice of Life", 21),
-            Genre("Smut", 23),
-            Genre("Sports", 25),
-            Genre("Supernatural", 26),
-            Genre("Tragedy", 28),
-            Genre("Webtoon", 36),
-            Genre("Yaoi", 29),
-            Genre("Yuri", 31),
-            Genre("[no chapters]", 44)
-    )
-
-}
+}