diff --git a/src/id/mangaku/build.gradle b/src/id/mangaku/build.gradle new file mode 100644 index 000000000..d6d00ef23 --- /dev/null +++ b/src/id/mangaku/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +ext { + appName = 'Tachiyomi: Mangaku' + pkgNameSuffix = 'id.mangaku' + extClass = '.Mangaku' + extVersionCode = 1 + libVersion = '1.2' +} + +apply from: "$rootDir/common.gradle" diff --git a/src/id/mangaku/res/mipmap-hdpi/ic_launcher.png b/src/id/mangaku/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 000000000..c8f53fb05 Binary files /dev/null and b/src/id/mangaku/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/id/mangaku/res/mipmap-mdpi/ic_launcher.png b/src/id/mangaku/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 000000000..800a8179f Binary files /dev/null and b/src/id/mangaku/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/id/mangaku/res/mipmap-xhdpi/ic_launcher.png b/src/id/mangaku/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 000000000..67d77e480 Binary files /dev/null and b/src/id/mangaku/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/id/mangaku/res/mipmap-xxhdpi/ic_launcher.png b/src/id/mangaku/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 000000000..cce3c5d1d Binary files /dev/null and b/src/id/mangaku/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/id/mangaku/res/mipmap-xxxhdpi/ic_launcher.png b/src/id/mangaku/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 000000000..1ba67d887 Binary files /dev/null and b/src/id/mangaku/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/id/mangaku/res/web_hi_res_512.png b/src/id/mangaku/res/web_hi_res_512.png new file mode 100755 index 000000000..6cd7c00f5 Binary files /dev/null and b/src/id/mangaku/res/web_hi_res_512.png differ diff --git a/src/id/mangaku/src/eu/kanade/tachiyomi/extension/id/mangaku/Mangaku.kt b/src/id/mangaku/src/eu/kanade/tachiyomi/extension/id/mangaku/Mangaku.kt new file mode 100644 index 000000000..6f35677e8 --- /dev/null +++ b/src/id/mangaku/src/eu/kanade/tachiyomi/extension/id/mangaku/Mangaku.kt @@ -0,0 +1,168 @@ +package eu.kanade.tachiyomi.extension.id.mangaku + +import android.annotation.SuppressLint +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Headers +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element + +class Mangaku : ParsedHttpSource() { + override val name = "Mangaku" + override val baseUrl = "https://mangaku.in/" + override val lang = "id" + override val supportsLatest = true + var searchQuery = "" + + override fun popularMangaRequest(page: Int): Request { + return GET(baseUrl + "daftar-komik-bahasa-indonesia/", headers) + } + + override fun latestUpdatesRequest(page: Int): Request { + return GET(baseUrl, headers) + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + searchQuery = query + return GET(baseUrl + "daftar-komik-bahasa-indonesia/", headers) + } + + override fun popularMangaSelector() = "a.screenshot" + override fun latestUpdatesSelector() = "div.kiri_anime div.utao" + override fun searchMangaSelector() = popularMangaSelector() + + override fun popularMangaFromElement(element: Element): SManga { + val manga = SManga.create() + manga.thumbnail_url = element.attr("rel") + manga.url = element.attr("href") + manga.title = element.text() + return manga + } + + override fun latestUpdatesFromElement(element: Element): SManga { + val manga = SManga.create() + manga.thumbnail_url = element.select("div.uta div.imgu img").attr("src") + + val mangaUrl = element.select("div.uta div.luf a.series").attr("href").replace("hhtps", "http") + manga.url = mangaUrl.replace("hhtps", "https") + manga.title = element.select("div.uta div.luf a.series").text() + return manga + } + + override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET(manga.url, headers) + } + + @SuppressLint("DefaultLocale") + override fun mangaDetailsParse(document: Document): SManga { + val infoString = document.select("#abc > p > span > small").html().toString().split("
") + val manga = SManga.create() + infoString.forEach { + if (it.contains("")) { + val info = it.split("") + val key = info[0].replace(":", "").replace("", "").trim().toLowerCase() + val value = info[1].replace(":", "").trim() + when (key) { + "genre" -> manga.genre = value.replace("–", ", ").replace("-", ", ").trim() + "author" -> manga.author = value + "artist" -> manga.artist = value + "sinopsis" -> manga.description = value + } + } + } + manga.status = SManga.UNKNOWN + manga.thumbnail_url = document.select("#abc > div > span > small > a > img").attr("src") + return manga + } + + override fun chapterListRequest(manga: SManga): Request { + return GET(manga.url, headers) + } + + override fun chapterListSelector() = "div.entry > div > table > tbody > tr > td:nth-child(1) > small > div:nth-child(2) > a" + override fun chapterFromElement(element: Element): SChapter { + val chapter = SChapter.create() + val chapterUrl = element.attr("href") + chapter.url = chapterUrl + chapter.name = element.text() + if (chapter.name.contains("–")) + chapter.name = chapter.name.split("–")[1].trim() + return chapter + } + + override fun prepareNewChapter(chapter: SChapter, manga: SManga) { + val basic = Regex("""Chapter\s([0-9]+)""") + when { + basic.containsMatchIn(chapter.name) -> { + basic.find(chapter.name)?.let { + chapter.chapter_number = it.groups[1]?.value!!.toFloat() + } + } + } + } + + override fun pageListRequest(chapter: SChapter): Request { + return GET(chapter.url, headers) + } + + override fun pageListParse(document: Document): List { + var pageList = document.select("div.entry img") + + if (pageList.isEmpty()) { + pageList = document.select("div.entry-content img") + } + + val pages = mutableListOf() + var i = 0 + pageList.forEach { element -> + val imageUrl = element.attr("src") + i++ + if (imageUrl.isNotEmpty()) { + pages.add(Page(i, "", imageUrl)) + } + } + return pages + } + + override fun imageUrlParse(document: Document) = "" + override fun imageRequest(page: Page): Request { + var mainUrl = baseUrl + var imageUrl = page.imageUrl.toString() + if (imageUrl.contains("mangaku.co")) { + mainUrl = "https://mangaku.co" + } + if (imageUrl.startsWith("//")) { + imageUrl = "https:" + imageUrl + } else if (imageUrl.startsWith("/")) { + imageUrl = mainUrl + imageUrl + } + val imgHeader = Headers.Builder().apply { + add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36") + add("referer", mainUrl) + }.build() + return GET(imageUrl, imgHeader) + } + + override fun popularMangaNextPageSelector() = "next" + override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() + override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() + + @SuppressLint("DefaultLocale") + override fun searchMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + val mangas = arrayListOf() + document.select(searchMangaSelector()).forEach { element -> + val manga = popularMangaFromElement(element) + if (manga.title.toLowerCase().contains(searchQuery.toLowerCase())) { + mangas.add(manga) + } + } + return MangasPage(mangas, false) + } +}