diff --git a/src/ja/nikkangecchan/build.gradle b/src/ja/nikkangecchan/build.gradle new file mode 100644 index 000000000..f78c8fc49 --- /dev/null +++ b/src/ja/nikkangecchan/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +ext { + appName = 'Tachiyomi: Nikkangecchan' + pkgNameSuffix = 'ja.nikkangecchan' + extClass = '.Nikkangecchan' + extVersionCode = 1 + libVersion = '1.2' +} + +apply from: "$rootDir/common.gradle" diff --git a/src/ja/nikkangecchan/res/mipmap-hdpi/ic_launcher.png b/src/ja/nikkangecchan/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..0f59927f1 Binary files /dev/null and b/src/ja/nikkangecchan/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/ja/nikkangecchan/res/mipmap-mdpi/ic_launcher.png b/src/ja/nikkangecchan/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..70e48fc27 Binary files /dev/null and b/src/ja/nikkangecchan/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/ja/nikkangecchan/res/mipmap-xhdpi/ic_launcher.png b/src/ja/nikkangecchan/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..63c6eb20e Binary files /dev/null and b/src/ja/nikkangecchan/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/ja/nikkangecchan/res/mipmap-xxhdpi/ic_launcher.png b/src/ja/nikkangecchan/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..5f9f02704 Binary files /dev/null and b/src/ja/nikkangecchan/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/ja/nikkangecchan/res/mipmap-xxxhdpi/ic_launcher.png b/src/ja/nikkangecchan/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..d7166dac5 Binary files /dev/null and b/src/ja/nikkangecchan/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/ja/nikkangecchan/res/web_hi_res_512.png b/src/ja/nikkangecchan/res/web_hi_res_512.png new file mode 100644 index 000000000..fe0e4d059 Binary files /dev/null and b/src/ja/nikkangecchan/res/web_hi_res_512.png differ diff --git a/src/ja/nikkangecchan/src/eu/kanade/tachiyomi/extension/ja/nikkangecchan/Nikkangecchan.kt b/src/ja/nikkangecchan/src/eu/kanade/tachiyomi/extension/ja/nikkangecchan/Nikkangecchan.kt new file mode 100644 index 000000000..003d254d7 --- /dev/null +++ b/src/ja/nikkangecchan/src/eu/kanade/tachiyomi/extension/ja/nikkangecchan/Nikkangecchan.kt @@ -0,0 +1,124 @@ +package eu.kanade.tachiyomi.extension.ja.nikkangecchan + +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import okhttp3.* +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable + +class Nikkangecchan : ParsedHttpSource() { + + override val name = "Nikkangecchan" + + override val baseUrl = "https://nikkangecchan.jp" + + override val lang = "ja" + + override val supportsLatest = false + + private val catalogHeaders = Headers.Builder() + .apply { + add("User-Agent", USER_AGENT) + add("Referer", baseUrl) + } + .build() + + override fun popularMangaRequest(page: Int): Request = GET(baseUrl, catalogHeaders) + + override fun popularMangaSelector(): String = ".contentInner > figure" + + override fun popularMangaFromElement(element: Element): SManga { + val imgBox = element.select(".imgBox").first() + val detailBox = element.select(".detailBox").last() + + return SManga.create().apply { + title = detailBox.select("h3").first().text() + thumbnail_url = baseUrl + imgBox.select("a > img").first().attr("src") + setUrlWithoutDomain(baseUrl + imgBox.select("a").first().attr("href")) + } + } + + override fun popularMangaNextPageSelector(): String? = null + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + return super.fetchSearchManga(page, query, filters) + .map { + val filtered = it.mangas.filter{ e -> e.title.contains(query, true) } + MangasPage(filtered, false) + } + } + + // Does not have search, use complete list (in popular) instead. + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request + = popularMangaRequest(page) + + override fun searchMangaSelector() = popularMangaSelector() + + override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element) + + override fun searchMangaNextPageSelector(): String? = null + + override fun mangaDetailsParse(document: Document): SManga { + val detailBox = document.select("#comicDetail .detailBox") + + return SManga.create().apply { + title = detailBox.select("h3").first().text() + author = detailBox.select(".author").first().text() + artist = detailBox.select(".author").first().text() + description = document.select(".description").first().text() + status = SManga.ONGOING + } + } + + override fun chapterListSelector(): String = ".episodeBox" + + override fun chapterListParse(response: Response): List + = super.chapterListParse(response).reversed() + + override fun chapterFromElement(element: Element): SChapter { + val episodePage = element.select(".episode-page").first() + val title = element.select("h4.episodeTitle").first().text() + val dataTitle = episodePage.attr("data-title").substringBefore("|").trim() + + return SChapter.create().apply { + name = "$title - $dataTitle" + chapter_number = element.select("h4.episodeTitle").first().text().toFloatOrNull() ?: 0f + scanlator = "Akita Publishing" + setUrlWithoutDomain(baseUrl + episodePage.attr("data-src").substringBeforeLast("/")) + } + } + + override fun fetchPageList(chapter: SChapter): Observable> { + return Observable.just(listOf(Page(0, chapter.url, "$baseUrl${chapter.url}/image"))) + } + + override fun imageUrlParse(document: Document) = "" + + override fun imageRequest(page: Page): Request { + val headers = Headers.Builder() + .apply { + add("User-Agent", USER_AGENT) + add("Referer", baseUrl + page.url.substringBeforeLast("/")) + } + + return GET(page.imageUrl!!, headers.build()) + } + + override fun latestUpdatesSelector() = "" + + override fun latestUpdatesRequest(page: Int): Request = throw Exception("This method should not be called!") + + override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("This method should not be called!") + + override fun latestUpdatesNextPageSelector(): String? = null + + override fun pageListRequest(chapter: SChapter): Request = throw Exception("This method should not be called!") + + override fun pageListParse(document: Document): List = throw Exception("This method should not be called!") + + companion object { + private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36" + } +}