diff --git a/src/ja/rawlh/build.gradle b/src/ja/rawlh/build.gradle new file mode 100644 index 000000000..b861437f6 --- /dev/null +++ b/src/ja/rawlh/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +ext { + appName = 'Tachiyomi: RawLH' + pkgNameSuffix = "ja.rawlh" + extClass = '.Rawlh' + extVersionCode = 1 + extVersionSuffix = 0 + libVersion = '1.0' +} + +apply from: "$rootDir/common.gradle" diff --git a/src/ja/rawlh/res/mipmap-hdpi/ic_launcher.png b/src/ja/rawlh/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..2264ff3e0 Binary files /dev/null and b/src/ja/rawlh/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/ja/rawlh/res/mipmap-mdpi/ic_launcher.png b/src/ja/rawlh/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..9e11619f5 Binary files /dev/null and b/src/ja/rawlh/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/ja/rawlh/res/mipmap-xhdpi/ic_launcher.png b/src/ja/rawlh/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..32a260391 Binary files /dev/null and b/src/ja/rawlh/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/ja/rawlh/res/mipmap-xxhdpi/ic_launcher.png b/src/ja/rawlh/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..66ed9c9f1 Binary files /dev/null and b/src/ja/rawlh/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/ja/rawlh/res/mipmap-xxxhdpi/ic_launcher.png b/src/ja/rawlh/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..97c726e7d Binary files /dev/null and b/src/ja/rawlh/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/ja/rawlh/res/web_hi_res_512.png b/src/ja/rawlh/res/web_hi_res_512.png new file mode 100644 index 000000000..832f5b54a Binary files /dev/null and b/src/ja/rawlh/res/web_hi_res_512.png differ diff --git a/src/ja/rawlh/src/eu/kanade/tachiyomi/extension/ja/rawlh/Rawlh.kt b/src/ja/rawlh/src/eu/kanade/tachiyomi/extension/ja/rawlh/Rawlh.kt new file mode 100644 index 000000000..348b7ff9c --- /dev/null +++ b/src/ja/rawlh/src/eu/kanade/tachiyomi/extension/ja/rawlh/Rawlh.kt @@ -0,0 +1,195 @@ +package eu.kanade.tachiyomi.extension.ja.rawlh + +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import okhttp3.HttpUrl +import okhttp3.Request +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element + +class Rawlh : ParsedHttpSource() { + + override val name = "RawLH" + + override val baseUrl = "http://rawlh.com" + + override val lang = "ja" + + override val supportsLatest = true + + override fun popularMangaRequest(page: Int): Request = + GET("$baseUrl/manga-list.html?listType=pagination&page=$page&artist=&author=&group=&m_status=&name=&genre=&ungenre=&sort=views&sort_type=DESC", headers) + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val url = HttpUrl.parse("$baseUrl/manga-list.html?")!!.newBuilder().addQueryParameter("name", query) + (if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> + when (filter) { + is Status -> { + val status = arrayOf("", "1", "2")[filter.state] + url.addQueryParameter("m_status", status) + } + is TextField -> url.addQueryParameter(filter.key, filter.state) + is GenreList -> { + + var genre = String() + var ungenre = String() + + filter.state.forEach { + if (it.isIncluded()) genre += ",${it.name}" + if (it.isExcluded()) ungenre += ",${it.name}" + } + url.addQueryParameter("genre", genre) + url.addQueryParameter("ungenre", ungenre) + } + } + } + return GET(url.toString(), headers) + } + + override fun latestUpdatesRequest(page: Int): Request = + GET("$baseUrl/manga-list.html?listType=pagination&page=$page&artist=&author=&group=&m_status=&name=&genre=&sort=last_update&sort_type=DESC") + + override fun popularMangaSelector() = "div.media" + + override fun latestUpdatesSelector() = popularMangaSelector() + + override fun searchMangaSelector() = popularMangaSelector() + + override fun popularMangaFromElement(element: Element): SManga { + val manga = SManga.create() + element.select("h3 > a").first().let { + manga.setUrlWithoutDomain("/" + it.attr("href")) + manga.title = it.text() + } + return manga + } + + override fun latestUpdatesFromElement(element: Element): SManga = + popularMangaFromElement(element) + + override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element) + + override fun popularMangaNextPageSelector() = "a:contains(ยป)" + + override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() + + override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() + + private fun searchGenresNextPageSelector() = popularMangaNextPageSelector() + + + override fun mangaDetailsParse(document: Document): SManga { + val manga = SManga.create() + val infoElement = document.select("div.row").first() + manga.author = infoElement.select("small a.btn.btn-xs.btn-info").first()?.text() + manga.genre = infoElement.select("ul.manga-info li:nth-child(3) small").first()?.text() + manga.status = parseStatus(infoElement.select("a.btn.btn-xs.btn-success").first().text()) + + manga.description = document.select("div.row > p").first()?.text() + val imgUrl = document.select("img.thumbnail").first()?.attr("src") + if (imgUrl!!.startsWith("app/")) { + manga.thumbnail_url = "$baseUrl/$imgUrl" + } else { + manga.thumbnail_url = imgUrl + } + return manga + } + + private fun parseStatus(element: String): Int = when { + element.contains("Completed") -> SManga.COMPLETED + element.contains("Ongoing") -> SManga.ONGOING + else -> SManga.UNKNOWN + } + + override fun chapterListSelector() = " table.table.table-hover tbody tr" + + override fun chapterFromElement(element: Element): SChapter { + val urlElement = element.select("td a").first() + + val chapter = SChapter.create() + chapter.setUrlWithoutDomain("/" + urlElement.attr("href")) + chapter.name = urlElement.text() + chapter.date_upload = 0 + return chapter + } + + + override fun pageListParse(document: Document): List { + val pages = mutableListOf() + document.select("img.chapter-img").forEach { + val url = it.attr("src") + if (url != "") { + pages.add(Page(pages.size, "", url)) + } + } + return pages + } + + override fun imageUrlParse(document: Document) = "" + + private class TextField(name: String, val key: String) : Filter.Text(name) + private class Status : Filter.Select("Status", arrayOf("Any", "Completed", "Ongoing")) + private class GenreList(genres: List) : Filter.Group("Genre", genres) + private class Genre(name: String, val id: String = name.replace(' ', '+')) : Filter.TriState(name) + + // TODO: Country + override fun getFilterList() = FilterList( + TextField("Author", "author"), + TextField("Group", "group"), + Status(), + GenreList(getGenreList()) + ) + + /* [...document.querySelectorAll("div.panel-body a")].map((el,i) => + * { return `Genre("${el.innerHTML}")` }).join(',\n') + * on http://rawlh.com/search + */ + private fun getGenreList() = listOf( + Genre("4-Koma"), + Genre("Action"), + Genre("Adult"), + Genre("Adventure"), + Genre("Isekai"), + Genre("Comedy"), + Genre("Comic"), + Genre("Cooking"), + Genre("Doujinshi"), + Genre("Drama"), + Genre("Ecchi"), + Genre("Fantasy"), + Genre("Gender Bender"), + Genre("Harem"), + Genre("Historical"), + Genre("Horror"), + Genre("Josei"), + Genre("Lolicon"), + Genre("Manga"), + Genre("Manhua"), + Genre("Manhwa"), + Genre("Martial Art"), + Genre("Mature"), + Genre("Mecha"), + Genre("Medical"), + Genre("Music"), + Genre("Mystery"), + Genre("One shot"), + Genre("Psychological"), + Genre("Romance"), + Genre("School Life"), + Genre("Sci-fi"), + Genre("Seinen"), + Genre("Shoujo"), + Genre("Shojou Ai"), + Genre("Shounen"), + Genre("Shounen Ai"), + Genre("Slice of Life"), + Genre("Smut"), + Genre("Sports"), + Genre("Supernatural"), + Genre("Tragedy"), + Genre("Webtoon"), + Genre("Yaoi"), + Genre("Yuri") + ) +}