diff --git a/src/all/mangadex/build.gradle b/src/all/mangadex/build.gradle index b908954a8..c9f49c893 100644 --- a/src/all/mangadex/build.gradle +++ b/src/all/mangadex/build.gradle @@ -5,8 +5,8 @@ ext { appName = 'Tachiyomi: MangaDex' pkgNameSuffix = 'all.mangadex' extClass = '.MangadexFactory' - extVersionCode = 32 - extVersionSuffix = 32 + extVersionCode = 33 + extVersionSuffix = 33 libVersion = '1.2' } diff --git a/src/all/mangadex/res/mipmap-hdpi/ic_launcher.png b/src/all/mangadex/res/mipmap-hdpi/ic_launcher.png index 1aec356ae..3239b43c1 100644 Binary files a/src/all/mangadex/res/mipmap-hdpi/ic_launcher.png and b/src/all/mangadex/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/all/mangadex/res/mipmap-mdpi/ic_launcher.png b/src/all/mangadex/res/mipmap-mdpi/ic_launcher.png index 7eab9d073..66b056d6c 100644 Binary files a/src/all/mangadex/res/mipmap-mdpi/ic_launcher.png and b/src/all/mangadex/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/all/mangadex/res/mipmap-xhdpi/ic_launcher.png b/src/all/mangadex/res/mipmap-xhdpi/ic_launcher.png index 4d1fbca31..c09a86a5a 100644 Binary files a/src/all/mangadex/res/mipmap-xhdpi/ic_launcher.png and b/src/all/mangadex/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/all/mangadex/res/mipmap-xxhdpi/ic_launcher.png b/src/all/mangadex/res/mipmap-xxhdpi/ic_launcher.png index 3670dfb76..02500ce5b 100644 Binary files a/src/all/mangadex/res/mipmap-xxhdpi/ic_launcher.png and b/src/all/mangadex/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/all/mangadex/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/mangadex/res/mipmap-xxxhdpi/ic_launcher.png index 74297ab03..8c8fbdfeb 100644 Binary files a/src/all/mangadex/res/mipmap-xxxhdpi/ic_launcher.png and b/src/all/mangadex/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/Mangadex.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/Mangadex.kt index d618a5fdf..e156a6989 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/Mangadex.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/Mangadex.kt @@ -53,7 +53,6 @@ open class Mangadex(override val lang: String, private val internalLang: String, .request() .newBuilder() .addHeader("Cookie", cookiesHeader(r18Toggle, langCode)) - .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)") .build() chain.proceed(newReq) }.build()!! @@ -154,17 +153,21 @@ open class Mangadex(override val lang: String, private val internalLang: String, override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { val byGenre = filters.find { it is GenreList } - val genres = mutableListOf<String>() + val genresToInclude = mutableListOf<String>() + val genresToExclude = mutableListOf<String>() + if (byGenre != null) { byGenre as GenreList byGenre.state.forEach { genre -> - when (genre.state) { - true -> genres.add(genre.id) + if (genre.isExcluded()) { + genresToExclude.add(genre.id) + } else if (genre.isIncluded()) { + genresToInclude.add(genre.id) } } } //do traditional search - val url = HttpUrl.parse("$baseUrl/?page=search")!!.newBuilder().addQueryParameter("p", page.toString()).addQueryParameter("title", query.replace(whitespaceRegex, " ")) + val url = HttpUrl.parse("$baseUrl/?page=search")!!.newBuilder().addQueryParameter("s", "0").addQueryParameter("p", page.toString()).addQueryParameter("title", query.replace(whitespaceRegex, " ")) filters.forEach { filter -> when (filter) { is TextField -> url.addQueryParameter(filter.key, filter.state) @@ -173,11 +176,20 @@ open class Mangadex(override val lang: String, private val internalLang: String, url.addQueryParameter("demo", filter.state.toString()) } } + is OriginalLanguage -> { + if (filter.state != 0) { + val number: String = SOURCE_LANG_LIST.first { it -> it.first == filter.values[filter.state] }?.second + url.addQueryParameter("source_lang", number) + } + } } } - if (genres.isNotEmpty()) { - url.addQueryParameter("genres", genres.joinToString(",")) + if (genresToInclude.isNotEmpty()) { + url.addQueryParameter("genres_inc", genresToInclude.joinToString(",")) + } + if (genresToExclude.isNotEmpty()) { + url.addQueryParameter("genres_exc", genresToExclude.joinToString(",")) } return GET(url.toString(), headers) @@ -208,7 +220,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, } private fun apiRequest(manga: SManga): Request { - return GET(baseUrl + URL + getMangaId(manga.url), headers) + return GET(baseUrl + API_MANGA + getMangaId(manga.url), headers) } private fun getMangaId(url: String): String { @@ -244,7 +256,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, var genres = mutableListOf<String>() mangaJson.get("genres").asJsonArray.forEach { id -> - getGenreList().find { it -> it.id == id.string }?.let { genre -> + GENRE_LIST.find { it -> it.id == id.string }?.let { genre -> genres.add(genre.name) } } @@ -287,7 +299,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, override fun chapterListParse(response: Response): List<SChapter> { val now = Date().time - var jsonData = response.body()!!.string() + val jsonData = response.body()!!.string() val json = JsonParser().parse(jsonData).asJsonObject val mangaJson = json.getAsJsonObject("manga") val status = mangaJson.get("status").int @@ -310,8 +322,8 @@ open class Mangadex(override val lang: String, private val internalLang: String, private fun chapterFromJson(chapterId: String, chapterJson: JsonObject, finalChapterNumber: String, status: Int): SChapter { val chapter = SChapter.create() - chapter.url = BASE_CHAPTER + chapterId - var chapterName = mutableListOf<String>() + chapter.url = API_CHAPTER + chapterId + val chapterName = mutableListOf<String>() //build chapter name if (chapterJson.get("volume").string.isNotBlank()) { chapterName.add("Vol." + chapterJson.get("volume").string) @@ -342,7 +354,7 @@ open class Mangadex(override val lang: String, private val internalLang: String, if (!chapterJson.get("group_name_3").nullString.isNullOrBlank()) { scanlatorName.add(chapterJson.get("group_name_3").string) } - chapter.scanlator = scanlatorName.joinToString(" & ") + chapter.scanlator = cleanString(scanlatorName.joinToString(" & ")) return chapter @@ -350,15 +362,20 @@ open class Mangadex(override val lang: String, private val internalLang: String, override fun chapterFromElement(element: Element) = throw Exception("Not used") - override fun pageListParse(document: Document): List<Page> { - val pages = mutableListOf<Page>() - val dataUrl = document.select("script").last().html().substringAfter("dataurl = '").substringBefore("';") - val imageUrl = document.select("script").last().html().substringAfter("page_array = [").substringBefore("];") - val listImageUrls = imageUrl.replace("'", "").split(",") - val server = document.select("script").last().html().substringAfter("server = '").substringBefore("';") + override fun pageListParse(document: Document) = throw Exception("Not used") - listImageUrls.filter { it.isNotBlank() }.forEach { - val url = "$server$dataUrl/$it" + override fun pageListParse(response: Response): List<Page> { + var jsonData = response.body()!!.string() + val json = JsonParser().parse(jsonData).asJsonObject + + val pages = mutableListOf<Page>() + + val hash = json.get("hash").string + val pageArray = json.getAsJsonArray("page_array") + val server = json.get("server").string + + pageArray.forEach { + val url = "$server$hash/$it" pages.add(Page(pages.size, "", getImageUrl(url))) } @@ -403,64 +420,23 @@ open class Mangadex(override val lang: String, private val internalLang: String, private class TextField(name: String, val key: String) : Filter.Text(name) - private class Genre(val id: String, name: String) : Filter.CheckBox(name) + private class Genre(val id: String, name: String) : Filter.TriState(name) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) private class R18 : Filter.Select<String>("R18+", arrayOf("Show all", "Show only", "Show none")) private class Demographic : Filter.Select<String>("Demographic", arrayOf("All", "Shounen", "Shoujo", "Seinen", "Josei")) + private class OriginalLanguage : Filter.Select<String>("Original Language", SOURCE_LANG_LIST.map { it -> it.first }.toTypedArray()) + override fun getFilterList() = FilterList( TextField("Author", "author"), TextField("Artist", "artist"), R18(), Demographic(), - GenreList(getGenreList()) + OriginalLanguage(), + GenreList(GENRE_LIST) ) - private fun getGenreList() = listOf( - Genre("1", "4-koma"), - Genre("2", "Action"), - Genre("3", "Adventure"), - Genre("4", "Award Winning"), - Genre("5", "Comedy"), - Genre("6", "Cooking"), - Genre("7", "Doujinshi"), - Genre("8", "Drama"), - Genre("9", "Ecchi"), - Genre("10", "Fantasy"), - Genre("11", "Gender Bender"), - Genre("12", "Harem"), - Genre("13", "Historical"), - Genre("14", "Horror"), - Genre("15", "Josei"), - Genre("16", "Martial Arts"), - Genre("17", "Mecha"), - Genre("18", "Medical"), - Genre("19", "Music"), - Genre("20", "Mystery"), - Genre("21", "Oneshot"), - Genre("22", "Psychological"), - Genre("23", "Romance"), - Genre("24", "School Life"), - Genre("25", "Sci-Fi"), - Genre("26", "Seinen"), - Genre("27", "Shoujo"), - Genre("28", "Shoujo Ai"), - Genre("29", "Shounen"), - Genre("30", "Shounen Ai"), - Genre("31", "Slice of Life"), - Genre("32", "Smut"), - Genre("33", "Sports"), - Genre("34", "Supernatural"), - Genre("35", "Tragedy"), - Genre("36", "Webtoon"), - Genre("37", "Yaoi"), - Genre("38", "Yuri"), - Genre("39", "[no chapters]"), - Genre("40", "Game"), - Genre("41", "Isekai") - ) - companion object { //this number matches to the cookie private const val NO_R18 = 0 @@ -468,8 +444,65 @@ open class Mangadex(override val lang: String, private val internalLang: String, private const val ONLY_R18 = 2 private const val SHOW_R18_PREF_Title = "Default R18 Setting" private const val SHOW_R18_PREF = "showR18Default" - private const val URL = "/api/3640f3fb/" - private const val BASE_CHAPTER = "/chapter/" + private const val API_MANGA = "/api/manga/" + private const val API_CHAPTER = "/api/chapter/" + private val SOURCE_LANG_LIST = listOf( + Pair("All", "0"), + Pair("Japanese", "2"), + Pair("English", "1"), + Pair("Polish", "3"), + Pair("German", "8"), + Pair("French", "10"), + Pair("Vietnamese", "12"), + Pair("Chinese", "21"), + Pair("Indonesian", "27"), + Pair("Korean", "28"), + Pair("Spanish (LATAM)", "29"), + Pair("Thai", "32"), + Pair("Filipino", "34") + ) + private val GENRE_LIST = listOf( + Genre("1", "4-koma"), + Genre("2", "Action"), + Genre("3", "Adventure"), + Genre("4", "Award Winning"), + Genre("5", "Comedy"), + Genre("6", "Cooking"), + Genre("7", "Doujinshi"), + Genre("8", "Drama"), + Genre("9", "Ecchi"), + Genre("10", "Fantasy"), + Genre("11", "Gender Bender"), + Genre("12", "Harem"), + Genre("13", "Historical"), + Genre("14", "Horror"), + Genre("15", "Josei"), + Genre("16", "Martial Arts"), + Genre("17", "Mecha"), + Genre("18", "Medical"), + Genre("19", "Music"), + Genre("20", "Mystery"), + Genre("21", "Oneshot"), + Genre("22", "Psychological"), + Genre("23", "Romance"), + Genre("24", "School Life"), + Genre("25", "Sci-Fi"), + Genre("26", "Seinen"), + Genre("27", "Shoujo"), + Genre("28", "Shoujo Ai"), + Genre("29", "Shounen"), + Genre("30", "Shounen Ai"), + Genre("31", "Slice of Life"), + Genre("32", "Smut"), + Genre("33", "Sports"), + Genre("34", "Supernatural"), + Genre("35", "Tragedy"), + Genre("36", "Webtoon"), + Genre("37", "Yaoi"), + Genre("38", "Yuri"), + Genre("39", "[no chapters]"), + Genre("40", "Game"), + Genre("41", "Isekai")) } }